/// <inheritdoc /> public override async Task <bool> OnExecute() { if (Runner.GlobalState.ReorgMode == true) { // null the store tip so the document count will be taken form disk Runner.GlobalState.StoreTip = null; // rewind the data in store Runner.GlobalState.StoreTip = await syncOperations.RewindToBestChain(syncConnection); Runner.GlobalState.PullingTip = null; Queue.Clear(); Runner.GlobalState.ReorgMode = false; return(false); } if (Runner.GlobalState.IndexMode) { return(false); } if (!TryDequeue(out StorageBatch batch)) { return(await Task.FromResult(false)); } ValidateBatch(batch); watch.Restart(); Runner.GlobalState.StoreTip = storageOperations.PushStorageBatch(batch); watch.Stop(); if (Runner.GlobalState.StoreTip == null) { throw new ApplicationException("Store tip was not persisted"); } long totalBlocks = batch.BlockTable.Count; // insertStats.Sum((tuple => tuple.count)); double totalSeconds = watch.Elapsed.TotalSeconds; // insertStats.Sum((tuple => tuple.seconds)); double blocksPerSecond = totalBlocks / totalSeconds; double secondsPerBlock = totalSeconds / totalBlocks; log.LogInformation($"Store - blocks={batch.BlockTable.Count}, outputs={batch.OutputTable.Count}, inputs={batch.InputTable.Count}, trx={batch.TransactionBlockTable.Count}, total Size = {((decimal)batch.TotalSize / 1000000):0.00}mb, tip={Runner.GlobalState.StoreTip.BlockIndex}, Seconds = {watch.Elapsed.TotalSeconds}, inserts = {blocksPerSecond:0.00}b/s ({secondsPerBlock:0.00}s/b)"); foreach (BlockTable mapBlocksValue in batch.BlockTable.Values) { syncConnection.RecentItems.Add((DateTime.UtcNow, TimeSpan.FromSeconds(blocksPerSecond), mapBlocksValue.BlockSize)); } var notifications = new AddressNotifications { Addresses = new List <string>() }; // count.Items.Where(ad => ad.Addresses != null).SelectMany(s => s.Addresses).Distinct().ToList() }; Runner.Get <Notifier>().Enqueue(notifications); return(await Task.FromResult(true)); }
public override async Task OnExecute() { IBlockchainClient client = clientFactory.Create(connection); List <string> allIndexes = mongoData.GetBlockIndexIndexes(); if (allIndexes.Count == BlockIndexer.ExpectedNumberOfIndexes) { Runner.GlobalState.IndexModeCompleted = true; } Runner.GlobalState.PullingTip = null; Runner.GlobalState.StoreTip = null; Runner.GlobalState.StoreTip = await syncOperations.RewindToLastCompletedBlockAsync(); if (Runner.GlobalState.StoreTip == null) { // No blocks in store start from zero // push the genesis block to store int start = 0; string genesisHash = await client.GetblockHashAsync(start); log.LogInformation($"Processing genesis hash = {genesisHash}"); BlockInfo genesisBlock = await client.GetBlockAsync(genesisHash); SyncBlockTransactionsOperation block = syncOperations.FetchFullBlock(connection, genesisBlock); StorageBatch genesisBatch = new StorageBatch(); storageOperations.AddToStorageBatch(genesisBatch, block); Runner.GlobalState.StoreTip = storageOperations.PushStorageBatch(genesisBatch); } BlockInfo fetchedBlock = await client.GetBlockAsync(Runner.GlobalState.StoreTip.BlockHash); if (fetchedBlock == null) { // check if the fullnode is ahead of the indexer height int fullnodeTipHeight = client.GetBlockCount(); if (fullnodeTipHeight < Runner.GlobalState.StoreTip.BlockIndex) { throw new ApplicationException($"Full node at height {fullnodeTipHeight} which is behind the Indexer at height {Runner.GlobalState.StoreTip.BlockIndex}"); } // reorg happend while indexer was offline rewind the indexer database Runner.GlobalState.PullingTip = null; Runner.GlobalState.StoreTip = null; Runner.GlobalState.StoreTip = await syncOperations.RewindToBestChain(connection); } // update the chains tip Runner.GlobalState.ChainTipHeight = syncOperations.GetBlockCount(client); }