Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit c56cc3f70588dee30f0bdc267dd3ab5551ac21a0
parent 0eb8ffc8cbbdc2f3a5c7e2268c8dd81c82b2c4c1
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Wed, 30 Sep 2026 09:21:41 -0400

common: review M1 — inFlightPerLocation is at most 8, half the editor's 16 file-access threads, so one drive that stops answering cannot hold every one; the hint, SETTINGS.md and the tests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
MSETTINGS.md | 2+-
Mcommon/lib/storageHealthTimings.test.ts | 2+-
Mcommon/lib/storageHealthTimings.ts | 15++++++++++-----
Meditor/app/storage/lib/healthTimingsForm.test.ts | 8++++----
4 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/SETTINGS.md b/SETTINGS.md @@ -556,7 +556,7 @@ Per entry — each entry spells its own values. | `passIntervalMs` | `15000` | How often the health pass reads each location's disk counters, in ms (default 15000, 5000–300000). A stall that starts between two passes is seen by the next, or at once by a page's read. A save on /storage re-arms the pass's timer at once; a hand edit, at the next pass. Two counter samples are compared only when at least min(10 s, this − 5 s) apart, a spacing never less than half of this. | | `probeTimeoutMs` | `3000` | How long the health pass waits, in ms (default 3000, 500–30000), for the child `stat` of a root where no disk can be named (a timeout counts as not answering) and for the `findmnt` that names a root's disk (a timeout names none that pass). Takes effect on the next pass. | | `clearAfterCleanPasses` | `2` | How many clean answers in a row clear a location marked not answering (default 2, 1–10). Each health pass is one answer, and so is a Refresh on /storage; a miss in between starts the count again. Takes effect on the next answer. | -| `inFlightPerLocation` | `4` | How many reads through the watchdog may be on one location's drive at once (default 4, 1–16); the rest wait in the editor's own queue, so a stall mid-walk holds this many of Node's threads, not all of them. Keep it under `UV_THREADPOOL_SIZE` (16 in the editor's start script). Takes effect on the next read. | +| `inFlightPerLocation` | `4` | How many reads through the watchdog may be on one location's drive at once (default 4, 1–8); the rest wait in the editor's own queue, so a stall mid-walk holds this many of Node's threads, not all of them. At most 8, half of `UV_THREADPOOL_SIZE` (16 in the editor's start script and the container), so one drive that stops answering cannot hold every thread. Takes effect on the next read. | Default: diff --git a/common/lib/storageHealthTimings.test.ts b/common/lib/storageHealthTimings.test.ts @@ -102,7 +102,7 @@ test("a settings.json round trip: a tuned value is written, read back, and a def process.env.SETTINGS_FILE!, JSON.stringify({ storage: { locations: [], health: { inFlightPerLocation: 99 } } }), ); - assert.deepEqual(getSettings().storage.health, { inFlightPerLocation: 16 }); + assert.deepEqual(getSettings().storage.health, { inFlightPerLocation: 8 }); }); test("the timings survive the mediaRoot migration (a block with no locations)", () => { diff --git a/common/lib/storageHealthTimings.ts b/common/lib/storageHealthTimings.ts @@ -52,7 +52,11 @@ export const HEALTH_TIMING_BOUNDS: Readonly< passIntervalMs: { min: 5_000, max: 300_000 }, probeTimeoutMs: { min: 500, max: 30_000 }, clearAfterCleanPasses: { min: 1, max: 10 }, - inFlightPerLocation: { min: 1, max: 16 }, + // At most HALF the editor's 16 file-access threads (`UV_THREADPOOL_SIZE` in + // `start` and the container): one drive that stops answering holds this + // many of them, and at 16 it would hold every one — the outage the cap + // exists to bound. + inFlightPerLocation: { min: 1, max: 8 }, }); // In the order the form shows them. @@ -126,7 +130,7 @@ export const HEALTH_TIMING_HINTS: Readonly<Record<HealthTimingKey, string>> = Ob clearAfterCleanPasses: "How many clean checks in a row it takes before a drive marked not answering is used again.", inFlightPerLocation: - "How many reads may be on one drive at once; the rest wait their turn, and are refused if it stops answering. Keep it well under the editor's 16 file-access threads: a drive that stops answering holds this many of them.", + "How many reads may be on one drive at once; the rest wait their turn, and are refused if it stops answering. At most 8, half the editor's 16 file-access threads: a drive that stops answering holds this many of them.", }); // SETTINGS.md's `storage.health` table. @@ -154,8 +158,9 @@ export const STORAGE_HEALTH_SETTINGS_FIELD_DOCS: FieldDocs<StorageHealthSettings "health pass is one answer, and so is a Refresh on /storage; a miss in between starts the count " + "again. Takes effect on the next answer.", inFlightPerLocation: - "How many reads through the watchdog may be on one location's drive at once (default 4, 1–16); the " + + "How many reads through the watchdog may be on one location's drive at once (default 4, 1–8); the " + "rest wait in the editor's own queue, so a stall mid-walk holds this many of Node's threads, not " + - "all of them. Keep it under `UV_THREADPOOL_SIZE` (16 in the editor's start script). Takes effect on " + - "the next read.", + "all of them. At most 8, half of `UV_THREADPOOL_SIZE` (16 in the editor's start script and the " + + "container), so one drive that stops answering cannot hold every thread. Takes effect on the next " + + "read.", }; diff --git a/editor/app/storage/lib/healthTimingsForm.test.ts b/editor/app/storage/lib/healthTimingsForm.test.ts @@ -49,7 +49,7 @@ test("a value in range is kept, trimmed; one equal to its default is not written passIntervalMs: String(HEALTH_TIMING_DEFAULTS.passIntervalMs), probeTimeoutMs: "500", clearAfterCleanPasses: "3", - inFlightPerLocation: "16", + inFlightPerLocation: "8", }), ), { @@ -58,7 +58,7 @@ test("a value in range is kept, trimmed; one equal to its default is not written budgetMs: 4_000, probeTimeoutMs: 500, clearAfterCleanPasses: 3, - inFlightPerLocation: 16, + inFlightPerLocation: 8, }, }, ); @@ -69,9 +69,9 @@ test("out of range is refused with the field, the range and the value — not cl ok: false, error: "Read budget must be between 500 and 60000 ms (got 200 ms).", }); - assert.deepEqual(parseHealthTimingsForm(form({ inFlightPerLocation: "17" })), { + assert.deepEqual(parseHealthTimingsForm(form({ inFlightPerLocation: "9" })), { ok: false, - error: "Reads at once per drive must be between 1 and 16 (got 17).", + error: "Reads at once per drive must be between 1 and 8 (got 9).", }); assert.deepEqual(parseHealthTimingsForm(form({ clearAfterCleanPasses: "0" })), { ok: false,