Support dynamic (catch-all) workflows - #784
Draft
datashaman wants to merge 1 commit into
Draft
Conversation
Allow a PHP worker to register a dynamic (catch-all) workflow, invoked for any workflow type name that has no statically registered handler. The host already registers a single shared WorkflowDefinitionFactory proxy (wDef) under each declared name; when a workflow is declared dynamic, register that same proxy via worker.RegisterDynamicWorkflow instead (it forwards the real workflow type name to PHP), and skip named registration for it. WorkflowInfo gains a Dynamic field, populated from the "dynamic" key the PHP GetWorkerInfo handshake emits. This enables Dynamic Workflow support in the PHP SDK (PHP and TypeScript are the only SDKs without it). Companion change: temporalio/sdk-php. Depends on temporalio/sdk-go#2449 (issue #2448): RegisterDynamicWorkflow accepts the factory, but go-sdk's dynamic execution path panics on it until that fix ships. A go.temporal.io/sdk bump to the first release containing it is required before dynamic dispatch runs.
datashaman
force-pushed
the
feat-dynamic-workflow
branch
from
July 10, 2026 12:32
b6563aa to
d24901b
Compare
datashaman
added a commit
to datashaman/sdk-php
that referenced
this pull request
Jul 10, 2026
Add `#[WorkflowMethod(dynamic: true)]` to declare a dynamic (catch-all) workflow — invoked when the worker receives a workflow whose type name is not statically registered. WorkflowReader flags the prototype; StartWorkflow falls back to the dynamic prototype when no named workflow matches; and the GetWorkerInfo handshake advertises `dynamic` so the RoadRunner temporal plugin can register a Go dynamic-workflow proxy for it. As in the other SDKs (Go panics, Python raises), at most one dynamic workflow may be registered per worker — WorkflowCollection enforces this. Enables Dynamic Workflow support in the PHP SDK (PHP and TypeScript are the only SDKs without it). End-to-end dispatch also requires temporalio/roadrunner-temporal#784 (register the dynamic proxy) and temporalio/sdk-go#2449 (execute a factory-registered dynamic workflow).
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.
What
Lets a PHP worker register a dynamic (catch-all) workflow — invoked for any workflow type name that has no statically-registered handler. The host already registers a single shared
WorkflowDefinitionFactoryproxy (wDef) under each declared name; this adds the ability to register that same proxy viaworker.RegisterDynamicWorkflowwhen the PHP worker declares a workflow as dynamic.internal/worker_info.go— newWorkflowInfo.Dynamicfield, populated from thedynamickey the PHPGetWorkerInfohandshake emits.aggregatedpool/workers.go— when a declared workflow isDynamic, register it viaRegisterDynamicWorkflow(reusingwDef, which forwards the real workflow type name to PHP) and skip named registration for it.Why
Enables Dynamic Workflow support in the PHP SDK — PHP and TypeScript are the only SDKs without it. It lets applications that author workflows at runtime (e.g. UI-driven pipeline/automation builders) give each workflow its own type name — real identity in the Web UI — while a single PHP handler interprets it, with no codegen or per-workflow deploy. Companion PHP change: temporalio/sdk-php (declares the dynamic workflow + emits the
dynamicWorkerInfofield).Dependency — must land first
Requires temporalio/sdk-go#2449 (issue temporalio/sdk-go#2448).
RegisterDynamicWorkflowaccepts theWorkflowDefinitionFactorywDef, but go-sdk's dynamic execution path currently reflects it as a function and panics (reflect: call of reflect.Value.Call on ptr Value). This repo pinsgo.temporal.io/sdk v1.44.1, so a bump to the first release containing that fix is needed before dynamic dispatch actually runs at execution time. I'll add that commit once the release is available; until then this compiles and registers, but a dynamic task panics at execution.Testing
go build ./...andgo vet ./...clean.rrbuilt from this change + a local go-sdk carrying #2449 + a forkedsdk-php: starting an unregistered type (pipeline-blog-publish) is caught by the shared proxy, dispatched to the PHP dynamic handler (which reads the real type viaWorkflow::getInfo()), and completes →{"dispatchedType":"pipeline-blog-publish"}. Without the go-sdk bump, the same run fails with aWorkflowTaskFailedcarrying the reflect panic.dynamicWorkerInfofield is emitted).Backwards compatibility
Additive.
Dynamicdefaults tofalse(omitted from the handshake JSON), so existing workers register exactly as before.