0

I have an orchestration that attempts to use the fan out pattern in order to process items and then add them to another queue. Throughout this learning process I've found that most of my issues arose from missing an await or trying to do something like not use context for getting the time. However, in this suborchestration I can't figure out what I'm doing wrong that prevents all of the code from being executed.

[FunctionName("O_ProcessLearnerQuestionQueueItems")]
public async Task ProcessLearnerQuestionQueueItems(
    [OrchestrationTrigger] IDurableOrchestrationContext ctx,
    ILogger log
)
{

   var currentTime = ctx.CurrentUtcDateTime;

   List<LearnerQuestionQueueItem> needProcessing
                = await ctx.CallActivityAsync<List<LearnerQuestionQueueItem>>("A_GetItemsForProcessingByDate", currentTime.ToUniversalTime());

   if (needProcessing != null && needProcessing.Count > 0)
   {
       // Set items in process
       await ctx.CallActivityAsync<List<LearnerQuestionQueueItem>>("A_SetQueueItemsProcessing", needProcessing);

       List<Task> gatherQuestions = new List<Task>();
       foreach (var item in needProcessing)
       {
           Task task = ctx.CallSubOrchestratorAsync<Message>("SO_GatherQuestionsForLearnerQueueItems", item);

           gatherQuestions.Add(task);
       }
       // My breakpoint on the next line hits, which calls the sub orchestrator; finally, my breakpoint within the activity (called my the sub orchestrator is hit)
       await Task.WhenAll(gatherQuestions);

       // However - I never get to this line
       await ctx.CallActivityAsync("A_SetQueueItemsProcessed", needProcessing);
   }
}

My suborchestrator is as follows, which is supposed to get some needed information, and then add a message to a queue.

[FunctionName("SO_GatherQuestionsForLearnerQueueItems")]
public async Task GatherQuestionsForLearnerQueueItems(
    [OrchestrationTrigger] IDurableOrchestrationContext ctx,
    ServiceBus("message-to-send", Connection = "AzureWebJobsServiceBus")] ICollector<Message> collector,
    ILogger log
)
{
    LearnerQuestionQueueItem item = ctx.GetInput<LearnerQuestionQueueItem>();
    Message message = await ctx.CallActivityAsync<Message>("A_GetQuestionMessageForLearnerQueueItem", item);

    // A breakpoint on this next line never gets hit
    collector.Add(message);
}

I've confirmed that A_GetQuestionMessageForLearnerQueueItem does everything it's supposed to and returns the message but never get to collector.Add(message). It's a big method, so I've trimmed it up quite a bit here:

[FunctionName("A_GetQuestionMessageForLearnerQueueItem")]
public async Task<Message> GetQuestionMessage(
    [ActivityTrigger] LearnerQuestionQueueItem input,
    ILogger log
)
{
    try
    {
        PlatformQuestion platformQuestion = await _questionService.GetQuestion(...);
        QuestionMessage questionMessage = new QuestionMessage() {...};

        QuestionToSendProperties questionToSendProperties = new QuestionToSendProperties() {...};

        var message = new Message();
        message.Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(questionMessage));
        ...
        return message;
     }
     catch (Exception ex)
     {
         var debug = true;
         return null;
     }
}
Daniel Mann
  • 57,011
  • 13
  • 100
  • 120
Chris Rockwell
  • 1,688
  • 2
  • 21
  • 36
  • What about you have the ServiceBus output binding on Activity function instead of eOrchestrator function? – user1672994 Apr 08 '21 at 09:42
  • To clarify - are you asking what happens if I put the output binding on a separate activity function, instead of within the SubOrchestrator? – Chris Rockwell Apr 08 '21 at 13:10
  • Yes, Activity functions are the basic unit of work in a durable function orchestration so having output binding makes sense on that. Also in my setup, ServiceBus as output binding on Activity function without any issue. – user1672994 Apr 08 '21 at 15:29

0 Answers0