|
3 | 3 | namespace TangibleDDD\Application\Process; |
4 | 4 |
|
5 | 5 | use DateTimeImmutable; |
6 | | -use TangibleDDD\Domain\Events\IIntegrationEvent; |
7 | 6 | use TangibleDDD\Domain\Shared\Aggregate; |
8 | 7 | use TangibleDDD\Domain\Shared\JsonLifecycleValue; |
9 | 8 |
|
|
13 | 12 | * Processes are defined as a series of steps (methods) that execute in declaration order. |
14 | 13 | * Each step returns a Result that tells the runner what to do next: |
15 | 14 | * - payload: pass data to the next step (must be JsonLifecycleValue) |
16 | | - * - queries: execute these queries, pass results to next step |
17 | | - * - commands: execute these commands (they send() themselves) |
| 15 | + * - commands: execute these commands (fire-and-forget side effects) |
18 | 16 | * - await: suspend until an integration event fires |
19 | 17 | * |
| 18 | + * ## Step Signatures |
| 19 | + * |
| 20 | + * Steps can have different signatures depending on what they need: |
| 21 | + * - `protected function step_name(): Result` - no input needed |
| 22 | + * - `protected function step_name(SomePayload $payload): Result` - receives payload |
| 23 | + * - `protected function step_name(?SomePayload $payload, SomeEvent $event): Result` - post-await step |
| 24 | + * |
20 | 25 | * ## DI Registration |
21 | 26 | * |
22 | 27 | * Register your process in services.yaml with the 'ddd.long_process' tag. |
23 | 28 | * If your process uses AwaitEvent, declare the awaited event classes: |
24 | 29 | * |
25 | 30 | * ```yaml |
26 | | - * App\Process\GenerateLearningPath: |
| 31 | + * App\Process\OrderFulfillmentProcess: |
27 | 32 | * tags: |
28 | 33 | * - name: 'ddd.long_process' |
29 | 34 | * awaits: |
30 | | - * - App\Events\UserApprovedPath |
| 35 | + * - App\Events\PaymentReceived |
31 | 36 | * ``` |
32 | 37 | * |
33 | 38 | * ## Example |
34 | 39 | * |
35 | 40 | * ```php |
36 | | - * class GenerateLearningPath extends LongProcess { |
| 41 | + * class OrderFulfillmentProcess extends LongProcess { |
37 | 42 | * public function __construct( |
38 | | - * private readonly int $user_id, |
| 43 | + * private readonly int $order_id, |
39 | 44 | * ) { |
40 | 45 | * parent::__construct(null); |
41 | 46 | * } |
42 | 47 | * |
43 | | - * protected function fetch_history(): Result { |
44 | | - * return new Result(payload: new HistoryPayload($this->user_id)); |
| 48 | + * protected function initialize(): Result { |
| 49 | + * return new Result(payload: new OrderPayload($this->order_id)); |
45 | 50 | * } |
46 | 51 | * |
47 | | - * protected function request_approval(HistoryPayload $payload): Result { |
| 52 | + * protected function request_payment(OrderPayload $payload): Result { |
| 53 | + * // Dispatch payment request... |
48 | 54 | * return new Result( |
49 | | - * await: new AwaitEvent(UserApprovedPath::class, ['user_id' => $this->user_id]) |
| 55 | + * payload: $payload, |
| 56 | + * await: new AwaitEvent(PaymentReceived::class, ['order_id' => $this->order_id]) |
50 | 57 | * ); |
51 | 58 | * } |
52 | 59 | * |
53 | | - * // Next step receives the event via $this->resume_event() |
54 | | - * protected function process_approval(): Result { |
55 | | - * $event = $this->resume_event(UserApprovedPath::class); |
56 | | - * // ... use event data |
| 60 | + * // Post-await step receives both payload and the event that woke it |
| 61 | + * protected function process_payment(?OrderPayload $payload, PaymentReceived $event): Result { |
| 62 | + * // Use $event->amount, $event->transaction_id, etc. |
57 | 63 | * return new Result(); |
58 | 64 | * } |
59 | 65 | * } |
@@ -85,17 +91,6 @@ abstract class LongProcess extends Aggregate { |
85 | 91 | */ |
86 | 92 | protected ?ProcessSteps $steps = null; |
87 | 93 |
|
88 | | - // ───────────────────────────────────────────────────────────────────────── |
89 | | - // Transient state (NOT persisted - only valid during current execution) |
90 | | - // ───────────────────────────────────────────────────────────────────────── |
91 | | - |
92 | | - /** |
93 | | - * Event that triggered resume from suspension. |
94 | | - * Available to the step immediately after an await. |
95 | | - * Cleared after the step executes. |
96 | | - */ |
97 | | - private ?IIntegrationEvent $resume_event = null; |
98 | | - |
99 | 94 | // ───────────────────────────────────────────────────────────────────────── |
100 | 95 | // Accessors (framework state) |
101 | 96 | // ───────────────────────────────────────────────────────────────────────── |
@@ -132,50 +127,6 @@ public function updated_at(): ?DateTimeImmutable { |
132 | 127 | return $this->updated_at; |
133 | 128 | } |
134 | 129 |
|
135 | | - // ───────────────────────────────────────────────────────────────────────── |
136 | | - // Transient state accessors |
137 | | - // ───────────────────────────────────────────────────────────────────────── |
138 | | - |
139 | | - /** |
140 | | - * Get the event that triggered resume from suspension. |
141 | | - * Only available to the step immediately after an await. |
142 | | - * |
143 | | - * @template T of IIntegrationEvent |
144 | | - * @param class-string<T>|null $expected_class Optional type check |
145 | | - * @return T|IIntegrationEvent|null |
146 | | - */ |
147 | | - public function resume_event(?string $expected_class = null): ?IIntegrationEvent { |
148 | | - if ($this->resume_event === null) { |
149 | | - return null; |
150 | | - } |
151 | | - |
152 | | - if ($expected_class !== null && !($this->resume_event instanceof $expected_class)) { |
153 | | - throw new \RuntimeException(sprintf( |
154 | | - 'Expected resume event of type %s, got %s', |
155 | | - $expected_class, |
156 | | - get_class($this->resume_event) |
157 | | - )); |
158 | | - } |
159 | | - |
160 | | - return $this->resume_event; |
161 | | - } |
162 | | - |
163 | | - /** |
164 | | - * Set the resume event (called by ProcessRunner). |
165 | | - * @internal |
166 | | - */ |
167 | | - public function set_resume_event(IIntegrationEvent $event): void { |
168 | | - $this->resume_event = $event; |
169 | | - } |
170 | | - |
171 | | - /** |
172 | | - * Clear the resume event after step execution. |
173 | | - * @internal |
174 | | - */ |
175 | | - public function clear_resume_event(): void { |
176 | | - $this->resume_event = null; |
177 | | - } |
178 | | - |
179 | 130 | // ───────────────────────────────────────────────────────────────────────── |
180 | 131 | // Step state accessors (delegates to ProcessSteps, hides internal structure) |
181 | 132 | // ───────────────────────────────────────────────────────────────────────── |
|
0 commit comments