/// <summary>
        /// Notifies about blocks, starting from block with hash passed as parameter.
        /// </summary>
        /// <param name="startHash">The hash of the block from which to start notifying</param>
        /// <param name="cancellationToken">A cancellation token</param>
        public virtual void Notify(uint256 startHash, CancellationToken cancellationToken)
        {
            // sets the location of the puller to the latest hash that was broadcasted
            this.Puller.SetLocation(this.Chain.GetBlock(startHash));

            AsyncLoop.Run("block notifier", token =>
            {
                // send notifications for all the following blocks
                while (true)
                {
                    var block = this.Puller.NextBlock(token);

                    if (block != null)
                    {
                        this.signals.Blocks.Broadcast(block);
                    }
                    else
                    {
                        break;
                    }
                }

                return(Task.CompletedTask);
            }, cancellationToken);
        }
        /// <inheritdoc />
        public IAsyncLoop CreateAndRunAsyncLoop <T>(string name, Func <CancellationToken, Task> loop, CancellationToken cancellation, TimeSpan?repeatEvery = null, TimeSpan?startAfter = null)
        {
            Guard.NotEmpty(name, nameof(name));
            Guard.NotNull(loop, nameof(loop));
            Guard.NotNull(cancellation, nameof(cancellation));

            // instantiate the loop
            IAsyncLoop loopInstance = new AsyncLoop(name, this.logger, loop);

            Task loopTask;

            lock (this.lockAsyncLoops)
            {
                this.asyncLoops.Add(loopInstance, new AsyncTaskInfo(name));
            }

            loopTask = loopInstance.Run(cancellation, repeatEvery ?? TimeSpan.FromMilliseconds(DefaultLoopRepeatInterval), startAfter).RunningTask;

            // task will continue with onAsyncDelegateUnhandledException if @delegate had unhandled exceptions
            loopTask.ContinueWith(this.onAsyncLoopUnhandledException, loopInstance, TaskContinuationOptions.OnlyOnFaulted);

            // task will continue with onAsyncDelegateCompleted if @delegate completed or was canceled
            loopTask.ContinueWith(this.onAsyncLoopCompleted, loopInstance, TaskContinuationOptions.NotOnFaulted);

            return(loopInstance);
        }
        public void RelayWorker(CancellationToken cancellationToken)
        {
            AsyncLoop.Run("BlockStore.RelayWorker", async token =>
            {
                var blocks = this.blockHashesToAnnounce.Keys.ToList();

                if (!blocks.Any())
                {
                    return;
                }

                uint256 outer;
                foreach (var blockHash in blocks)
                {
                    this.blockHashesToAnnounce.TryRemove(blockHash, out outer);
                }

                var nodes = this.connection.ConnectedNodes;
                if (!nodes.Any())
                {
                    return;
                }

                // announce the blocks on each nodes behaviour
                var behaviours = nodes.Select(s => s.Behavior <BlockStoreBehavior>());
                foreach (var behaviour in behaviours)
                {
                    await behaviour.AnnounceBlocks(blocks).ConfigureAwait(false);
                }
            },
                          cancellationToken,
                          repeatEvery: TimeSpans.Second,
                          startAfter: TimeSpans.FiveSeconds);
        }
        public async Task RunLogsStartAndStopAsync()
        {
            var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token =>
            {
                await this.DoTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(330)).RunningTask;
        }
        public async Task RunWithoutDelayRunsTaskUntilCancelled()
        {
            var asyncLoop = new AsyncLoop("TestLoop", async token =>
            {
                await DoTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(90).Token, TimeSpan.FromMilliseconds(33));

            Assert.Equal(3, this.iterationCount);
        }
        public async Task RunWithDelayRunsTaskUntilCancelledAsync()
        {
            var asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token =>
            {
                await this.DoTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(300), TimeSpan.FromMilliseconds(100)).RunningTask;

            Assert.True(this.iterationCount > 1);
        }
Exemplo n.º 7
0
        public void RunWithDelayRunsTaskUntilCancelled()
        {
            var asyncLoop = new AsyncLoop("TestLoop", async token =>
            {
                await DoTask(token);
            });

            asyncLoop.Run(new CancellationTokenSource(100).Token, TimeSpan.FromMilliseconds(33), TimeSpan.FromMilliseconds(40)).Wait();

            Assert.Equal(2, iterationCount);
        }
        public async Task RunWithoutDelayRunsTaskUntilCancelledAsync()
        {
            var asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token =>
            {
                this.iterationCount++;
                await Task.CompletedTask;
            });

            await asyncLoop.Run(new CancellationTokenSource(900).Token, TimeSpan.FromMilliseconds(330)).RunningTask;

            Assert.True(this.iterationCount > 1);
        }
Exemplo n.º 9
0
        public void RunLogsStartAndStop()
        {
            var asyncLoop = new AsyncLoop("TestLoop", async token =>
            {
                await DoTask(token);
            });

            asyncLoop.Run(new CancellationTokenSource(100).Token, TimeSpan.FromMilliseconds(33)).Wait();

            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting");
            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping");
        }
        public async Task RunLogsStartAndStop()
        {
            var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token =>
            {
                await this.DoTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(330)).RunningTask;

            this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop starting");
            this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop stopping");
        }
 public void Loop(CancellationToken cancellationToken)
 {
     // A loop that writes pending blocks to store
     // or downloads missing blocks then writing to store
     AsyncLoop.Run("BlockStoreLoop.DownloadBlocks", async token =>
     {
         await DownloadAndStoreBlocks(cancellationToken);
     },
                   cancellationToken,
                   repeatEvery: TimeSpans.Second,
                   startAfter: TimeSpans.FiveSeconds);
 }
Exemplo n.º 12
0
        public async Task RunOperationCanceledExceptionThrownBeforeCancellationTokenIsCancelledLogsExceptionAsync()
        {
            var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token =>
            {
                await this.DoOperationCanceledExceptionTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(800).Token, TimeSpan.FromMilliseconds(300)).RunningTask;

            this.AssertLog <OperationCanceledException>(this.FullNodeLogger, LogLevel.Critical, "This should not block the task from continuing.", "TestLoop threw an unhandled exception");
            Assert.Equal(1, this.iterationCount);
        }
Exemplo n.º 13
0
        public async Task RunWithCancellationTokenRunsUntilExceptionOccursAsync()
        {
            var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token =>
            {
                await this.DoExceptionalTask(token);
            });

            await asyncLoop.Run(new CancellationTokenSource(1500).Token, TimeSpan.FromMilliseconds(330)).RunningTask;

            this.AssertLog <InvalidOperationException>(this.FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception");
            Assert.Equal(3, this.iterationCount);
        }
Exemplo n.º 14
0
        public void RunWithCancellationTokenRunsUntilExceptionOccurs()
        {
            var asyncLoop = new AsyncLoop("TestLoop", async token =>
            {
                await DoExceptionalTask(token);
            });

            asyncLoop.Run(new CancellationTokenSource(150).Token, TimeSpan.FromMilliseconds(33)).Wait();

            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting");
            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping");
            AssertLog <InvalidOperationException>(FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception");
            Assert.Equal(3, iterationCount);
        }
Exemplo n.º 15
0
        public async Task RunWithoutCancellationTokenRunsUntilExceptionOccurs()
        {
            var asyncLoop = new AsyncLoop("TestLoop", this.FullNodeLogger.Object, async token =>
            {
                await this.DoExceptionalTask(token);
            });

            await asyncLoop.Run(TimeSpan.FromMilliseconds(330));

            this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop starting");
            this.AssertLog(this.FullNodeLogger, LogLevel.Information, "TestLoop stopping");
            this.AssertLog <InvalidOperationException>(this.FullNodeLogger, LogLevel.Critical, "Cannot run more than 3 times.", "TestLoop threw an unhandled exception");
            Assert.Equal(3, this.iterationCount);
        }
Exemplo n.º 16
0
        public void RunOperationCanceledExceptionThrownBeforeCancellationTokenIsCancelledLogsException()
        {
            var asyncLoop = new AsyncLoop("TestLoop", async token =>
            {
                await DoOperationCanceledExceptionTask(token);
            });

            asyncLoop.Run(new CancellationTokenSource(80).Token, TimeSpan.FromMilliseconds(33)).Wait();

            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop starting");
            AssertLog(FullNodeLogger, LogLevel.Information, "TestLoop stopping");
            AssertLog <OperationCanceledException>(FullNodeLogger, LogLevel.Critical, "This should not block the task from continuing.", "TestLoop threw an unhandled exception");
            Assert.Equal(1, iterationCount);
        }
Exemplo n.º 17
0
        public Task Mine(List <TrxStakingInfo> stakeTxes)
        {
            if (this.mining != null)
            {
                return(this.mining);                // already mining
            }
            this.mining = AsyncLoop.Run("PosMining.Mine", token =>
            {
                this.GenerateBlocks(stakeTxes);
                return(Task.CompletedTask);
            },
                                        cancellationProvider.Cancellation.Token,
                                        repeatEvery: TimeSpan.FromMilliseconds(this.minerSleep),
                                        startAfter: TimeSpans.TenSeconds);

            return(this.mining);
        }
        public void Stake_StakingLoopNotStarted_StartsStakingLoop()
        {
            var asyncLoop = new AsyncLoop("PosMining.Stake2", this.FullNodeLogger.Object, token => { return(Task.CompletedTask); });

            this.asyncLoopFactory.Setup(a => a.Run("PosMining.Stake",
                                                   It.IsAny <Func <CancellationToken, Task> >(), It.IsAny <CancellationToken>(),
                                                   It.Is <TimeSpan>(t => t.Milliseconds == 500), TimeSpans.Second))
            .Returns(asyncLoop)
            .Verifiable();

            this.posMinting.Stake(new WalletSecret()
            {
                WalletName = "wallet1", WalletPassword = "******"
            });

            this.nodeLifetime.Verify();
            this.asyncLoopFactory.Verify();
        }
Exemplo n.º 19
0
        /// <inheritdoc />
        public Task WaitForChainDownloadAsync()
        {
            // make sure the chain is downloaded
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            return(AsyncLoop.Run("WalletFeature.DownloadChain", token =>
            {
                // wait until the chain is downloaded. We wait until a block is from an hour ago.
                if (this.chain.IsDownloaded())
                {
                    cancellationTokenSource.Cancel();
                }

                return Task.CompletedTask;
            },
                                 cancellationTokenSource.Token,
                                 repeatEvery: TimeSpans.FiveSeconds));
        }
Exemplo n.º 20
0
        public Task Mine(Script reserveScript)
        {
            if (this.mining != null)
            {
                return(this.mining);                // already mining
            }
            this.mining = AsyncLoop.Run("PowMining.Mine", token =>
            {
                this.GenerateBlocks(new ReserveScript {
                    reserveSfullNodecript = reserveScript
                }, int.MaxValue, int.MaxValue);
                this.mining = null;
                return(Task.CompletedTask);
            },
                                        cancellationProvider.Cancellation.Token,
                                        repeatEvery: TimeSpans.RunOnce,
                                        startAfter: TimeSpans.TenSeconds);

            return(this.mining);
        }
        /// <summary>
        /// Notifies about blocks, starting from block with hash passed as parameter.
        /// </summary>
        /// <param name="cancellationToken">A cancellation token</param>
        public virtual void Notify(CancellationToken cancellationToken)
        {
            AsyncLoop.Run("block notifier", token =>
            {
                // if the StartHash hasn't been set yet
                if (this.StartHash == null)
                {
                    return(Task.CompletedTask);
                }

                // make sure the chain has been downloaded
                ChainedBlock startBlock = this.Chain.GetBlock(this.StartHash);
                if (startBlock == null)
                {
                    return(Task.CompletedTask);
                }

                // sets the location of the puller to the latest hash that was broadcasted
                this.Puller.SetLocation(startBlock);

                // send notifications for all the following blocks
                while (!this.reSync)
                {
                    var block = this.Puller.NextBlock(token);

                    if (block != null)
                    {
                        // broadcast the block to the registered observers
                        this.signals.Blocks.Broadcast(block);
                    }
                    else
                    {
                        break;
                    }
                }

                this.reSync = false;

                return(Task.CompletedTask);
            }, cancellationToken);
        }
        public void Stake_StakingLoopThrowsConsensusErrorException_AddsErrorToRpcStakingInfoModel()
        {
            var asyncLoop = new AsyncLoop("PosMining.Stake2", this.FullNodeLogger.Object, token => { return(Task.CompletedTask); });

            this.asyncProvider.Setup(a => a.CreateAndRunAsyncLoop("PosMining.Stake",
                                                                  It.IsAny <Func <CancellationToken, Task> >(), It.IsAny <CancellationToken>(),
                                                                  It.Is <TimeSpan>(t => t.Milliseconds == 500), TimeSpans.Second))
            .Callback <string, Func <CancellationToken, Task>, CancellationToken, TimeSpan?, TimeSpan?>((name, func, token, repeat, start) =>
            {
                func(token);
            })
            .Returns(asyncLoop)
            .Verifiable();

            bool isSystemTimeOutOfSyncCalled = false;

            this.timeSyncBehaviorState.Setup(c => c.IsSystemTimeOutOfSync)
            .Returns(() =>
            {
                if (!isSystemTimeOutOfSyncCalled)
                {
                    isSystemTimeOutOfSyncCalled = true;
                    throw new ConsensusErrorException(new ConsensusError("15", "Consensus error."));
                }
                this.cancellationTokenSource.Cancel();
                throw new InvalidOperationException("End the loop");
            });

            this.posMinting.Stake(new List <WalletSecret>()
            {
                new WalletSecret()
                {
                    WalletName = "wallet1", WalletPassword = "******"
                }
            });
            asyncLoop.Run();

            GetStakingInfoModel model = this.posMinting.GetGetStakingInfoModel();

            Assert.Equal("Consensus error.", model.Errors);
        }
        private void RelayWorker(CancellationToken cancellationToken)
        {
            AsyncLoop.Run("MemoryPool.RelayWorker", async token =>
            {
                var nodes = this.connection.ConnectedNodes;
                if (!nodes.Any())
                {
                    return;
                }

                // announce the blocks on each nodes behaviour
                var behaviours = nodes.Select(s => s.Behavior <MempoolBehavior>());
                foreach (var behaviour in behaviours)
                {
                    await behaviour.SendTrickle().ConfigureAwait(false);
                }
            },
                          cancellationToken,
                          repeatEvery: TimeSpans.TenSeconds,
                          startAfter: TimeSpans.TenSeconds);
        }
Exemplo n.º 24
0
        public async Task AsyncLoopRepeatEveryIntervalCanBeChangedWhileRunningAsync()
        {
            int iterations = 0;

            IAsyncLoop asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, async token =>
            {
                iterations++;
            });

            Task loopRun = asyncLoop.Run(new CancellationTokenSource(1000).Token, TimeSpan.FromMilliseconds(300)).RunningTask;

            await Task.Delay(500);

            asyncLoop.RepeatEvery = TimeSpan.FromMilliseconds(100);

            // At this point there were 2 iterations, 600 ms passed.

            await loopRun;

            // Should be 6 but in some slow environments occasionally can be 5.
            Assert.True(iterations >= 5);
        }
Exemplo n.º 25
0
 /// <inheritdoc />
 public void SyncFrom(DateTime date)
 {
     // before we start syncing we need to make sure that the chain is at a certain level.
     // if the chain is behind the date from which we want to sync, we wait for it to catch up, and then we start syncing.
     // if the chain is already past the date we want to sync from, we don't wait, even though the chain might not be fully downloaded.
     if (this.chain.Tip.Header.BlockTime.LocalDateTime < date)
     {
         AsyncLoop.RunUntil("WalletFeature.DownloadChain", this.cancellationProvider.Cancellation.Token,
                            () => this.chain.Tip.Header.BlockTime.LocalDateTime >= date,
                            () => this.StartSync(this.chain.GetHeightAtTime(date)),
                            (ex) =>
         {
             // in case of an exception while waiting for the chain to be at a certain height, we just cut our losses and
             // sync from the current height.
             this.logger.LogError($"Exception occurred while waiting for chain to download: {ex.Message}");
             this.StartSync(this.chain.Tip.Height);
         },
                            TimeSpans.FiveSeconds);
     }
     else
     {
         this.StartSync(this.chain.GetHeightAtTime(date));
     }
 }
Exemplo n.º 26
0
 /// <inheritdoc />
 public void SyncFrom(int height)
 {
     // before we start syncing we need to make sure that the chain is at a certain level.
     // if the chain is behind the height from which we want to sync, we wait for it to catch up, and then we start syncing.
     // if the chain is already past the height we want to sync from, we don't wait, even though the chain might  not be fully downloaded.
     if (this.chain.Tip.Height < height)
     {
         AsyncLoop.RunUntil("WalletFeature.DownloadChain", this.nodeLifetime.ApplicationStopping,
                            () => this.chain.Tip.Height >= height,
                            () => this.StartSync(height),
                            (ex) =>
         {
             // in case of an exception while waiting for the chain to be at a certain height, we just cut our losses and
             // sync from the current height.
             this.logger.LogError($"Exception occurred while waiting for chain to download: {ex.Message}");
             this.StartSync(this.chain.Tip.Height);
         },
                            TimeSpans.FiveSeconds);
     }
     else
     {
         this.StartSync(height);
     }
 }
Exemplo n.º 27
0
        public async Task AsyncLoopRepeatEveryIntervalCanBeChangedWhileRunningAsync()
        {
            int iterations = 0;

            IAsyncLoop asyncLoop = null;

            asyncLoop = new AsyncLoop("TestLoop", NullLogger.Instance, token =>
            {
                iterations++;

                if (iterations == 2)
                {
                    asyncLoop.RepeatEvery = TimeSpan.FromMilliseconds(200);
                }

                return(Task.CompletedTask);
            });

            Task loopRun = asyncLoop.Run(new CancellationTokenSource(5000).Token, TimeSpan.FromMilliseconds(1000)).RunningTask;

            await loopRun;

            Assert.True(iterations >= 6);
        }
Exemplo n.º 28
0
 /// <summary>
 /// Runs game.
 /// </summary>
 public void Run()
 {
     if (this.flow.IsAtBegin)
     {
         /* spawn separate game loop thread */
         AsyncLoop loop = new AsyncLoop(this.Loop);
         loop.BeginInvoke(new AsyncCallback(this.Halt), loop);
     }
 }