0

I am trying to build a simple orchestrator func + additional call with sub-orchestrator. The problem is in main orchestrator and call to await ctx.CallSubOrchestratorAsync("sub-orchestration", someInput) - the task is never resolved/completed... If I change the code in sub orchestrator from await Send_SomeData(); to Send_SomeData().Wait(); then it works, but that is not what I want. As far as I know async/await is supported in orchestration funcs

Thank you!

The code is below:

Main Orchestrator

[FunctionName("main-orchestration")]
public static async Task MainOrchestrationAsync(
     [OrchestrationTrigger] IDurableOrchestrationContext ctx, 
     ILogger log)
{
     var someInput = "my msg";
     await ctx.CallSubOrchestratorAsync("sub-orchestration", someInput);
     log.LogWarning("finish");
}

Sub Orchestrator

[FunctionName("sub-orchestration")]
public static async Task SubOrchestrationAsync(
     [OrchestrationTrigger] IDurableOrchestrationContext ctx, 
     ILogger log)
{
     log.LogWarning("Sub Start");
     await Send_SomeData(some_url, some_message);
     log.LogWarning("Sub End");
}

Send_SomeData

public static async Task<string> ConnectAsync(string url, string message)
{
     using var request = new HttpRequestMessage
     {
          RequestUri = new Uri(url),
          Method = HttpMethod.Post, 
          Content = new FormUrlEncodedContent(new[]
          {
                    ...message...
          })
     };

     var response = await _httpClient.SendAsync(request);
     response.EnsureSuccessStatusCode();

     return await response.Content.ReadAsStringAsync();
}

UPDATE I've decided to create an example from scratch, to not miss something and get something that can be copy/paste for debugging. Below is another example. Main End log message never appeared, so Task from .CallSubOrchestratorAsync never resolved.

What am I missing? Thanks again!

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;

namespace _Await_Issue
{
    public static class Function1
    {
        [FunctionName("Main")]
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            log.LogWarning("Main Start");

            try
            {
                await context.CallSubOrchestratorAsync("Sub", null);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            
            log.LogWarning("Main End");
        }

        [FunctionName("Sub")]
        public static async Task RunSubOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            log.LogWarning("Sub Start");

            var data = await GetDataAsync("https://www.google.com");

            log.LogWarning("Sub End");
        }

        [FunctionName("Start")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]
            HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("Main", null);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }

        public static async Task<string> GetDataAsync(string url)
        {
            var httpClient = new HttpClient();

            using var request = new HttpRequestMessage
            {
                RequestUri = new Uri(url),
                Method = HttpMethod.Get,
            };

            var response = await httpClient.SendAsync(request);
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStringAsync();
        }
    }
}
Prog
  • 67
  • 9

1 Answers1

0

I found the light here )) Answering on my own question as it might help others.

As Peter Bons pointed Send_SomeData method was under suspicion ))

The problem in general is in "Deterministic Apis" as Azure team call in the docs Deterministic Apis Explanation

In my case Send_SomeData inside uses HttpClient to communication with external endpoint. It's not recommended as it might result in an unexpected behavior as in my case with await...

If there are such portions of code (e.g. Send_SomeData in my case) put it in Activity and call this with context.CallActivityAsync() - (be aware that Activity funcs has limited time to execute)

Prog
  • 67
  • 9