private Task <TResult> ExecuteAsync <TResult>(OperationContext context, Func <IContentMetadataService, Task <TResult> > executeAsync, [CallerMemberName] string caller = null) where TResult : ResultBase { return(context.PerformOperationWithTimeoutAsync( Tracer, context => { var attempt = -1; return _retryPolicy.ExecuteAsync(async() => { attempt++; var result = await context.PerformOperationAsync(Tracer, async() => { var client = await _metadataServiceClientFactory.CreateClientAsync(context); return await executeAsync(client); }, extraEndMessage: _ => $"Attempt=[{attempt}]", caller: caller, traceErrorsOnly: true); // 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.Succeeded && result.HasException) { throw result.Exception; } return result; }, context.Token); }, caller: caller, traceErrorsOnly: true, timeout: _configuration.OperationTimeout)); }