microsoft / durabletask-dotnet

Out-of-process .NET SDK for the Durable Task Framework
MIT License
119 stars 34 forks source link

Durable tasks using the class-based syntax are no longer discovered with Microsoft.Azure.Functions.Worker.Sdk 1.16.0+ #247

Open BrianWhiting opened 1 year ago

BrianWhiting commented 1 year ago

I wasn't sure whether to post this issue here or in the Azure Functions project, so I'm posting it both places (other issue here: https://github.com/Azure/azure-functions-dotnet-worker/issues/2067).

I'm currently using durable tasks in one of my projects with the class-based syntax provided through the Microsoft.DurableTask.Generators preview package (https://github.com/microsoft/durabletask-dotnet#class-based-syntax). When I upgrade Microsoft.Azure.Functions.Worker.Sdk from 1.15.1 to 1.16.0+, the runtime no longer discovers the orchestration triggers or activity triggers that are generated in the project.

Using 1.15.1: image

Using 1.16.0+ (1.16.0, 1.16.1, and 1.16.2): image

jviau commented 12 months ago

Pasting my comment from the other issue here:

The cause of this issue is that when using the class-based syntax and the durable generator, the functions that need to be indexed are emitted as part of source gen. But our function indexing itself also occurs during source-gen. This may be just an unsupported scenario and you need to revert to the old-style indexing (setting FunctionsEnableWorkerIndexing to false as others have mentioned).

I don't see this being solvable with the code-gen way as it is twofold issue:

  1. I don't know if one source generator can even access emitted code from another source generator.
  2. We cannot order/chain source generators, so no guarantee the durable generator will always run before the functions indexing generator.

I have been wanting to remove the need for a durable source generator to use class-based syntax for a bit now, and this is another good motivator for that. Not sure what the priority on that is, will need to discuss internally. But for now you correct workaround is to disable the new indexer.

jviau commented 11 months ago

Workaround is to add <FunctionsEnableWorkerIndexing>false</FunctionsEnableWorkerIndexing> to your project.

snerte commented 4 months ago

Workaround is to add <FunctionsEnableWorkerIndexing>false</FunctionsEnableWorkerIndexing> to your project.

This does show Orchestrations for me, but they are not triggered! Bewarned!

martinlingstuyl commented 3 months ago

Same here. It does add a line or 2 to the log say the orchestrator is Executing and Executed. But that's all it does. While the orchestration was working fine before I migrated to class based. I fear I'll be migrating back till this is solved.

tonyperez-dp commented 1 month ago

Workaround is to add <FunctionsEnableWorkerIndexing>false</FunctionsEnableWorkerIndexing> to your project.

This does show Orchestrations for me, but they are not triggered! Bewarned!

I am seeing the same behavior. Is there an ETA as to when this will be addressed?

GeoffreyJKing commented 1 month ago

Same behavior here and the FunctionsEnableWorkerIndexing workaround doesn't work (orchestrators show up as registered but don't actually run). Given how much time I wasted on this, the class-based syntax should be removed from this page: https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-dotnet-isolated-overview#class-based-example

etheone commented 3 days ago

I'm inclined to agree with the previous speaker. Should be removed from the documentation or at least marked as not production ready.

Is there any work at all being done on this? It has been open for over a year now. We're stuck using very old versions due to the class based syntax no longer being discovered.

We're itching to upgrade due to using the old versions seems to be the cause of this startup issue when deployed to azure which seems to be the root cause of the following issue.

BrianWhiting commented 3 days ago

I built a workaround to this issue a few weeks ago based on the internal code generation that the class-based syntax library uses. It doesn't require the use of classes, just functions decorated with the Function attribute with appropriate durable task parameters.

It solves the issue that the class-based syntax library has by not relying on the source generators to create the actual functions (since the Azure function framework also uses source generators to build some bootstrapping code and doesn't see the functions that the class-based syntax library generates), but instead it generates extension methods that just wrap the string-based calls to the durable task framework with strongly-typed methods.

I've been running it on an internal project for a couple weeks without any issues so far.

I put together a small example repo that you can use for yourself: https://github.com/BrianWhiting/DurableTasksSourceGeneratorExample

If you have the source generator project in the same solution as your durable task project, you need to add OutputItemType="Analyzer" ReferenceOutputAssembly="false" to your project reference in your .csproj file. See here: https://github.com/BrianWhiting/DurableTasksSourceGeneratorExample/blob/d6eb463207afe7f8a3bbf1578fd74b090f8a52cc/AzureFunctions/AzureFunctions.csproj#L18

shibayan commented 1 day ago

I have found a workaround that works with the latest SDK, so I'd like to share it.

    <FunctionsEnableWorkerIndexing>false</FunctionsEnableWorkerIndexing>
    <FunctionsEnableExecutorSourceGen>false</FunctionsEnableExecutorSourceGen>

Image