简体   繁体   中英

How to include a multiline block of code in a lambda expression for Polly ExecuteAsync?

I have working code that uses the ExecuteAsync() method on a Polly policy ( IAsyncPolicy<HttpResponseMessage> ) to pull data from a web page. I'd like to add some debug logging to it, but so far I am not able to figure out the correct syntax to have this happen unless I wrap both the logging and http call in a separate method, and then call that via ExecuteAsync .

This doesn't seem "right" to me, and I feel there is a cleaner or more direct way. I think my issue is that I don't have a complete enough understanding of how Func<T> and lambda expressions truly operate to pull this off, as when I wrap things in {} I get errors like:

Not all code paths return a value in lambda expression of type Func<CancellationToken, Task<HttpResponseMessage>> .

This is my original working code:

var httpClient = _httpClientFactory.CreateClient();
HttpResponseMessage result;
var retryPolicy = (IAsyncPolicy<HttpResponseMessage>)_policyRegistry[RetryPolicyKeyName];

result = await retryPolicy.ExecuteAsync(
    async cancellationToken =>    
        await httpClient.GetAsync(myUrl, cancellationToken)
    , cancellationToken
);

This code produces the "Not all code paths return a value in lambda expression of type Func<CancellationToken, Task> error:

var httpClient = _httpClientFactory.CreateClient();
HttpResponseMessage result;
var retryPolicy = (IAsyncPolicy<HttpResponseMessage>)_policyRegistry[RetryPolicyKeyName];

result = await retryPolicy.ExecuteAsync(
    async cancellationToken =>    
    {
        await httpClient.GetAsync(myUrl, cancellationToken);
    }
    , cancellationToken
);

This is my "hack" that gets done what I want with an extra method:

private async Task<HttpResponseMessage> TestWithLogAsync(HttpClient httpClient, string myUrl, CancellationToken cancellationToken)
{
    _logger.LogDebug("Requesting from: {myUrl}", myUrl);
    var result = await httpClient.GetAsync(myUrl, cancellationToken);
    return result;
}

var httpClient = _httpClientFactory.CreateClient();
HttpResponseMessage result;
var retryPolicy = (IAsyncPolicy<HttpResponseMessage>)_policyRegistry[RetryPolicyKeyName];

result = await retryPolicy.ExecuteAsync(
    async cancellationToken =>
        await TestWithLogAsync(httpClient, myUrl, cancellationToken)
    , cancellationToken
);

What you have here:

result = await retryPolicy.ExecuteAsync(
    await httpClient.GetAsync(managementUrl, cancellationToken)
    , cancellationToken
);

Is equivalent to:

result = await retryPolicy.ExecuteAsync(async () => {
      return await httpClient.GetAsync(managementUrl, cancellationToken);
    }
    , cancellationToken
);

Hence this will execute more than one line in the lambda:

result = await retryPolicy.ExecuteAsync(async () => {
      _logger.LogDebug("Requesting from: {managementUrl}", managementUrl);
      return await httpClient.GetAsync(managementUrl, cancellationToken);
    }
    , cancellationToken
);

..though I wasn't quite clear on how managementUrl morphed into myUrl across your examples, and whether they differ.. I've assumed not

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM