Activity calls from CreateRetryableClient are non-deterministic
See original GitHub issueIssue
It appears that proxy objects generated by OrchestrationContext.CreateRetriableClient
result in clients that invoke activities in a way that is non-deterministic. In particular, there appears to be threading problems with these clients that often result in stuck orchestrations or orchestrations that fail with errors like the following:
DurableTask.Core.Exceptions.NonDeterministicOrchestrationException: Non-Deterministic workflow detected: TaskScheduledEvent: 4 TaskScheduled Method5
at DurableTask.Core.TaskOrchestrationContext.HandleTaskScheduledEvent(TaskScheduledEvent scheduledEvent) in C:\GitHub\durabletask\src\DurableTask.Core\TaskOrchestrationContext.cs:line 268
at DurableTask.Core.TaskOrchestrationExecutor.ProcessEvent(HistoryEvent historyEvent) in C:\GitHub\durabletask\src\DurableTask.Core\TaskOrchestrationExecutor.cs:line 141
at DurableTask.Core.TaskOrchestrationExecutor.ExecuteCore(IEnumerable`1 eventHistory) in C:\GitHub\durabletask\src\DurableTask.Core\TaskOrchestrationExecutor.cs:line 82
at DurableTask.Core.TaskOrchestrationContext.HandleTaskScheduledEvent(TaskScheduledEvent scheduledEvent) in C:\GitHub\durabletask\src\DurableTask.Core\TaskOrchestrationContext.cs:line 268
Previous maintainers of this repro have mentioned that this API is buggy.
The issue may be related to the use of Dynamity for dynamically invoking activity functions.
Workarounds
- Use
OrchestrationContext.ScheduleWithRetry
- unfortunately this is not a type-safe way to call activity tasks. - Use
OrchestrationContext.CreateClient
- unfortunately this doesn’t support automatic retries.
Issue Analytics
- State:
- Created 2 years ago
- Comments:17 (2 by maintainers)
Top Results From Across the Web
Durable activity sometimes detected as Non-Deterministic ...
First, it calls an activity to do an update on a SQL Server database. Then a sub orchestrator task is called to some...
Read more >Non-Deterministic workflow detected in Durable Functions
The activity function returns the orders that have been rated, and then I save those orders to the blob along with the rules...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@davidmrdavid , In the mean time, I’ve opened a PR with the changes mentioned here.
https://github.com/Azure/durabletask/pull/750
@cgillum , I did a test with Castle.Core library that seems a much better alternative to the current Dynamity. Castle.Core is also used internally by the Moq library.
Castle.Core supports creating proxy objects from interfaces, as well as abstract and non-sealed classes. In addition, it mitigates a separate edge case bug with Dynamity where the proxy method return types cannot be
private
or less visible than the proxy target. With Castle.Core, this is what theRetryProxy.cs
would look like:Similarly, the
ScheduleProxy.cs
would become:With these changes, the
CreateClient<T>()
andCreateRetryableClient<T>
would change like below: