public Task <TResult> UseAsync <TResult>(OperationContext context, MachineLocation key, Func <TService, Task <TResult> > operation) { if (_localClient?.Location.Equals(key) == true) { return(operation(_localClient.Client)); } return(_connectionAccessor.UseAsync(context, key, connectionHandle => { var client = _clientTable.GetValue(connectionHandle, static h => h.Channel.CreateGrpcService <TService>(MetadataServiceSerializer.ClientFactory)); return operation(client); })); }
private async Task <TResult> ExecuteAsync <TResult>( OperationContext originalContext, Func <OperationContext, CallOptions, IGlobalCacheService, Task <TResult> > executeAsync, Func <TResult, string?> extraEndMessage, string?extraStartMessage = null, [CallerMemberName] string caller = null !) where TResult : ResultBase { var attempt = -1; using var contextWithShutdown = TrackShutdown(originalContext); var context = contextWithShutdown.Context; var callerAttempt = $"{caller}_Attempt"; return(await context.PerformOperationWithTimeoutAsync( Tracer, context => { var callOptions = new CallOptions( headers: new Metadata() { MetadataServiceSerializer.CreateContextIdHeaderEntry(context.TracingContext.TraceId) }, deadline: _clock.UtcNow + _configuration.OperationTimeout, cancellationToken: context.Token); return _retryPolicy.ExecuteAsync(async() => { await Task.Yield(); attempt++; var stopwatch = StopwatchSlim.Start(); var clientCreationTime = TimeSpan.Zero; var result = await context.PerformOperationAsync(Tracer, () => { return _serviceClientFactory.UseAsync(context, service => { clientCreationTime = stopwatch.Elapsed; return executeAsync(context, callOptions, service); }); }, extraStartMessage: extraStartMessage, extraEndMessage: r => $"Attempt=[{attempt}] ClientCreationTimeMs=[{clientCreationTime.TotalMilliseconds}] {extraEndMessage(r)}", caller: callerAttempt, traceErrorsOnly: true); await Task.Yield(); // Because we capture exceptions inside the PerformOperation, we need to make sure that they // get propagated for the retry policy to kick in. if (result.Exception != null) { result.ReThrow(); } return result; }, context.Token); }, caller : caller, traceErrorsOnly : true, extraStartMessage : extraStartMessage, extraEndMessage : r => $"Attempts=[{attempt + 1}] {extraEndMessage(r)}", timeout : _configuration.OperationTimeout)); }
public async Task <TResult> UseAsync <TResult>(OperationContext context, Func <T, Task <TResult> > operation) { var masterMachineLocation = await GetClientAsync(context); return(await _clientAccessor.UseAsync(context, masterMachineLocation, operation)); }