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 } }
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()); }
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); }
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)); }
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); }
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); }
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); }
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 } }
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 }); }
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); }
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); } } }
// 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)); }
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); } } }