Every bead read costs 23-47s while 6-7 gc dolt-state allocate-port processes stand permanently open, and the provider state file records a dead pid for a server that is alive on the recorded port #34
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Measured 2026-09-25 00:00-00:20Z on the gc-scratch city by gastown.mayor. Every bead operation in the city is 23-47 seconds. It is not fatal — writes land and reads answer — but it gates the whole city: the refinery gates slowly, so its queue stays above the mayor's ceiling, so held work cannot be lifted.
The measurement
The second read of the same bead was slower than the first, so this is not cache-cold warm-up. It looks like queueing.
What is certainly abnormal
gc dolt-state allocate-portruns 6 to 7 concurrently, continuously, sampled three times at 3s intervals during a singlegc bd show:These are not one-per-call transients that exit. There is a standing pile.
A candidate cause, NOT established
.gc/runtime/packs/dolt/dolt-provider-state.jsonreads:pid 37203is dead. The live server is pid79387, started 2026-09-25 14:49:20, and it is listening on the same port the file records:So the recorded port is correct and the recorded pid is not. If the provider-liveness check is pid-based, every gc invocation would conclude the provider is down and re-allocate, which would explain the standing pile. I did not verify that code path, so this is a hypothesis that fits the evidence, not a diagnosis.
There is exactly ONE
dolt sql-serverrunning. An earlier reading of mine suggesting four was a badpgrep/lsofmatching its own process; disregard any such claim.A competing cause, also not excluded
celilo/gascity#8 (hq wisp table never sheds closed rows; dolt rewrites 313 MB of journal an hour and full-GCs every ~24 minutes) and #22 (reaper bulk prune never runs, so closed records accumulate) predict exactly this symptom. Current sizes:
hq being 3.5x the size of the busiest rig store is consistent with #8/#22 still being live. A dolt full-GC cycle would produce slow, variable, queue-shaped reads.
I cannot separate the two from here, and distinguishing them is the investigation this issue exists to hand off rather than to guess at.
Explicitly NOT recommending the obvious workaround
Hand-correcting
pidto 79387 in the provider state file is the tempting one-field fix. I proposed it to the operator and then withdrew it, because:.beads/backup/backup_state.jsonis the precedent, where a fabricated value would have armed a prune of 12,587 records.If someone does try it, the discriminating test is whether the allocate-port pile disappears. If the pile goes and reads stay slow, the cause is #8/#22.
Why this matters beyond latency
The mayor's lift watcher polls the store and its queue-depth check does one
gc bd showper queued bead. At 30s a read, a 5-deep queue takes 2.5 minutes per poll, so a watcher designed for a 2-minute cadence is effectively continuously hammering the store. Any tooling that loops over beads has the same shape. Slow reads here do not just cost time, they change the behaviour of everything built on top.ROOT CAUSE FOUND, and it is neither of the two candidates in the issue body. THE DISK WAS FULL. Correcting this within the hour because the issue as filed sends the next reader after the wrong thing.
174 megabytes free. Sequence, measured 2026-09-26 01:00-02:27Z:
.beads/dolt/hqgrew 361M → 442M in under two hours. That is gascity#8's journal rewrite (hq never sheds closed rows) consuming the last of the volume..beads/dolt-server.logends in a stack trace throughnbs.(*ChunkJournal).Update→nbs.(*NomsBlockStore).updateManifest. Preserved asdolt-server.log.precrash.dolt sql-serverprocess, port 59880 refused, and every gc bead call returnedError: failed to open database: dolt circuit breaker is open: server appears down, failing fast (cooldown 5s).So the 23-47s reads in the issue body were the precursor, not the defect: the volume was filling and every journal write was fighting for space. Then reads went from slow (exit 0) to failing (exit 1), and then the server died.
The
allocate-portpile was a symptom, not a cause. I flagged 6-7 standinggc dolt-state allocate-portprocesses as "certainly abnormal". They are what gc does when the provider is unreachable, which it genuinely was. The stalepid 37203indolt-provider-state.jsonis real and still worth fixing — it is why gc would not START a replacement server, so it turned a recoverable crash into a hard stop — but it did not cause the slowness.Recovery, for whoever hits this next. Freeing space alone did NOT bring it back; gc never restarts the provider. Two steps:
~/.cache,~/.bun/install/cacheand~/Library/Cacheson the operator's approval: 174Mi → 7.3Gi.dolt-server-config.yamlsets nodata_dir, so dolt serves databases from its CWD. Started from.beadsit comes up listening and then logsdatabase not found: hqfor every connection — it looks healthy on the port and serves nothing. It must be:After that:
gc bd showexit 0 in 12s,answering from the rig "celilo" store, data intact across the crash (a bead merged minutes before it died readsclosedcorrectly).What should change in gc, in priority order:
running: truestate file naming a dead pid, so the city cannot self-heal from a crash.Also still true and unrelated:
ERROR native_store_unavailable gate=identity_match reason="database project_id could not be confirmed" scope=/Users/pbanka/hobby/celiloprinted on every call both before and after recovery, while reads answer correctly from the rig store. That looks like its own defect and is not part of this.