Relationships
#4285 Worker set_status writes an output record on every dispatch, so outputs grow without bound
Opened by nckrtl · 11/2/2026
Summary
Each worker status change runs as a full swamp/worker set_status method run, and every method run writes an output record. A dispatch records busy and then idle, so every dispatch writes two outputs under .swamp/outputs/swamp/worker/set_status/. The state resource sets garbageCollection: 20, so its data is bounded, but the outputs are bounded only by the outputs retention window. On a busy serve they pile up to tens of thousands of files.
Version
swamp 20261031.063736.0-sha.e459d219, swamp serve --remote-only --hot-reload --auth-mode token, filesystem datastore, Linux x86_64. Two workers with --concurrency 8.
Measurements (one serve, 2026-11-02)
.swamp/outputs/swamp/worker/set_status/held 24,215 files, growing by about 44 per minute.- A 3-second
straceof serve showed 833realpath-style walks, each about 12readlinkcalls. 48% of them resolved paths under that directory.
Code path
WorkerGateway dispatch calls #recordTransition("worker_busy", () => this.#runModelMethod({ typeArg: WORKER_MODEL_TYPE.normalized, definitionName: workerDefinitionName(name), methodName: "set_status", inputs: { status: "busy", activeDispatchIds } })), and the matching idle transition on completion. Both go through the normal method run path, which saves an output record.
Expected
A status transition costs no output record, or its outputs are bounded like the resource data (keep the last N). Status is control-plane bookkeeping: nobody reads a set_status output, and its count should not grow with the number of dispatches.
Reproduce
- Run
swamp servewith one worker connected. - Dispatch a few hundred short steps, for example a workflow that runs
truein aforEach. - Count the files under
.swamp/outputs/swamp/worker/set_status/: about two per dispatch.
Open
No activity in this phase yet.
Sign in to post a ripple.