Follow-up to #3608236: Extract a core execution service so the recovery and incident logic can move out and WorkflowEngine becomes a thin facade, #3608366: Extract the loop-free leaf services from the WorkflowExecutor: token lineage, variables, deadline math, definition resolution, incident store and #3608367: Rework the join and subprocess coordination into decide-then-apply collaborators (JoinCoordinator, SubprocessCoordinator), postponed on #3608367: Rework the join and subprocess coordination into decide-then-apply collaborators (JoinCoordinator, SubprocessCoordinator) (it builds on the coordinators). Four finishing moves, one MR:
- Role interfaces on the contract, before 1.0 freezes it: ProcessControlInterface (start, advance, signal, resume, cancel, spawn, variables, correlation lookup), IncidentActionsInterface (the five operator actions) and RecoveryInterface (the three sweeps plus armJoinTimeouts), with WorkflowEngineInterface extending all three so every existing type hint keeps working. Consumers can then declare only the role they use.
- The cron timeout sweep logic moves from the Hook class into a TimeoutSweeper service (orchestra.timeout_sweeper); the hook keeps only the cron entry point, and the service depends on the engine collaborators it actually uses instead of type-hinting the concrete WorkflowEngine for its extra publics.
- The executor becomes stateless: the inline-drain depth and per-request advance budget move to a small request-scoped holder, so every engine service is immutable after construction.
- Test optimization: the pure leaves gain fast unit coverage (the Duration absolute-date helpers, the JoinOutcome factories), starting the shift of engine coverage down the pyramid now that the decide side of the join and the timeout math are leaves.
No public signature changes anywhere; one MR and one CI round.
Issue fork orchestra-3608380
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mably commentedComment #4
mably commentedOpened MR !281 with the four moves: the role interfaces (ProcessControlInterface, IncidentActionsInterface, RecoveryInterface, with WorkflowEngineInterface extending all three so no type hint breaks), the TimeoutSweeper service (the Hook class is now a 37-line cron entry point and nothing type-hints the concrete WorkflowEngine anymore; the orchestra_ui fire-now action calls the sweeper directly), the stateless executor (the drain counters live in a small DrainState holder, so every engine service is immutable after construction) and unit coverage for the pure leaves (DurationTest, JoinOutcomeTest; the unit suite runs in 41 milliseconds).
No public signature changes. Verified locally: root kernel (183), unit plus all submodule kernel (333), all Functional in Docker (37), FunctionalJavascript (6), phpcs, cspell and phpstan parity.
Comment #6
mably commented