fix(cloudflare/workers): keep the previous dev worker instance serving until its replacement starts#863
Draft
sam-goodwin wants to merge 1 commit into
Draft
fix(cloudflare/workers): keep the previous dev worker instance serving until its replacement starts#863sam-goodwin wants to merge 1 commit into
sam-goodwin wants to merge 1 commit into
Conversation
…g until its replacement starts (#859) Under alchemy dev, a reconcile that replaced a Worker instance ("Changes detected, interrupting existing instance") tore down the running workerd — and deleted its dev-registry entry — before the replacement completed runtime.start. For DO/container hosts, whose start includes docker image prep, that dark window spans seconds to minutes and re-opens on every change; cross-script DO bindings resolve through the registry and 503 with 'Durable Object "X" defined in worker "y" not found' the whole time. Make the serve path make-before-break: - workerd scopes are forked from the provider root scope, not the instance scope, so tearing down an instance's bundle watcher no longer kills the running workerd; the last good instance keeps serving until the replacement's first serve completes. - serveWith starts the replacement first, cuts the proxy over, then closes the previous scope. Registry safety for the shared key comes from owner-aware entry removal in cloudflare-runtime (cloudflare-tools#72), which unblocks reverting the close-old-first ordering #812 introduced. - delete/external-mode teardown now closes the workerd scope explicitly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Install the packages built from this commit: alchemy bun add alchemy@https://pkg.ing/alchemy/4e3eb4e@alchemy.run/better-auth bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/4e3eb4e@alchemy.run/pr-package bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/4e3eb4e |
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.
Fixes #859.
Under
alchemy dev, a reconcile that replaces a Worker instance ("Changes detected, interrupting existing instance") tore down the running workerd — and deleted its dev-registry entry — before the replacement completedruntime.start. For DO/container hosts, whose start includes docker image prep, that dark window spans seconds to minutes and re-opens on every change. Cross-script DO bindings resolve through the registry, so consumers 503 with exactly the reported error for the whole window:I reproduced the issue's exact forensic state live (host worker present only as its stable-port proxy, no
--debug-portinstance, no registry entry, "Changes detected" logged with no subsequent "Started") — it is the window between an instance interrupt and the replacement's serve completing, held open by churn or a slow container start.The serve path is now make-before-break:
const serveWith = (worker, bundle, proxy) => Semaphore.withPermits(serveLock(worker.id), 1)( - // close previous workerd, THEN start the replacement (dark window) - Scope.close(previous) → runtime.start(...) + // start the replacement while the previous instance keeps serving + // (and stays registered), then cut the proxy over and close it + runtime.start(...) → proxy.set(url) → Scope.close(previous) )reconcilereplacement, sibling-triggeredrestartWorker, and rebuilds all included).delete/dev: externalteardown closes the workerd scope explicitly.The regression test drives the real dev topology (persistent provider sidecar via
RpcSpawner+RpcProviderProxy, likealchemy dev): deploy a DO-hosting Effect Worker, redeploy with a changed env var, and assert the old instance still answers mid-handoff and the registry entry never vanishes (stable inode). Onmainit fails with the issue's failure mode (502 ProxyError: Network connection lost); with this change it passes.