What happens
A workflow class carrying #[AsWorkflow] in a Symfony application is never registered. WorkflowRegistry stays empty for it, and starting an execution fails with:
Unknown workflow type: OrderFulfilment
Why
DurableBundle::build() registers attribute autoconfiguration for three attributes:
AsActivityHandler → tag durable.activity_handler
AsNexusServiceHandler → tag NexusHandlerPass::TAG
FulfilsNexusOperation → tag NexusHandlerPass::FULFILMENT_TAG
AsWorkflow is not among them. WorkflowPass then iterates findTaggedServiceIds('durable.workflow'), and no compiler pass and no configuration ever applies that tag. A grep across durable-bundle finds 'durable.workflow' in exactly one place: the pass that reads it.
The documentation says the opposite - the host table in the workflow reference reads "Symfony, Sylius | autoconfigured from the attribute", and contrasts it with Laravel and Magento where the class must be named explicitly.
Reproduce
Sylius 2.2.1 / Symfony 7.4.2 / PHP 8.3, gplanchat/durable-bundle v0.1.0-alpha10.
#[AsWorkflow('OrderFulfilment')]
final class OrderFulfilmentWorkflow
{
public function __construct(private readonly WorkflowEnvironment $environment) {}
#[AsWorkflowMethod]
public function run(string $orderNumber): string { /* … */ }
}
bin/console debug:container --tag=durable.workflow lists nothing.
Suggested fix
Add the fourth registration in DurableBundle::build():
$container->registerAttributeForAutoconfiguration(
AsWorkflow::class,
static function (ChildDefinition $definition): void {
$definition->addTag('durable.workflow');
},
);
One wrinkle worth deciding at the same time: a workflow is instantiated by WorkflowDefinitionLoader::instantiate() through reflection, not by the container, and its constructor takes a WorkflowEnvironment that is not a service. So autoconfiguring the tag also needs the service definition to skip autowiring, otherwise the container fails to compile on a class it will never build. Marking such definitions autowire: false inside the autoconfiguration callback would make the attribute work on its own.
Workaround in use
App\:
resource: '../src/'
exclude:
- '../src/Workflow/'
App\Workflow\OrderFulfilmentWorkflow:
autowire: false
autoconfigure: false
tags: ['durable.workflow']
What happens
A workflow class carrying
#[AsWorkflow]in a Symfony application is never registered.WorkflowRegistrystays empty for it, and starting an execution fails with:Why
DurableBundle::build()registers attribute autoconfiguration for three attributes:AsActivityHandler→ tagdurable.activity_handlerAsNexusServiceHandler→ tagNexusHandlerPass::TAGFulfilsNexusOperation→ tagNexusHandlerPass::FULFILMENT_TAGAsWorkflowis not among them.WorkflowPassthen iteratesfindTaggedServiceIds('durable.workflow'), and no compiler pass and no configuration ever applies that tag. A grep acrossdurable-bundlefinds'durable.workflow'in exactly one place: the pass that reads it.The documentation says the opposite - the host table in the workflow reference reads "Symfony, Sylius | autoconfigured from the attribute", and contrasts it with Laravel and Magento where the class must be named explicitly.
Reproduce
Sylius 2.2.1 / Symfony 7.4.2 / PHP 8.3,
gplanchat/durable-bundlev0.1.0-alpha10.bin/console debug:container --tag=durable.workflowlists nothing.Suggested fix
Add the fourth registration in
DurableBundle::build():One wrinkle worth deciding at the same time: a workflow is instantiated by
WorkflowDefinitionLoader::instantiate()through reflection, not by the container, and its constructor takes aWorkflowEnvironmentthat is not a service. So autoconfiguring the tag also needs the service definition to skip autowiring, otherwise the container fails to compile on a class it will never build. Marking such definitionsautowire: falseinside the autoconfiguration callback would make the attribute work on its own.Workaround in use