2424
2525/**
2626 * @psalm-type QueryHandler = \Closure(QueryInput): mixed
27- * @psalm-type UpdateHandler = \Closure(UpdateInput, Deferred): PromiseInterface
27+ * @psalm-type UpdateHandler = \Closure(UpdateInput, Deferred): mixed
2828 * @psalm-type ValidateUpdateHandler = \Closure(UpdateInput): void
2929 * @psalm-type QueryExecutor = \Closure(QueryInput, callable(ValuesInterface): mixed): mixed
3030 * @psalm-type UpdateExecutor = \Closure(UpdateInput, callable(ValuesInterface): mixed, Deferred): PromiseInterface
31- * @psalm-type ValidateUpdateExecutor = \Closure(UpdateInput, callable(ValuesInterface): mixed): mixed
31+ * @psalm-type ValidateUpdateExecutor = \Closure(UpdateInput, callable(ValuesInterface): mixed): void
3232 * @psalm-type UpdateValidator = \Closure(UpdateInput, UpdateHandler): void
3333 *
3434 * @internal
3535 */
3636final class WorkflowInstance extends Instance implements WorkflowInstanceInterface
3737{
38- /**
39- * @var array<non-empty-string, QueryHandler>
40- */
38+ /** @var array<non-empty-string, QueryHandler> */
4139 private array $ queryHandlers = [];
4240
43- /**
44- * @var array<non-empty-string, MethodHandler>
45- */
41+ /** @var null|QueryHandler */
42+ private ?\Closure $ queryDynamicHandler = null ;
43+
44+ /** @var null|UpdateHandler */
45+ private ?\Closure $ updateDynamicHandler = null ;
46+
47+ /** @var null|ValidateUpdateHandler */
48+ private ?\Closure $ updateDynamicValidator = null ;
49+
50+ /** @var array<non-empty-string, MethodHandler> */
4651 private array $ signalHandlers = [];
4752
48- /**
49- * @var array<non-empty-string, UpdateHandler>
50- */
53+ /** @var array<non-empty-string, UpdateHandler> */
5154 private array $ updateHandlers = [];
5255
53- /**
54- * @var array<non-empty-string, null|ValidateUpdateHandler>
55- */
56+ /** @var array<non-empty-string, null|ValidateUpdateHandler> */
5657 private array $ validateUpdateHandlers = [];
5758
5859 private SignalQueue $ signalQueue ;
@@ -174,7 +175,7 @@ public function getSignalQueue(): SignalQueue
174175 */
175176 public function findQueryHandler (string $ name ): ?\Closure
176177 {
177- return $ this ->queryHandlers [$ name ] ?? null ;
178+ return $ this ->queryHandlers [$ name ] ?? $ this -> queryDynamicHandler ;
178179 }
179180
180181 /**
@@ -185,7 +186,7 @@ public function findQueryHandler(string $name): ?\Closure
185186 */
186187 public function findUpdateHandler (string $ name ): ?\Closure
187188 {
188- return $ this ->updateHandlers [$ name ] ?? null ;
189+ return $ this ->updateHandlers [$ name ] ?? $ this -> updateDynamicHandler ;
189190 }
190191
191192 /**
@@ -196,7 +197,11 @@ public function findUpdateHandler(string $name): ?\Closure
196197 */
197198 public function findValidateUpdateHandler (string $ name ): ?\Closure
198199 {
199- return $ this ->validateUpdateHandlers [$ name ] ?? null ;
200+ return $ this ->validateUpdateHandlers [$ name ] ?? (
201+ \array_key_exists ($ name , $ this ->updateHandlers )
202+ ? null
203+ : $ this ->updateDynamicValidator
204+ );
200205 }
201206
202207 /**
@@ -207,16 +212,13 @@ public function addQueryHandler(string $name, callable $handler): void
207212 $ fn = $ this ->createCallableHandler ($ handler );
208213
209214 $ this ->queryHandlers [$ name ] = $ this ->pipeline ->with (
210- function (QueryInput $ input ) use ($ fn ) {
211- return ($ this ->queryExecutor )($ input , $ fn );
212- },
215+ fn (QueryInput $ input ): mixed => ($ this ->queryExecutor )($ input , $ fn ),
213216 /** @see WorkflowInboundCallsInterceptor::handleQuery() */
214217 'handleQuery ' ,
215218 )(...);
216219 }
217220
218221 /**
219- * @param non-empty-string $name
220222 * @throws \ReflectionException
221223 */
222224 public function addUpdateHandler (string $ name , callable $ handler ): void
@@ -233,7 +235,6 @@ function (UpdateInput $input, Deferred $deferred) use ($fn) {
233235 }
234236
235237 /**
236- * @param non-empty-string $name
237238 * @throws \ReflectionException
238239 */
239240 public function addValidateUpdateHandler (string $ name , callable $ handler ): void
@@ -263,15 +264,49 @@ public function getSignalHandler(string $name): \Closure
263264 return fn (ValuesInterface $ values ) => $ this ->signalQueue ->push ($ name , $ values );
264265 }
265266
266- /**
267- * @throws \ReflectionException
268- */
269267 public function addSignalHandler (string $ name , callable $ handler ): void
270268 {
271269 $ this ->signalHandlers [$ name ] = $ this ->createCallableHandler ($ handler );
272270 $ this ->signalQueue ->attach ($ name , $ this ->signalHandlers [$ name ]);
273271 }
274272
273+ public function setDynamicSignalHandler (callable $ handler ): void
274+ {
275+ $ this ->signalQueue ->setFallback ($ handler (...));
276+ }
277+
278+ public function setDynamicQueryHandler (callable $ handler ): void
279+ {
280+ $ this ->queryDynamicHandler = $ this ->pipeline ->with (
281+ fn (QueryInput $ input ): mixed => ($ this ->queryExecutor )(
282+ $ input ,
283+ static fn (ValuesInterface $ arguments ): mixed => $ handler ($ input ->queryName , $ arguments ),
284+ ),
285+ /** @see WorkflowInboundCallsInterceptor::handleQuery() */
286+ 'handleQuery ' ,
287+ )(...);
288+ }
289+
290+ public function setDynamicUpdateHandler (callable $ handler , ?callable $ validator = null ): void
291+ {
292+ $ this ->updateDynamicValidator = $ validator === null
293+ ? null
294+ : fn (UpdateInput $ input ): mixed => ($ this ->updateValidator )(
295+ $ input ,
296+ static fn (ValuesInterface $ arguments ): mixed => $ validator ($ input ->updateName , $ arguments ),
297+ );
298+
299+ $ this ->updateDynamicHandler = $ this ->pipeline ->with (
300+ fn (UpdateInput $ input , Deferred $ deferred ): mixed => ($ this ->updateExecutor )(
301+ $ input ,
302+ static fn (ValuesInterface $ arguments ): mixed => $ handler ($ input ->updateName , $ arguments ),
303+ $ deferred ,
304+ ),
305+ /** @see WorkflowInboundCallsInterceptor::handleUpdate() */
306+ 'handleUpdate ' ,
307+ )(...);
308+ }
309+
275310 public function clearSignalQueue (): void
276311 {
277312 $ this ->signalQueue ->clear ();
@@ -290,6 +325,7 @@ public function destroy(): void
290325 $ this ->updateValidator ,
291326 $ this ->prototype ,
292327 $ this ->pipeline ,
328+ $ this ->queryDynamicHandler ,
293329 );
294330 parent ::destroy ();
295331 }
0 commit comments