Repository navigation
feat(runtime): instance registry written by dev and serve - #52
Merged
Merged
Conversation
One synchronous loop blocks the only thread serving requests, so every URL stops answering at once with nothing in the logs. A Worker now expects a heartbeat from the main thread; after 15s (DUNE_WATCHDOG_TIMEOUT_MS) of silence it writes a report to <site>/.dune/hangs/ (in-flight requests, plus a native stack sample on macOS) and SIGKILLs the process so a supervisor can restart it. DUNE_WATCHDOG=warn reports only, =off disables. SIGKILL rather than Deno.exit(): an exit requested from a Worker only ends the Worker, the spinning main thread carries on. A Worker also can't be unref'd, so serve's graceful-shutdown paths stop it explicitly. The main thread additionally logs a warning when its own timer ran over a second late. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Each running instance records itself in ~/.dune/instances/<pid>.json (pid, process start time, mode, root, title, port, version) and removes the record on a graceful exit. Readers verify a record against the live process (alive and same start time, since pids are reused) and prune stale ones. Groundwork for `dune ps` to list instances from what each one says about itself instead of parsing command lines and lsof; nothing reads it yet. Refs #42 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Oct 26, 2026
Merged
…imately busy Review of #51 and a test of my own turned up false-kill cases and a kill that could fail to happen: - A process suspended and resumed (laptop sleep, Ctrl-Z/SIGSTOP) was killed on resume: confirmed by SIGSTOPping a watched process for 4s. The stall clock is now monotonic (performance.now()), and a gap in the Worker's own ticks resets it instead of firing. - Startup gets its own, much longer limit (2 min) until the server calls ready(), so a big site's initial indexing can't put a supervised process into a kill/restart loop. - watchdogProgress() (rate-limited heartbeat for long synchronous loops) and watchdogGrace() (capped, auto-expiring, nestable busy window), exported as @dune/core/watchdog. - Under --inspect/--inspect-brk the default becomes warn. - The kill no longer depends on the report: writing it is raced against a timeout, and a failed Deno.kill is logged instead of silencing the watchdog. - Reports are pruned to the newest 20, and path segments over 24 characters are masked before they are written. Refs #42 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md # src/cli/dev.ts # src/cli/serve.ts
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.
Refs #42
Stacked on #51 (base is
feat/event-loop-watchdog; I'll retarget tomainonce #51 merges). The branch also contains a merge of #51's latest review fixes; the registry itself isinstance-registry.tsplus its two call sites.What
dune dev/dune serverecord themselves in~/.dune/instances/<pid>.json(DUNE_REGISTRY_DIRoverrides): pid, process start time, mode, site root, title, port,@dune/coreversion. Removed on graceful exit (serve's two shutdown paths, plus anunloadbackstop).A SIGKILL, crash or default signal termination leaves the file behind, so every reader checks that the pid is alive and has the recorded start time (
ps -o lstart=; pids get reused) and deletes records that fail. Writes are atomic (temp file + rename). Nothing here can stop a server from starting: all failures are swallowed. Unix only, likedune ps; where the start time can't be read nothing is written.Nothing reads it in this PR; #53 makes
dune psuse it (and keeps the command-line heuristics as the fallback for older versions and for processes that hang during bootstrap, which are never registered because the record is written after bootstrap).A change to the plan
I'd planned for the watchdog to also mark an instance
hungin the registry. That only helps inwarn/offmode (in the default mode a hung process is killed within seconds). #53 probes/health/liveinstead, which needs no cooperation from the stuck process and also works for unregistered ones.Verification
deno lint src/;deno test -A --unstable-kv tests/runtime tests/cli: passestests/runtime/instance_registry_test.ts(9 tests): fields round-trip, no leftover temp file, repeat-safe unregister, dead process pruned, live pid with a different start time pruned, garbage and unrelated files tolerated, missing directory, unwritable location doesn't throw, a normally exiting process leaves no record.Not done
title: null.dune devhas no graceful-exit hook, so its record relies on theunloadhandler and pruning.🤖 Generated with Claude Code