public async Task UpdateUserAsync1( SailplayCredentials credentials, UpdateUser requestData, CancellationToken cancellationToken) { var tokenResult = await this.authorisationExecutor.GetAuthorizationTokenAsync( credentials: credentials, cancellationToken: cancellationToken); var apiResponse = await Policy.HandleResult(apiResult => apiResult.IsAuthorizationTokenError) .RetryAsync( retryCount: 1, onRetryAsync: async (_, _, _) => { tokenResult = await this.authorisationExecutor.RenewAuthorizationTokenAsync( credentials: credentials, cancellationToken: cancellationToken); }) .ExecuteAsync( async () => await tokenResult .Match( onSuccess: async token => { var request = HttpRequestMessageFactory .BuildPost(ApiPath.UsersUpdate); var tokenFormData = FormDataFactory .FromToken(token.Token); var storeDepartmentIdFormData = FormDataFactory .FromStoreDepartmentId(credentials.StoreDepartmentId); var keyValuePairs = new List>() { tokenFormData, storeDepartmentIdFormData, }; keyValuePairs.AddRange(FormDataFactory.FromUserId(requestData.UserId)); requestData.Phone .MatchSome(phone => keyValuePairs.Add(FormDataFactory.FromNewPhone(phone))); requestData.Email .MatchSome(email => keyValuePairs.Add(FormDataFactory.FromNewEmail(email))); requestData.FirstName .MatchSome(firstName => keyValuePairs.Add(FormDataFactory.FromFirstName(firstName))); requestData.MiddleName .MatchSome(middleName => keyValuePairs.Add(FormDataFactory.FromMiddleName(middleName))); requestData.LastName .MatchSome(lastName => keyValuePairs.Add(FormDataFactory.FromLastName(lastName))); requestData.BirthDate .MatchSome(birthDate => keyValuePairs.Add(FormDataFactory.FromBirthDate(birthDate))); requestData.Sex .MatchSome(sex => keyValuePairs.Add(FormDataFactory.FromSex(sex))); requestData.RegisterDate .MatchSome( registerDate => keyValuePairs.Add(FormDataFactory.FromRegisterDate(registerDate))); request.Content = new FormUrlEncodedContent(keyValuePairs); return await this .requestExecutor.ExecuteApiRequestAsync( request: request, cancellationToken: cancellationToken, token: token.Token); }, onError: result => Task.FromResult( SailplayApiResult.FromError( statusCode: result.ErrorCode, message: result.Message)), onUnexpectedHttpStatusCode: result => Task.FromResult( SailplayApiResult.FromUnexpectedHttpStatusCode( httpStatusCode: result.StatusCode)))); return apiResponse.Match( onSuccess: UpdateUserResult.FromSuccess, onError: errorResult => errorResult.ErrorCode switch { ApiResponse.ErrorCodes.InvalidValue => UpdateUserResult.FromError( ErrorResult.FromInvalidValue( errorCode: errorResult.ErrorCode, message: errorResult.Message)), ApiResponse.ErrorCodes.UserNotFound => UpdateUserResult.FromError( ErrorResult.FromUserNotFound( errorCode: errorResult.ErrorCode, message: errorResult.Message)), ApiResponse.ErrorCodes.EmailIsUsed => UpdateUserResult.FromError( ErrorResult.FromEmailIsUsed( errorCode: errorResult.ErrorCode, message: errorResult.Message)), ApiResponse.ErrorCodes.PhoneIsUsed => UpdateUserResult.FromError( ErrorResult.FromPhoneIsUsed( errorCode: errorResult.ErrorCode, message: errorResult.Message)), _ => UpdateUserResult.FromError( ErrorResult.FromGeneralError( errorCode: errorResult.ErrorCode, message: errorResult.Message)), }, onUnexpectedHttpStatusCode: UpdateUserResult.FromUnexpectedHttpStatusCode); } namespace RetailRocket.Sailplay.HttpApi.Client.StrictClient { using System.Threading; using System.Threading.Tasks; using RetailRocket.Sailplay.HttpApi.Client.StrictClient.Ports; using RetailRocket.Sailplay.HttpApi.Client.ValueTypes; using RetailRocket.Sailplay.HttpApi.Client.ValueTypes.Results; internal class AuthorisationExecutor { private readonly ITokenProvider tokenProvider; public AuthorisationExecutor( ITokenProvider tokenProvider) { this.tokenProvider = tokenProvider; } public async Task GetAuthorizationTokenAsync( SailplayCredentials credentials, CancellationToken cancellationToken) { var tokenResult = await this.tokenProvider .GetTokenAsync( credentials: credentials, cancellationToken: cancellationToken); return tokenResult; } public async Task RenewAuthorizationTokenAsync( SailplayCredentials credentials, CancellationToken cancellationToken) { var tokenResult = await this.tokenProvider .RenewTokenAsync( credentials: credentials, cancellationToken: cancellationToken); return tokenResult; } } } namespace RetailRocket.Sailplay.HttpApi.Client.StrictClient { using System.Diagnostics; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; using RetailRocket.Sailplay.HttpApi.Client.StrictClient.Ports; using RetailRocket.Sailplay.HttpApi.Client.StrictClient.Responses; using RetailRocket.Sailplay.HttpApi.Client.ValueTypes.Results; internal class RequestExecutor : IRequestExecutor { private readonly IMetricsCollector metricsCollector; private readonly HttpClient httpClient; public RequestExecutor( IMetricsCollector metricsCollector, HttpClient httpClient) { this.metricsCollector = metricsCollector; this.httpClient = httpClient; } public async Task ExecuteApiRequestAsync( HttpRequestMessage request, CancellationToken cancellationToken, string token) { var stopwatch = Stopwatch.StartNew(); using var httpResponseMessage = await this .httpClient .SendAsync( request: request, cancellationToken: cancellationToken); this.metricsCollector.CollectHttpRequestDuration( uri: request.RequestUri, statusCode: httpResponseMessage.StatusCode, elapsedMilliseconds: stopwatch.ElapsedMilliseconds); var result = await this.MapHttpResponseAsync( httpResponseMessage: httpResponseMessage, cancellationToken: cancellationToken); return result; } private async Task MapHttpResponseAsync( HttpResponseMessage httpResponseMessage, CancellationToken cancellationToken) { var basicResponse = await httpResponseMessage .Content .ReadFromJsonAsync( cancellationToken: cancellationToken); return httpResponseMessage.StatusCode switch { HttpStatusCode.OK => basicResponse!.Match( onStatusOk: SailplayApiResult.FromSuccess, onStatusError: SailplayApiResult.FromError), _ => SailplayApiResult.FromUnexpectedHttpStatusCode(httpResponseMessage.StatusCode), }; } } } Отрефактори метод UpdateUserAsync1, максимально сократив его. Разнести по классам RequestExecutor и AuthorisationExecutor. Так же вынеси Retry куда-то в отдельное место. У меня есть много методов типа UpdateUserAsync1, которые используют Retry и в будущем я хотел бы вынести их в отдельные классы и не хотелось бы писать retry код во всех классах.