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

context.df.Task.any with createTimer and waitForExternalEvent leaves orchestrator in invalid state #577

Open
wanton7 opened this issue Jan 31, 2024 · 0 comments
Labels
P1 Priority 1 item

Comments

@wanton7
Copy link

wanton7 commented Jan 31, 2024

Describe the bug

I have this code

df.app.orchestration('queue_orchestrator', {
  handler: function* (context) {
    const response: 'queue_empty' | 'continue' | null = yield context.df.callActivity('pop_queue');

    if (!response) {
      // Activity failed retry in 1 minute
      yield context.df.createTimer(new Date(context.df.currentUtcDateTime.getTime() + 1000 * 60)); // 1 minute
    } else if (response === 'queue_empty') {
      // No more items in queue, wait for new items
      const timeoutTask = context.df.createTimer(
        new Date(context.df.currentUtcDateTime.getTime() + 1000 * 60 * 60 * 5),
      ); // 5 hours
      const hasQueueTask = context.df.waitForExternalEvent('has_queue');
      yield context.df.Task.any([timeoutTask, hasQueueTask]);
    }

    context.df.continueAsNew(undefined);
  },
});
  1. After this code is run under function emulator 4.0.5455 on WIndows 11
const timeoutTask = context.df.createTimer(
  new Date(context.df.currentUtcDateTime.getTime() + 1000 * 60 * 60 * 5),
); // 5 hours
const hasQueueTask = context.df.waitForExternalEvent('has_queue');
yield context.df.Task.any([timeoutTask, hasQueueTask]);
  1. this code starts returning old data without calling the activity
const response: 'queue_empty' | 'continue' | null = yield context.df.callActivity('pop_queue');

If I change code 1. to this everything works

yield context.df.waitForExternalEvent('has_queue');

I think there is a bug in context.df.Task.any that it leaves orchestrator in invalid state if waitForExternalEvent is first task to finish.

Investigative information

  • durable-functions npm module version: 3.0.1
  • Language (JavaScript/TypeScript) and version: 5.2.2
  • Node.js version: v18.18

Actual behavior
When using context.df.Task.any with context.df.createTimer & context.df.waitForExternalEvent and if context.df.waitForExternalEvent task finishes first orchestrator is left in invalid state and starts to receive old values from context.df.callActivity('pop_queue') without even calling the activity meaning code in the activity is never called.

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

No branches or pull requests

3 participants