Esempio n. 1
0
        /// <inheritdoc />
        public async Task TryToStartGameAsync(INetworkSigningAccount networkSigningAccount, ContractAddress gameContract, INetworkBlockHeader blockHeader, CancellationToken cancellationToken)
        {
            if (!this._contractInfo.Addresses.TryGetValue(key: networkSigningAccount.Network, out ContractAddress? gameManagerContractAddress))
            {
                // Contract not supported on the network
                return;
            }

            await using (IObjectLock <EthereumAddress>?gameManagerLock = await this._gameManagerLockManager.TakeLockAsync(gameManagerContractAddress))
            {
                if (gameManagerLock == null)
                {
                    // something else has the game manager locked so is probably doing something important with it
                    return;
                }

                bool canGameBeStarted = await this._gameRoundDataManager.CanStartAGameAsync(gameManagerContract: gameManagerContractAddress, (int)GameRoundParameters.InterGameDelay.TotalSeconds);

                if (!canGameBeStarted)
                {
                    // Has active games don't start a new one
                    return;
                }

                this._logger.LogInformation($"{blockHeader.Network.Name}: Starting new game of game contract {gameContract} using game manager: {gameManagerContractAddress}");

                await this._gameManager.StartGameAsync(account : networkSigningAccount, gameContract : gameContract, networkBlockHeader : blockHeader, cancellationToken : cancellationToken);
            }
        }
        private async Task EndGameRoundAsync(INetworkBlockHeader blockHeader, GameRound gameRound, CancellationToken cancellationToken)
        {
            await using (IObjectLock <GameRoundId>?gameRoundLock = await this._gameRoundLockManager.TakeLockAsync(gameRound.GameRoundId))
            {
                if (gameRoundLock == null)
                {
                    // something else has the game round locked
                    this._logger.LogInformation($"{gameRound.Network.Name}: could not get lock for {gameRound.GameRoundId}");

                    return;
                }

                try
                {
                    INetworkSigningAccount signingAccount = this._ethereumAccountManager.GetAccount(new NetworkAccount(network: gameRound.Network, address: gameRound.CreatedByAccount));

                    this._logger.LogInformation($"{gameRound.Network.Name}: End using game round: {gameRound.GameRoundId}");

                    await this._gameManager.EndGameAsync(account : signingAccount, gameRoundId : gameRound.GameRoundId, networkBlockHeader : blockHeader, cancellationToken : cancellationToken);
                }
                catch (Exception exception)
                {
                    this._logger.LogError(new EventId(exception.HResult), exception: exception, $"{gameRound.Network.Name}: Failed to end game {gameRound.GameRoundId}: {exception.Message}");
                }
            }
        }
        /// <inheritdoc />
        public async Task <bool> HandleAsync(EventMiningContext eventMiningContext, NetworkEventLog <TEvent> eventOutput)
        {
            try
            {
                this.Logger.LogInformation($"{eventOutput.Network.Name}: Event {this.GetType().Name} Game {eventOutput.Event.GameRoundId}");

                CancellationToken cancellationToken = CancellationToken.None;

                await using (IObjectLock <GameRoundId>?gameRoundLock = await this._gameRoundLockManager.TakeLockAsync(eventOutput.Event.GameRoundId))
                {
                    if (gameRoundLock == null)
                    {
                        this.Logger.LogWarning(
                            $"{eventOutput.Network.Name}: Event {this.GetType().Name} Game {eventOutput.Event.GameRoundId} - Could not acquire lock, for event in block {eventMiningContext.NetworkBlockHeader.Number.Value} ({eventMiningContext.NetworkBlockHeader.Hash}). Transaction will need retrying... TX: {eventMiningContext.TransactionHash}.");

                        return(false);
                    }

                    GameRound?gameRound = await this.GameRoundDataManager.GetAsync(eventOutput.Event.GameRoundId);

                    if (gameRound == null)
                    {
                        // Game doesn't exist
                        return(true);
                    }

                    if (gameRound.Status == GameRoundStatus.COMPLETED)
                    {
                        // Game already completed - don't need to do anything here.
                        return(true);
                    }

                    bool result = await this.ProcessEventUnderLockAsync(gameRound : gameRound,
                                                                        eventData : eventOutput.Event,
                                                                        transactionHash : eventMiningContext.TransactionHash,
                                                                        networkBlockHeader : eventMiningContext.NetworkBlockHeader,
                                                                        cancellationToken : cancellationToken);

                    if (!result)
                    {
                        this.Logger.LogWarning(
                            $"{eventOutput.Network.Name}: Event {this.GetType().Name} Game {eventOutput.Event.GameRoundId} - Event Handler Returned False: Incomplete, for event in block {eventMiningContext.NetworkBlockHeader.Number.Value} ({eventMiningContext.NetworkBlockHeader.Hash}). Transaction will need retrying... TX: {eventMiningContext.TransactionHash}.");
                    }

                    return(result);
                }
            }
            catch (Exception exception)
            {
                this.Logger.LogWarning(new EventId(exception.HResult),
                                       exception: exception,
                                       $"{eventOutput.Network.Name}: Event {this.GetType().Name} Game {eventOutput.Event.GameRoundId} - Event Handler failed to process, for event in block {eventMiningContext.NetworkBlockHeader.Number.Value} ({eventMiningContext.NetworkBlockHeader.Hash}). Transaction will need retrying... TX: {eventMiningContext.TransactionHash}.");

                return(false);
            }
        }
Esempio n. 4
0
        public Locked(
            T model,
            IEnumerable <LockedObject> lockables,
            ILockResolver resolver)
        {
            this.model = model;

            this.relatives = lockables;
            this.lockList  = new ThreadLocal <LinkedList <ILockStateInternal> >(() => new LinkedList <ILockStateInternal>(new Locked().Yield()));

            if (resolver == null)
            {
                this.@lock = new FastObjectLock();
            }
            else
            {
                this.@lock = new ResolveableObjectLock(model, resolver);
            }
        }
Esempio n. 5
0
        TResult ILockStateInternal.Unlock <T, TResult>(
            LinkedList <ILockStateInternal> lockList,
            IObjectLock @lock,
            T obj,
            Func <T, TResult> fn)
        {
            var state = new SharedUnlocked();

            lockList.AddLast(state);

            @lock.TakeSharedLock(state);

            var r = fn(obj);

            @lock.ExitSharedLock();

            lockList.RemoveLast();

            return(r);
        }
Esempio n. 6
0
        TResult ILockStateInternal.UnlockExclusive <TResult>(LinkedList <ILockStateInternal> lockList, IObjectLock @lock, Func <TResult> fn)
        {
            var state = new ExclusiveUnlocked();

            lockList.AddLast(state);

            @lock.TakeExclusiveLock(state);

            var r = fn();

            @lock.ExitExclusiveLock();

            lockList.RemoveLast();

            return(r);
        }
Esempio n. 7
0
 TResult ILockStateInternal.UnlockUpgradeable <T, TResult>(LinkedList <ILockStateInternal> lockList, IObjectLock @lock, T obj, Func <T, TResult> fn)
 {
     return(fn(obj));
 }
Esempio n. 8
0
 TResult ILockStateInternal.Unlock <TResult>(LinkedList <ILockStateInternal> lockList, IObjectLock @lock, Func <TResult> fn)
 {
     return(fn());
 }
Esempio n. 9
0
        TResult ILockStateInternal.UnlockExclusive <T, TResult>(LinkedList <ILockStateInternal> lockList, IObjectLock @lock, T obj, Func <T, TResult> fn)
        {
            // Will throw LockRecursionException
            @lock.TakeExclusiveLock(new ExclusiveUnlocked());

            return(fn(obj));
        }