Skip to content

fix(runtime): seed registry with existing entries before watching#65

Merged
john-royal merged 2 commits into
mainfrom
fix/registry-watcher-initial-snapshot
Jul 16, 2026
Merged

fix(runtime): seed registry with existing entries before watching#65
john-royal merged 2 commits into
mainfrom
fix/registry-watcher-initial-snapshot

Conversation

@john-royal

Copy link
Copy Markdown
Collaborator

Fixes #63.

Problem

On platforms where CLOUDFLARE_RUNTIME_FILE_SYSTEM_SUPPORTS_WATCHER defaults to true, RegistryLive initialized its SubscriptionRef with an empty map and relied on fs.watch events to populate it. Native watchers only report future changes, so a subscriber could not resolve workers whose registry entries existed before it started — resolution only began after a later filesystem event, typically the provider's 30-second heartbeat. This broke cross-process service bindings whenever the provider started before the consumer.

Fix

  • Read the registry directory once during layer construction and seed the SubscriptionRef with the result, so entries written before the process started are resolvable on the first read in both watcher and polling modes.
  • In watcher mode, merge one synthetic event into the watch stream so the directory is re-read once the watcher is running. This covers a change made in the window between the initial snapshot and the watcher subscription.
  • The reads run through a sequential Stream.mapEffect, so an older snapshot cannot overwrite a newer watcher-triggered read.

Tests

Added the regression test suggested in the issue: a provider registry writes its entry, then a second registry sharing the same CLOUDFLARE_RUNTIME_HOME is constructed and its first read must resolve the provider. The test runs in both watcher and polling modes and fails on main in both (the polling fallback's first read was also racy, since its initial directory read ran in a forked fiber).

Verified with bun run check and the registry, durable object, queue, and workflow test suites.

Made with Cursor

The watcher-based registry initialized its SubscriptionRef with an empty
map and relied on future filesystem events to populate it, so entries
written before the subscriber started were invisible until the
provider's next 30-second heartbeat. The polling fallback did not have
this problem because it reads the directory immediately.

Read the directory once during layer construction to seed the ref, and
trigger one extra read after the watcher is subscribed so a change made
between the initial snapshot and the watcher subscription is not lost.
Reads are run sequentially so an older snapshot cannot overwrite a
newer watcher-triggered one.

Fixes #63

Co-authored-by: Cursor <cursoragent@cursor.com>
@alchemy-version-bot

alchemy-version-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Install the packages built from this commit:

@distilled.cloud/cloudflare-rolldown-plugin

bun add https://pkg.distilled.cloud/cloudflare-rolldown-plugin/8902f84

@distilled.cloud/cloudflare-runtime

bun add https://pkg.distilled.cloud/cloudflare-runtime/8902f84

@distilled.cloud/cloudflare-vite-plugin

bun add https://pkg.distilled.cloud/cloudflare-vite-plugin/8902f84

@john-royal
john-royal merged commit bb379bf into main Jul 16, 2026
18 of 25 checks passed
@john-royal
john-royal deleted the fix/registry-watcher-initial-snapshot branch July 16, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Registry watcher misses entries written before subscriber starts

1 participant