Azure Durable Functions: External events not working properly in Orchestration

31 Views Asked by At

I'm developing a meeting timer using Azure Durable Functions where I'm using external events to control the orchestration flow. Specifically, I have an orchestration function that calls an activity function repeatedly, and it listens for external events ("pause" and "stop") to control the execution. I utilize HTTP webhooks provided by Azure to raise events for orchestrations. The timer allows users to start, pause, play, and stop meeting timer.

Here i have attached a image of timer functionality. timer functionality image

The problem I'm encountering is that the HTTP webhooks used to raise events for orchestrations sometimes work perfectly with a single click for pausing, stopping, or playing the meeting timer, but other times they don't seem to have any effect and working on multiple clicks. Strangely, I'm receiving a 202 status code indicating successful execution, but the orchestration function doesn't consistently receive these events. This inconsistency leads to unexpected behavior in the timer's execution flow.

Here's a simplified version of my code:

# orchestrator_function.py
import json
import azure.functions as func
import azure.durable_functions as df
import datetime


def orchestrator_function(context: df.DurableOrchestrationContext):
    input_data = context.get_input()
    while True:
        if context.custom_status:
            cur_custom_status = json.loads(context.custom_status)
            status = cur_custom_status.get("status", "Waiting")
            if status == "Finished":
                break
        else:
            context.set_custom_status(json.dumps(input_data))
            status = "Waiting"

        # Wait for events before entering the loop
        durable_time_out_task = context.create_timer(
            context.current_utc_datetime + datetime.timedelta(seconds=1))
        if status  != "Started":
            start_timer_event = context.wait_for_external_event("start_timer")
            action = yield context.task_any([start_timer_event, durable_time_out_task])
            if action == start_timer_event:
                timer_state = yield context.call_activity("StartTimer", context.custom_status)
                context.set_custom_status(timer_state)
        else:
            # Check for events
            # play_timer_event = context.wait_for_external_event("play_timer")
            pause_timer_event = context.wait_for_external_event("pause_timer")
            stop_timer_event = context.wait_for_external_event("stop_timer")
            
            # Convert event into task if raised else raise timeout event
            action = yield context.task_any([pause_timer_event, stop_timer_event, durable_time_out_task])
            if action == pause_timer_event:
                timer_state = yield context.call_activity("PauseTimer", context.custom_status)
                context.set_custom_status(timer_state)
                replay_event = yield context.task_any([context.wait_for_external_event("play_timer")])
                if replay_event:
                    timer_state = yield context.call_activity("PlayTimer", context.custom_status)
                    context.set_custom_status(timer_state)
                replay_event = None
                continue
            elif action == stop_timer_event:
                timer_state = yield context.call_activity("StopTimer", timer_state)
                context.set_custom_status(timer_state)
                break
        
 
        if status == "Started":
            timer_state = yield context.call_activity("PlayTimer", context.custom_status)
            context.set_custom_status(timer_state)

        action = None
main = df.Orchestrator.create(orchestrator_function)

here are the webhook i am using to raise events using http:

POST /runtime/webhooks/durabletask/instances/{instanceId}/raiseEvent/{eventName}
    ?taskHub={taskHub}
    &connection={connectionName}
    &code={systemKey}

Has anyone else had trouble with Azure Durable Functions and HTTP webhooks causing inconsistent event triggering? I'm finding that while the webhooks usually work with a single click to pause, stop, or play the timer, sometimes they don't respond or need multiple clicks.

Could this issue be due to timing, concurrency, or something else? And is there a more reliable way to handle external events in Durable Functions to ensure consistent flow control?

Note: I am using azurite to test durable function at localhost

I'd really appreciate any advice on how to make sure my meeting timer app handles events reliably.

Thanks for your help!

0

There are 0 best solutions below