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
        }
示例#2
0
        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);
        }