Description
On main, workflowEntrypoint() initializes its request-time queue handler through getWorldHandlers(). That accessor intentionally owns a separate build-time-safe cache from getWorld(). As a result, the first runtime operation that calls getWorld() invokes an asynchronous World factory a second time in the same process.
Minimal reproduction
- Configure a World whose async
createWorld() factory increments a counter and returns a stateful World.
- Create a route with
workflowEntrypoint() and invoke it once so the queue handler is initialized.
- Call
getWorld(), as workflow execution does.
- Observe that
createWorld() was called twice.
Expected: request-time route initialization and runtime execution share the single runtime World instance, so the factory is called once.
Actual: route initialization populates the build-time handler cache, while execution independently populates the runtime World cache.
Impact
For stateful self-hosted Worlds, the second construction can create duplicate database pools, listeners, queue workers, or other process-scoped resources. Async factories make this especially likely because initialization often includes configuration loading or connection setup.
Proposed direction
Have the request-time workflowEntrypoint() path obtain its handler view from getWorld() while leaving the public getWorldHandlers() API and its intentionally separate build-time cache unchanged.
Description
On
main,workflowEntrypoint()initializes its request-time queue handler throughgetWorldHandlers(). That accessor intentionally owns a separate build-time-safe cache fromgetWorld(). As a result, the first runtime operation that callsgetWorld()invokes an asynchronous World factory a second time in the same process.Minimal reproduction
createWorld()factory increments a counter and returns a stateful World.workflowEntrypoint()and invoke it once so the queue handler is initialized.getWorld(), as workflow execution does.createWorld()was called twice.Expected: request-time route initialization and runtime execution share the single runtime World instance, so the factory is called once.
Actual: route initialization populates the build-time handler cache, while execution independently populates the runtime World cache.
Impact
For stateful self-hosted Worlds, the second construction can create duplicate database pools, listeners, queue workers, or other process-scoped resources. Async factories make this especially likely because initialization often includes configuration loading or connection setup.
Proposed direction
Have the request-time
workflowEntrypoint()path obtain its handler view fromgetWorld()while leaving the publicgetWorldHandlers()API and its intentionally separate build-time cache unchanged.