private async Task Run(ulong blockNumber, CancellationToken stoppingToken)
        {
            void OnHealthCheck()
            {
                stoppingToken.ThrowIfCancellationRequested();
                _application.Dispose();
            }

            try
            {
                _application?.HealthCheck(TimeSpan.FromMinutes(1), OnHealthCheck);
                var blockHash = _application !.Application !
                                .GetBlockHash(new GetBlockHashParams()
                {
                    BlockNumber = blockNumber
                }).Hash;
                _application.HealthCheck(TimeSpan.FromMinutes(1), OnHealthCheck);
                var block = _application.Application.GetBlock(new GetBlockParams()
                {
                    BlockHash = blockHash
                });
                _application.HealthCheck(TimeSpan.FromMinutes(1), OnHealthCheck);
                var eventsString =
                    _application.Application.StorageApi.GetStorage("System", "Events",
                                                                   new GetBlockHashParams()
                {
                    BlockNumber = blockNumber
                });
                _application.CancelHealthCheck();

                var eventsList =
                    _application.Application.Serializer.Deserialize <EventList>(eventsString.HexToByteArray());
                var extrinsics = block.Block.Extrinsic
                                 .Select(e => e !.HexToByteArray())
                                 .Select(e => _application.Application.Serializer.DeserializeAssertReadAll <DeserializedExtrinsic>(e))
                                 .Where((_, index) => eventsList.ExtrinsicSuccess((uint)index))
                                 .ToList();

                var actions = ProcessExtrinsics(extrinsics, blockNumber, stoppingToken).ToList();

                stoppingToken.ThrowIfCancellationRequested();
                await SaveToDatabase(blockNumber, stoppingToken, actions);
            }
            catch (JrpcErrorException ex) when(ex.Code == -32603)
            {
                await SaveToDatabase(blockNumber, stoppingToken, Array.Empty <ExtrinsicHandler>());
            }
        }
Пример #2
0
        public static Task CallSubstrate(this BackgroundService service, ILogger logger, PublicKey contractKey, string nodeEndpoint, Address from, byte[] privateKey, Func <IApplication, IExtrinsicCall> callGenerator)
        {
            var completionSource = new TaskCompletionSource();

            Task.Run(async() =>
            {
                SafeApplication application = SafeApplication.CreateApplication(
                    ex =>
                {
                    logger.LogError(ex, "{ServiceName} substrate api failed", service.GetType().FullName);
                    Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(ex);
                }, logger, contractKey);
                try
                {
                    application.Application.Connect(nodeEndpoint);
                    var call = callGenerator(application.Application !);
                    application.HealthCheck(TimeSpan.FromMinutes(10), () =>
                    {
                        Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(new TimeoutException());
                        application.Dispose();
                    });
                    var result =
                        await application.Application.SignWaitRetryOnLowPriority(from,
                                                                                 privateKey, call);
                    application.CancelHealthCheck();
                    result.Switch(_ =>
                    {
                        Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetResult();
                    }, fail =>
                    {
                        var error = fail.ErrorMessage(application.Application);
                        logger.LogError("Failed to call substrate, {ErrorText}", error);
                        Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(new ApplicationException(error));
                    });
                }
                catch (Exception ex)
                {
                    Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(ex);
                }
                finally
                {
                    application.Dispose();
                }
            });
            return(completionSource.Task);
        }