Esempio n. 1
0
        public async Task DisconnectAsync(bool gracefulDisconnect)
        {
            IsConnected = false;
            IsShutdown  = true;

            // send disconnect message if the peer is still connected and the connection
            // is stable.
            if (gracefulDisconnect && IsReady)
            {
                GrpcRequest request = new GrpcRequest {
                    ErrorMessage = "Error while sending disconnect."
                };

                try
                {
                    await RequestAsync(_client, c => c.DisconnectAsync(new DisconnectReason {
                        Why = DisconnectReason.Types.Reason.Shutdown
                    }), request);
                }
                catch (NetworkException)
                {
                    // swallow the exception, we don't care because we're disconnecting.
                }
            }

            try
            {
                await _channel.ShutdownAsync();
            }
            catch (InvalidOperationException)
            {
                // if channel already shutdown
            }
        }
Esempio n. 2
0
        public async Task <List <BlockWithTransactions> > GetBlocksAsync(Hash firstHash, int count)
        {
            var blockRequest = new BlocksRequest {
                PreviousBlockHash = firstHash, Count = count
            };
            var blockInfo = $"{{ first: {firstHash}, count: {count} }}";

            GrpcRequest request = new GrpcRequest
            {
                ErrorMessage = $"Get blocks for {blockInfo} failed.",
                MetricName   = nameof(MetricNames.GetBlocks),
                MetricInfo   = $"Get blocks for {blockInfo}"
            };

            Metadata data = new Metadata
            {
                { GrpcConstants.TimeoutMetadataKey, BlocksRequestTimeout.ToString() },
                { GrpcConstants.SessionIdMetadataKey, OutboundSessionId }
            };

            var list = await RequestAsync(() => _client.RequestBlocksAsync(blockRequest, data), request);

            if (list == null)
            {
                return(new List <BlockWithTransactions>());
            }

            return(list.Blocks.ToList());
        }
Esempio n. 3
0
        public async Task <Handshake> DoHandshakeAsync(Handshake handshake)
        {
            GrpcRequest request = new GrpcRequest {
                ErrorMessage = "Error while updating handshake."
            };

            Metadata data = new Metadata {
                { GrpcConstants.TimeoutMetadataKey, UpdateHandshakeTimeout.ToString() }
            };

            var handshakeReply = await RequestAsync(_client,
                                                    c => c.DoHandshakeAsync(new HandshakeRequest {
                Handshake = handshake
            }, data), request);

            LastReceivedHandshake = handshakeReply?.Handshake;

            // Do some pre-checks that represent the minimum acceptable for the peers state.
            if (LastReceivedHandshake?.HandshakeData?.BestChainHead == null)
            {
                IsConnected = false;
                return(null);
            }

            UpdateLastReceivedHandshake(LastReceivedHandshake);

            return(LastReceivedHandshake);
        }
Esempio n. 4
0
        public Task <NodeList> GetNodesAsync(int count = NetworkConstants.DefaultDiscoveryMaxNodesToRequest)
        {
            GrpcRequest request = new GrpcRequest {
                ErrorMessage = "Request nodes failed."
            };
            Metadata data = new Metadata {
                { GrpcConstants.TimeoutMetadataKey, GetNodesTimeout.ToString() }
            };

            return(RequestAsync(_client, c => c.GetNodesAsync(new NodesRequest {
                MaxCount = count
            }, data), request));
        }
Esempio n. 5
0
        public async Task ConfirmHandshakeAsync()
        {
            var request = new GrpcRequest {
                ErrorMessage = "Error while sending confirm handshake."
            };

            Metadata data = new Metadata
            {
                { GrpcConstants.TimeoutMetadataKey, UpdateHandshakeTimeout.ToString() },
                { GrpcConstants.SessionIdMetadataKey, OutboundSessionId }
            };

            await RequestAsync(() => _client.ConfirmHandshakeAsync(new ConfirmHandshakeRequest(), data), request);
        }
Esempio n. 6
0
        public async Task CheckHealthAsync()
        {
            GrpcRequest request = new GrpcRequest {
                ErrorMessage = $"Health check failed."
            };

            Metadata data = new Metadata
            {
                { GrpcConstants.TimeoutMetadataKey, HealthCheckTimeout.ToString() },
                { GrpcConstants.SessionIdMetadataKey, OutboundSessionId }
            };

            await RequestAsync(() => _client.CheckHealthAsync(new HealthCheckRequest(), data), request);
        }
Esempio n. 7
0
        public async Task PingAsync()
        {
            GrpcRequest request = new GrpcRequest {
                ErrorMessage = $"Ping failed."
            };

            Metadata data = new Metadata
            {
                { GrpcConstants.TimeoutMetadataKey, PingTimeout.ToString() },
                { GrpcConstants.SessionIdMetadataKey, OutboundSessionId }
            };

            await RequestAsync(() => _client.PingAsync(new PingRequest(), data), request);
        }
Esempio n. 8
0
        public async Task DisconnectAsync(bool gracefulDisconnect)
        {
            IsConnected = false;
            IsShutdown  = true;

            // we complete but no need to await the jobs
            _sendAnnouncementJobs.Complete();
            _sendBlockJobs.Complete();
            _sendTransactionJobs.Complete();

            _announcementStreamCall?.Dispose();
            _transactionStreamCall?.Dispose();
            _blockStreamCall?.Dispose();

            // send disconnect message if the peer is still connected and the connection
            // is stable.
            if (gracefulDisconnect && (_channel.State == ChannelState.Idle || _channel.State == ChannelState.Ready))
            {
                GrpcRequest request = new GrpcRequest {
                    ErrorMessage = "Error while sending disconnect."
                };

                try
                {
                    Metadata metadata = new Metadata {
                        { GrpcConstants.SessionIdMetadataKey, OutboundSessionId }
                    };

                    await RequestAsync(
                        () => _client.DisconnectAsync(new DisconnectReason
                    {
                        Why = DisconnectReason.Types.Reason.Shutdown
                    }, metadata), request);
                }
                catch (NetworkException)
                {
                    // swallow the exception, we don't care because we're disconnecting.
                }
            }

            try
            {
                await _channel.ShutdownAsync();
            }
            catch (InvalidOperationException)
            {
                // if channel already shutdown
            }
        }
Esempio n. 9
0
        private void RecordMetric(GrpcRequest grpcRequest, Timestamp requestStartTime, long elapsedMilliseconds)
        {
            var metrics = _recentRequestsRoundtripTimes[grpcRequest.MetricName];

            while (metrics.Count >= MaxMetricsPerMethod)
            {
                metrics.TryDequeue(out _);
            }

            metrics.Enqueue(new RequestMetric
            {
                Info          = grpcRequest.MetricInfo,
                RequestTime   = requestStartTime,
                MethodName    = grpcRequest.MetricName,
                RoundTripTime = elapsedMilliseconds
            });
        }
Esempio n. 10
0
        public async Task <BlockWithTransactions> GetBlockByHashAsync(Hash hash)
        {
            var blockRequest = new BlockRequest {
                Hash = hash
            };

            GrpcRequest request = new GrpcRequest
            {
                ErrorMessage = $"Block request for {hash} failed.",
                MetricName   = nameof(MetricNames.GetBlock),
                MetricInfo   = $"Block request for {hash}"
            };

            Metadata data = new Metadata {
                { GrpcConstants.TimeoutMetadataKey, BlockRequestTimeout.ToString() }
            };

            var blockReply = await RequestAsync(_client, c => c.RequestBlockAsync(blockRequest, data), request);

            return(blockReply?.Block);
        }
Esempio n. 11
0
        private async Task <TResp> RequestAsync <TResp>(Func <AsyncUnaryCall <TResp> > func, GrpcRequest requestParams)
        {
            var metricsName      = requestParams.MetricName;
            var timeRequest      = !string.IsNullOrEmpty(metricsName);
            var requestStartTime = TimestampHelper.GetUtcNow();

            Stopwatch requestTimer = null;

            if (timeRequest)
            {
                requestTimer = Stopwatch.StartNew();
            }

            try
            {
                var response = await func();

                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }

                return(response);
            }
            catch (ObjectDisposedException ex)
            {
                throw new NetworkException("Peer is closed", ex, NetworkExceptionType.Unrecoverable);
            }
            catch (AggregateException ex)
            {
                throw HandleRpcException(ex.InnerException as RpcException, requestParams.ErrorMessage);
            }
            finally
            {
                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }
            }
        }
Esempio n. 12
0
        // todo consider removing client from the lambda as it is not used. It can be capture by the func.
        private async Task <TResp> RequestAsync <TResp>(PeerService.PeerServiceClient client,
                                                        Func <PeerService.PeerServiceClient, AsyncUnaryCall <TResp> > func, GrpcRequest requestParams)
        {
            var  metricsName      = requestParams.MetricName;
            bool timeRequest      = !string.IsNullOrEmpty(metricsName);
            var  requestStartTime = TimestampHelper.GetUtcNow();

            Stopwatch requestTimer = null;

            if (timeRequest)
            {
                requestTimer = Stopwatch.StartNew();
            }

            try
            {
                var response = await func(client);

                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }

                return(response);
            }
            catch (AggregateException e)
            {
                HandleFailure(e.Flatten(), requestParams.ErrorMessage);
            }
            finally
            {
                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }
            }

            return(default(TResp));
        }
Esempio n. 13
0
        private async Task <TResp> RequestAsync <TResp>(Func <AsyncUnaryCall <TResp> > func, GrpcRequest requestParams)
        {
            var metricsName      = requestParams.MetricName;
            var timeRequest      = !string.IsNullOrEmpty(metricsName);
            var requestStartTime = TimestampHelper.GetUtcNow();

            Stopwatch requestTimer = null;

            if (timeRequest)
            {
                requestTimer = Stopwatch.StartNew();
            }

            try
            {
                var response = await func();

                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }

                return(response);
            }
            catch (AggregateException ex)
            {
                throw CreateNetworkException(ex.Flatten(), requestParams.ErrorMessage);
            }
            finally
            {
                if (timeRequest)
                {
                    requestTimer.Stop();
                    RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds);
                }
            }
        }