Make an Http request through a Lambda Func

Viewed 1030

I'm trying make httpclient requests through a helper function that will manage a circuitbreaker polly policy.

I'm trying to call it like so

var response = clientFactory.MakeRequest(() => client.GetAsync("/"));

Inside of the client factory I have my circuit breaker policy defined and I'm trying to execute the lambda above using that policy like so

public async Task<HttpResponseMessage> MakeRequest(Func<HttpResponseMessage> request)
{
     var response = policy.ExecuteAsync(() => request.Invoke());
     return response;
}

I'm fairly new to Lambda's as a whole and passing it as a function gets more confusing. How do I configure the function and the first line of code to execute the client and return the HttpResponseMessage? I don't think Task<HttpResponseMessage> or Func<HttpResponseMessage> is correct

2 Answers

Let's start from this line:

var response = clientFactory.MakeRequest(() => client.GetAsync("/"));

If client is an HttpClient instance then the GetAsync returns a Task<HttpResponseMessage>. So, what you have passed as a parameter to the MakeRequest is a function which returns a Task<HttpResponseMessage>. Without defining a custom delegate you can use the Func type to describe this intent: Func<Task<HttpResponseMessage>>.


So, your MakeRequest should anticipate this kind of parameter to be able to decorate it with a policy (or chain of policies). The actual implementation of the MakeRequest can be written in so many different ways:

Option 1

  • Passing request to ExecuteAsync as it is
  • Returning the result of ExecuteAsync as it is
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => policy.ExecuteAsync(request);

Option 2

  • Passing request to ExecuteAsync as it is
  • Awaiting the result of ExecuteAsync
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => await policy.ExecuteAsync(request);

Option 3

  • Passing a function to ExecuteAsync which calls the request
  • Returning the result of ExecuteAsync as it is
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => policy.ExecuteAsync(() => request());

Option 4

  • Passing a function to ExecuteAsync which calls the request
  • Awaiting the result of ExecuteAsync
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => await policy.ExecuteAsync(() => request());

Option 5

  • Passing an async function to ExecuteAsync which awaits the request
  • Returning the result of ExecuteAsync as it is
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => policy.ExecuteAsync(async () => await request());

Option 6

  • Passing an async function to ExecuteAsync which awaits the request
  • Awaiting the result of ExecuteAsync
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
   => await policy.ExecuteAsync(async () => await request());

Even though Option 1 is the most simplest I would recommend the usage of Option 6

Related