Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single event notification is being yielded every time with wait_for_external_event #507

Open
arjendev opened this issue Jun 11, 2024 · 2 comments
Assignees
Labels
P1 Priority 1

Comments

@arjendev
Copy link

arjendev commented Jun 11, 2024

🐛 Describe the bug
When an event notification is raised for an orchestrator that is not yet waiting, then using wait_for_external_event multiple times will always yield that same specific initial event.

A typical scenario when this might happen is when multiple event notifications are raised at the same time by other orchestrators and the main orchestrator would not be waiting during handling of the first event.

🤔 Expected behavior
The expected behavior is that a single event notification only yields a single wait_for_external_event. This does work as expected for event notifications that were submitted after an orchestrator already started to wait for the external event, but not for notification events that were scheduled before waiting for the external event.

Steps to reproduce

I have been able to reproduce the issue in a small example as seen below.

Sample repository: https://github.com/arjendev/durable-functions-python-external-events-issue-sample
Sample orchestration history: https://github.com/arjendev/durable-functions-python-external-events-issue-sample/blob/main/OrchestrationHistory.csv

myApp = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@myApp.route(route="orchestrators/{functionName}")
@myApp.durable_client_input(client_name="client")
async def http_start(req: func.HttpRequest, client: DurableOrchestrationClient):
    function_name = req.route_params.get('functionName')
    instance_id = await client.start_new(function_name)
    response = client.create_check_status_response(req, instance_id)
    return response

# Orchestrator
@myApp.orchestration_trigger(context_name="context")
def hello_orchestrator(context: DurableOrchestrationContext):
    yield context.call_activity("raise_my_durable_event", context.instance_id)
    while True:
        yield context.wait_for_external_event("my-durable-event")

# Activity
@myApp.activity_trigger(input_name="instance", activity="raise_my_durable_event")
@myApp.durable_client_input(client_name="client")
async def raise_my_durable_event(client: DurableOrchestrationClient, instance):
    await client.raise_event(instance, "my-durable-event")

The expected behavior of execution of the orchestrator would be:

  1. Start the orchestrator through the http_trigger
  2. Main orchestrator starts and raises an event notification with name: my-durable-event
  3. Main orchestrator enters the while loop and starts waiting for external events and immediately yields the already scheduled event notification
  4. Main orchestrator halts in the second iteration of the while loop and waits for future events

However, on step 4, the wait_for_external_event keeps returning the initial event and thus the while loop runs forever with the eventual error: Orchestrator function 'hello_orchestrator' failed: maximum recursion depth exceeded in comparison.

@arjendev
Copy link
Author

Together with @LeonardHd, we confirmed that it is working as expected for dotnet and nodejs, see examples here:

@davidmrdavid davidmrdavid added P1 Priority 1 and removed Needs: Triage 🔍 labels Jun 12, 2024
@davidmrdavid davidmrdavid self-assigned this Jun 12, 2024
@davidmrdavid
Copy link
Collaborator

Thanks @arjendev for the detailed bug report. The team is a bit busy with some urgent threads this week, but would you be able to ping this thread again next week for me to take a look? I suspect this should be an easy fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 Priority 1
Projects
None yet
Development

No branches or pull requests

2 participants