M17 / #255 — #[AsWorkflow] autoconfigures, like the other three attributes - #278
Open
gplanchat wants to merge 1 commit into
Open
M17 / #255 — #[AsWorkflow] autoconfigures, like the other three attributes#278gplanchat wants to merge 1 commit into
gplanchat wants to merge 1 commit into
Conversation
…tributs `DurableBundle::build()` autoconfigurait AsActivityHandler, AsNexusServiceHandler et FulfilsNexusOperation, mais pas AsWorkflow. Trois briques sur quatre se déclaraient par attribut, la quatrième par convention de dossier, dans le services.yaml de l'application. L'incohérence était dans le bundle, pas dans les applications. L'issue #255 annonçait un piège : un workflow est instancié par réflexion par WorkflowDefinitionLoader, jamais par le conteneur, et son constructeur reçoit un WorkflowEnvironment qui n'est pas un service — baliser sans plus ferait donc échouer la compilation. Éprouvé plutôt que supposé, et ça ne mord pas. Un cas compile réellement un conteneur portant un workflow de cette forme exacte, celle que le guide enseigne. La raison : WorkflowPass ne lit que le nom de classe et n'ajoute aucune référence, donc la définition reste privée et non référencée, et RemoveUnusedDefinitionsPass la retire avant que DefinitionErrorExceptionPass ne rapporte l'échec d'autowiring. Pas de setAutowired(false), qui aurait été du bruit défensif contre un problème qui n'existe pas. Le tag reste lu : une application qui l'écrit continue de marcher, il fait double emploi. Le guide cesse de le faire écrire, et la page des paquets cesse d'annoncer que `#[AsActivity]` enregistre — c'est un attribut de nommage posé sur le contrat. Les fixtures suivent la convention du dépôt, qui n'est pas celle des tests : sous Fixtures/, le namespace suit le chemin et la classe est autochargeable, comme unit\DurablePhpstan\Fixtures. Les classes de test, elles, gardent leur namespace unit\Gplanchat\… que PHPUnit charge par fichier. Suite unit : 1076 tests contre 1073 sur main, mêmes 4 erreurs d'environnement. PHPStan : 2 erreurs, la base de main. Refs: M17 de documentation/audit/, issue #255 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes issue #255.
DurableBundle::build()autoconfiguredAsActivityHandler,AsNexusServiceHandlerandFulfilsNexusOperation— but notAsWorkflow. Three building blocks out of four declared themselves by attribute, the fourth by folder convention in the application'sservices.yaml. The inconsistency was in the bundle.The trap #255 warned about does not bite
The issue warns — reasonably — that a workflow is instantiated by reflection by
WorkflowDefinitionLoader, never by the container, and that its constructor receives aWorkflowEnvironmentwhich is not a service. It concludes thatautowire: falsemust also be set, without which compilation would fail on a class the container will never build.Tested rather than assumed. One of the three cases actually compiles a
ContainerBuildercarrying a workflow of exactly that shape — the one the getting-started guide teaches:It passes. The mechanism:
WorkflowPassonly reads$definition->getClass()and adds no reference. The definition therefore stays private and unreferenced,RemoveUnusedDefinitionsPassremoves it, andDefinitionErrorExceptionPass— which only reports errors for definitions that survived — has nothing to say.No
setAutowired(false): that would be defensive noise against a problem that does not exist, and it would take autowiring away from a workflow whose author legitimately wants dependencies injected.Worth noting for review all the same: the guard holds because the definition is private and unreferenced. An application declaring its workflows public would hit the autowiring failure — but it already did before this change, since the class was already a service via
App\:. The tag is not what breaks.Documentation
Two places had you write what becomes unnecessary:
resource:+tags:block. It now says there is nothing to write, keeps the block while showing it is redundant, and states that the tag is still read — an application that writes it keeps working.#[AsWorkflow]and#[AsActivity]register themselves. The first becomes true with this PR; the second stays false —#[AsActivity]is a naming attribute placed on the contract.A repository convention rediscovered along the way
The fixtures did not autoload: the test classes' namespace (
unit\Gplanchat\DurableBundle\…) does not match their path, which is fine for tests PHPUnit loads file by file, but not for fixtures. The repository already has the answer —unit\DurablePhpstan\Fixtures,unit\DurableLaravel\Fixtures: underFixtures/, the namespace follows the path. Mine now conform.Verification
mainunitsuitePre-existing and identical errors. Three cases: a workflow with no dependency is registered, a workflow receiving the environment compiles and is registered, a class without the attribute does not join the registry.