feat(nitro): auto-start the World at server boot#2550
Merged
Conversation
Re-introduce the dropped auto startup plugin so self-hosted Nitro apps (Nitro v2/v3, Nuxt, Express/Hono/Fastify on Nitro) recover in-flight runs after a restart with no manual wiring. The previously-reverted version imported the runtime via a build-time `file://` URL, which collided with the bundled flow handler's copy of the same file (CJS/ESM dual-load -> ERR_INTERNAL_ASSERTION, 500ing the flow route). This version instead emits a real plugin file in the build dir that imports `workflow/runtime` via a *bare* dynamic import — mirroring a hand-written Nitro plugin — so the bundler resolves and dedupes it with the flow handler's runtime. `ensureWorldStarted()` caches its start promise on `globalThis`, so the World starts exactly once. Gated off Vercel deploys (the Vercel World's start() is a no-op). Removes the manual `start-pg-world.ts` workbench workaround and updates the recovering-in-flight-runs docs to note Nitro starts the World automatically. Co-Authored-By: Claude Opus 4.8 <[email protected]>
🦋 Changeset detectedLatest commit: 2ae642b The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
Contributor
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests▲ Vercel Production (1 failed)nuxt (1 failed):
📦 Local Production (127 failed)nuxt-stable (127 failed):
🐘 Local Postgres (126 failed)nuxt-stable (126 failed):
Details by Category❌ ▲ Vercel Production
✅ 💻 Local Development
❌ 📦 Local Production
❌ 🐘 Local Postgres
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
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.
Context
#2544 added
ensureWorldStarted()and wired boot-time World recovery across the framework integrations — but for Nitro it had to settle for manual wiring (a hand-writtenserver/plugins/workflow.ts) after its auto-plugin was reverted. The auto-plugin imported the runtime via a build-timefile://URL, which collided with the bundled flow handler's copy of the same file:That CJS/ESM dual-load 500'd the flow route and broke the nitro+postgres e2e, so the plugin was dropped.
This PR brings the auto-plugin back — fixed — so self-hosted Nitro apps (Nitro v2/v3, Nuxt, Express/Hono/Fastify on Nitro) recover in-flight runs after a restart with no manual wiring.
The fix
Instead of a virtual module doing a
file://dynamic import,@workflow/nitronow emits a real plugin file in the build dir that importsworkflow/runtimevia a bare dynamic import — mirroring the hand-written Nitro plugin that already works (and that #2544'sstart-pg-world.tsused). The bundler resolves and dedupes it with the flow handler's runtime, so there's no second physical module loaded as both CJS and ESM.ensureWorldStarted()caches its start promise onglobalThis, so the World starts exactly once. Registration is gated off Vercel deploys (the Vercel World'sstart()is a no-op).Changes
@workflow/nitro—addStartupPlugin(): generate + register the boot plugin (gated!isVercelDeploy).workbench/nitro-v3/plugins/start-pg-world.ts+ itsnitro.config.tsentry.recovering-in-flight-runsdocs: Nitro/Nuxt now say "no action required."@workflow/nitro, minor).Test plan
Verified on
workbench/nitro-v3(local world), dev and production build:world.start()creates the local data dir before any request (no first-request dependency).ERR_INTERNAL_ASSERTIONafter the boot plugin has loaded the runtime — the exact regression that reverted the original is gone..output/server/index.mjs(nofile://runtime import).restart-recovery.test.ts, the case that originally broke) requires a Postgres DB I couldn't run locally — please let CI exercise it before merge.🤖 Generated with Claude Code