Skip to content

fix(sandbox): make daemon.json read async to stop blocking the event loop - #5336

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/daemon-persistence-sync-read-w1
Jul 28, 2026
Merged

fix(sandbox): make daemon.json read async to stop blocking the event loop#5336
pedrofrxncx merged 1 commit into
mainfrom
fix/daemon-persistence-sync-read-w1

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Source: hardening follow-up — CONTRIBUTING.md rule #1 / CLAUDE.md gotcha #8 explicitly bans sync fs in packages/sandbox/daemon/** because the daemon runs on a single-threaded Bun event loop and Studio tears the daemon down on a single missed health-probe response.

Why it matters: persistence.ts#readConfig used readFileSync to load .decocms/daemon.json. It's not just a boot-time call — orchestrator.ts#fillApplicationDefaults calls it during stepClone, which runs on an already-serving daemon, so every repo clone blocked the event loop (and the health probe) for the duration of that synchronous read.

Fix: switched readConfig to node:fs/promises readFile and made it async, threading await through both call sites (entry.ts's hydrate(), now itself async with a top-level await, and orchestrator.ts's fillApplicationDefaults). Pure behavior-preserving conversion — same validation, same return shape, same error handling — just non-blocking. Updated persistence.test.ts to use the async node:fs/promises helpers and await readConfig(...).

Reviewer check: cd packages/sandbox && bunx tsc --noEmit and bun test packages/sandbox/daemon/persistence.test.ts.

Verified locally: bun run fmt, bunx tsc --noEmit in packages/sandbox (green), and the targeted persistence.test.ts (3 pass). Full CI covers the rest.


Summary by cubic

Make reading .decocms/daemon.json async to stop blocking the daemon’s Bun event loop and prevent missed health probes during repo clones. Behavior is unchanged; the read is now non-blocking.

  • Bug Fixes
    • Switched readConfig to node:fs/promises.readFile and made it async.
    • Propagated await to entry.ts hydrate() (top-level await) and setup/orchestrator.ts fillApplicationDefaults().
    • Updated persistence.test.ts to async fs APIs and await readConfig.

Written for commit 1284562. Summary will update on new commits.

Review in cubic

…loop

readConfig() used readFileSync on the daemon's single-threaded Bun event
loop. It runs from orchestrator.fillApplicationDefaults() during
stepClone — a live-daemon path, not just boot — so every clone blocked
the loop from answering its HTTP health probe for the duration of the
read. Studio tears down a daemon on a single missed probe.

Switch to node:fs/promises readFile and thread the await through both
call sites (entry.ts hydrate, orchestrator.ts fillApplicationDefaults).
@pedrofrxncx
pedrofrxncx merged commit 877536a into main Jul 28, 2026
15 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/daemon-persistence-sync-read-w1 branch July 28, 2026 17:14
decocms Bot pushed a commit that referenced this pull request Jul 28, 2026
PR: #5336 fix(sandbox): make daemon.json read async to stop blocking the event loop
Bump type: patch

- @decocms/sandbox (packages/sandbox/package.json): 1.24.3 -> 1.24.4
- deploy/helm/sandbox-env (chart 0.9.35) (deploy/helm/sandbox-env/values.yaml deploy/helm/sandbox-env/Chart.yaml): image.tag/appVersion -> 1.24.4

Deploy-Scope: both
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.

1 participant