简体   繁体   中英

How to do a durable post call in an ServiceBusTrigger azure function?

Hey I'm using a ServiceBusTrigger azure function to get the messages received in a queue, and then send them to my webapi which is going to do some stuff with that content

[FunctionName("MyAzureFunction")]
public async void Run(
    [ServiceBusTrigger("<MyQueue>", Connection = "<MyConnectionString>")] Message myQueueItem, ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem.ToString()}");
    var client = new HttpClient();
    // Retrieving the string content from the message
    var bodyMessage = Encoding.UTF8.GetString(myQueueItem.Body);
    // Calling my API to do something based on the message content
    var response = await client.PostAsync("<MyAPIUrl>", new StringContent(bodyMessage, Encoding.UTF8, "application/json"));
    // doing something based on the response
}

I've been reading about azure functions and in order to it gets cheaper I read about durable functions, I'm looking forward how to use them so I can take decisions based on my response and I can get it working with this ServiceBusTrigger

Needs to be changed the current ServiceBusTrigger function so it calls another Function that will actually do the job:

[FunctionName("MyAzureFunction")] public async void Run(
    [ServiceBusTrigger("<MyQueue>", Connection = "<MyConnectionString>")] Message myQueueItem,
    [DurableClient] IDurableOrchestrationClient orchestratorClient,
    ILogger log) {

    log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem.ToString()}");

    // Here is where you need to specify in the first parameter the name of the function to be called
    // and the last parameter are the params you'll send to that one
    var instanceId = await orchestratorClient.StartNewAsync("MyPostFunction", null, myQueueItem);

    log.LogInformation($"C# ServiceBus queue trigger function created an async instance of 'MyPostFunction' with the ID: {instanceId}");
}

Then is needed to create another function that will be OrchestrationTrigger type, that will look like this:

[FunctionName("MyPostFunction")] public async void RunOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) {
    // using the context can be retrieved the parammeters passed in the function above
    // in this case I just specify the type of that one and that's it
    var myQueueItem = context.GetInput<Message>();
    var bodyMessage = Encoding.UTF8.GetString(myQueueItem.Body);

    // Create a URI of your API url
    var postUri = new Uri($"<MyAPIUrl>");

    // depending on your WebAPI you'll need to specify the content type in the headers
    var headers = new Dictionary<string, StringValues>() { { "Content-Type", "application/json" } };
    // creating durable http request
    var request = new DurableHttpRequest(HttpMethod.Post, postUri, headers, bodyMessage);

    // Doing the http call async, in this context you'll save money since your function will not be completely waiting for a response
    // this one will keep just checking to see if there's a response available or not
    var response = await context.CallHttpAsync(request);

    // do your stuffs depending in the response
}

In my case I had to specicify the headers in the request, otherwise I used to get 415 Unsupported Media Type can be done in that way, or just creating the request without specifying any header at the begining and then adding those like this:

var request = new DurableHttpRequest(HttpMethod.Post, postUri, null, bodyMessage);
request.Headers.Add("Content-Type", "application/json");

Both options work

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