Skip to content

Conversation

@jviau
Copy link
Contributor

@jviau jviau commented Oct 17, 2025

This change set adds support for:

  1. Invoking class-based orchestration, entity, and activities directly. No source generator needed.
  2. Moves handling invoking or func-based tasks out of the middleware and into a dedicated executor.

This PR really is two in one, may consider breaking into separate PRs.

Issue 1 - Solving Asynchronous Middleware Breaking Orchestrations

This PR solves orchestrations not support asynchronous middleware by moving the orchestration invocation handling to a custom IFunctionExector, which will always be ran at the very end of the middleware pipeline. So any async middleware will not be captured as part of the orchestration invocation.

NOTE: this PR moves activities and entities to be invoked the same way as well. This does have implications where some bindings are no longer prepared in the middleware. It might be a 'breaking' change for some customers if they tried to access that directly, but we could argue that behavior was never officially supported.

Issue 2 - Fully Support Class Based Tasks

Today class-based tasks are only supported via the source generator and require disabling the functions worker source generator. This is a poor experience for customers. Instead, this PR leverages a new extensibility point from functions allowing durable to supply function definitions directly. Now we can take existing durabletask-dotnet configuration and apply it to functions. No source generation needed - customers directly declare their class-based tasks during startup.

To further improve this experience, durable can adjust how to register implementations to the DurableTaskRegistry. This could be a great use of source-gen. Durable generator (still in preview) can generate a method which registers all discovered types to DurableTaskRegistry. In function projects a startup hook could also be emitted to automatically register those to DurableTaskRegistry.

TODO

  • tests
  • DO NOT MERGE until the next version of Microsoft.Azure.Functions.Worker.Core is released and this project is updated (this code is not functional until then)

Issue describing the changes in this PR

resolves #2720
resolve #2876
resolves microsoft/durabletask-dotnet#158

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation PR is ready to merge and referenced in pending_docs.md
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • I have added all required tests (Unit tests, E2E tests)
  • My changes do not require any extra work to be leveraged by OutOfProc SDKs
    • Otherwise: That work is being tracked here: #issue_or_pr_in_each_sdk
  • My changes do not change the version of the WebJobs.Extensions.DurableTask package
    • Otherwise: major or minor version updates are reflected in /src/Worker.Extensions.DurableTask/AssemblyInfo.cs
  • My changes do not add EventIds to our EventSource logs
    • Otherwise: Ensure the EventIds are within the supported range in our existing Windows infrastructure. You may validate this with a deployed app's telemetry. You may also extend the range by completing a PR such as this one.
  • My changes should be added to v2.x branch.
    • Otherwise: This change applies exclusively to WebJobs.Extensions.DurableTask v3.x. It will be retained only in the dev and main branches and will not be merged into the v2.x branch.

-->
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.DurableTask.Generators" OutputItemType="Analyzer" />
<!-- <PackageReference Include="Microsoft.DurableTask.Generators" OutputItemType="Analyzer" /> -->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source generator will need follow up work after this before it can be included back. Primarily, it will need work to remove generating the class-based shims:

Basically, all this /AzureFunctions folder can be removed: https://github.com/microsoft/durabletask-dotnet/tree/main/src/Generators/AzureFunctions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we tracking this work and when will it be done? The source generators have been available and included in samples for a very long time, and I'm concerned that we might be releasing an update that breaks these existing use cases.

Copy link
Contributor Author

@jviau jviau Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing tracking, will need it.

This class-based change is opt-in (classes need to be manually registered to DurableTaskRegistry), so it won't outright break customers that use the generators package without some action by them. But yes, it is incompatible with the generators package (it will cause duplicate functions).

I have a branch here: https://github.com/microsoft/durabletask-dotnet/tree/u/jviau/generator-refactor which overhauls the generator to address this. But it also drops some existing features, like the strongly-typed extension methods for running orchestrations & activities.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but I consider the strongly typed extension methods (which also works for regular orchestrator and activity function definitions) to be more important than supporting class-based syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can definitely be added back into my branch. My personal opinion is that the sourge-gen approach for strongly typing is an implementation dead end, as it won't work on interface derived types. I recommend investing in mediator style APIs instead. Gives you type safety plus more, and no source gen reliance needed.

@halspang halspang force-pushed the u/jviau/metadata-transform branch 2 times, most recently from 418acca to 4d6ad2a Compare November 6, 2025 05:48
@halspang halspang force-pushed the u/jviau/metadata-transform branch 2 times, most recently from 471c154 to 2eabfae Compare November 7, 2025 00:18
@halspang halspang marked this pull request as ready for review November 7, 2025 20:24
@halspang halspang force-pushed the u/jviau/metadata-transform branch from 2eabfae to 6c70461 Compare November 8, 2025 07:25
jviau and others added 3 commits November 10, 2025 12:30
This change set adds support for:
1. Invoking class-based orchestration, entity, and
activities directly. No source generator needed.
2. Moves handling invoking or func-based tasks out of
the middleware and into a dedicated executor.
@halspang halspang force-pushed the u/jviau/metadata-transform branch from 6c70461 to e798793 Compare November 10, 2025 20:30
-->
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.DurableTask.Generators" OutputItemType="Analyzer" />
<!-- <PackageReference Include="Microsoft.DurableTask.Generators" OutputItemType="Analyzer" /> -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we tracking this work and when will it be done? The source generators have been available and included in samples for a very long time, and I'm concerned that we might be releasing an update that breaks these existing use cases.

@halspang halspang merged commit 1fef0e4 into dev Nov 12, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants