public void Start(Func <Task> task, TimeSpan delay) { if (task == null) { throw new ArgumentNullException(nameof(task)); } #pragma warning disable 4014 // Fire-and-forget Task.Factory.StartNew(async() => { await _delayer.Delay(delay).ConfigureAwait(false); await task().ConfigureAwait(false); }); #pragma warning restore 4014 }
private bool CreateChannel(CancellationToken cancellationToken) { _grpcWrapper.Shutdown(); var attemptId = 0; LogMessage(LogLevel.Finest, $"Creating gRPC channel to endpoint {EndpointHost}:{EndpointPort}. (attempt {attemptId})"); while (!cancellationToken.IsCancellationRequested && IsServiceEnabled) { try { var createdChannel = false; using (_agentTimerService.StartNew(_timerEventNameForChannel)) { createdChannel = _grpcWrapper.CreateChannel(EndpointHost, EndpointPort, EndpointSsl, MetadataHeaders, TimeoutConnectMs, cancellationToken); } if (createdChannel) { LogMessage(LogLevel.Finest, $"gRPC channel to endpoint {EndpointHost}:{EndpointPort} connected."); return(true); } if (cancellationToken.IsCancellationRequested) { break; } LogMessage(LogLevel.Debug, $"Timeout creating gRPC channel at endpoint {EndpointHost}:{EndpointPort}. (attempt {attemptId}, timeout {TimeoutConnectMs}ms)"); } catch (Exception ex) { LogMessage(LogLevel.Debug, $"Error creating gRPC channel to endpoint {EndpointHost}:{EndpointPort}. (attempt {attemptId})", ex); RecordResponseError(); var grpcWrapperEx = ex as GrpcWrapperException; if (grpcWrapperEx != null && !string.IsNullOrWhiteSpace(grpcWrapperEx.Status)) { RecordGrpcError(grpcWrapperEx.Status); if (grpcWrapperEx.Status == UnimplementedStatus) { LogMessage(LogLevel.Error, $"The gRPC endpoint defined at {EndpointHost}:{EndpointPort} is not available and no reconnection attempts will be made."); Shutdown(false); return(false); } if (grpcWrapperEx.Status == OkStatus) { //Getting the OK status back indicates that the channel was created successfully, but the test stream //needed to be rebalanced to another handler. Since the test stream is only used to ensure that the //channel is valid we can just return true here. LogMessage(LogLevel.Finest, $"gRPC channel to endpoint {EndpointHost}:{EndpointPort} connected."); return(true); } } } var delayIdx = Math.Min(attemptId, _backoffDelaySequenceConnectMs.Length - 1); var delayPeriodMs = _backoffDelaySequenceConnectMs[delayIdx]; LogMessage(LogLevel.Finest, $"Backoff for {delayPeriodMs}ms before attempting to reconnect."); _delayer.Delay(delayPeriodMs, cancellationToken); attemptId++; } return(false); }