Commit Graph

3 Commits

Author SHA1 Message Date
kami 27e8acc592 fix: guard the integrity sweep against wiping the library on a dead mount
The sweep stats every track path and marks unreadable files missing, with no
check that /music is mounted. An unmounted or misbehaving bind would fail
every stat and mark the entire library missing in one pass; the ratio is only
recoverable by a full rescan.

Three guards, cheapest first:
  - liveness: probe a sample of existing track paths before doing anything;
    abort if none are readable
  - ratio: abort mid-sweep if the missing fraction crosses a threshold,
    leaving already-marked rows alone rather than rolling back a partial pass
  - progress: keyset pagination over id with the cursor persisted in
    integrity_sweep_state, so a sweep aborted or restarted mid-run resumes
    instead of re-walking from the top and re-marking

The repair-corrupted-metadata script shares the same failure mode and gets
the same abort path.

REVIEW-2026-07-30.md secondary finding: integrity sweep has no mount check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 23:58:38 +04:00
kami ee43995e96 fix: give the worker a pg Pool and real transactions
The worker ran every job through a single pg Client while BullMQ was
configured with concurrency: 10. A Client is one connection with one
protocol stream and no queueing: ten concurrent jobs interleave on it, and
any BEGIN/COMMIT is shared by all of them, so an unrelated job's failure can
roll back another's work and a rollback can discard a third's committed
intent.

Switched to a Pool, added a small withTransaction(pool, fn) helper that
takes a dedicated connection per transaction, and threaded a Queryable
interface through the services so they accept either a pool or a pooled
client. Both reprocess_artists merge blocks — the artist merge and the
duplicate-album merge — now run inside withTransaction; previously a failure
partway through left artists merged and their tracks unmoved.

integrity.service and cleanup.service get only the constructor type change
here so this commit compiles; their own fixes follow in the next two
commits. cleanup.service's BEGIN/COMMIT-on-a-Pool is therefore still wrong
at this commit and is replaced wholesale by the hard-delete commit.

REVIEW-2026-07-30.md finding 4 (and the concurrency note in finding 3).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 23:58:31 +04:00
kami 737bf19fd1 initial state: muzick music player + recommendation engine 2026-07-14 01:35:52 +04:00