Problem
Both recomputeAllFsr() (src/lib/fsr/compute.ts) and recomputeAllTsrs() (src/lib/tsr/replay.ts) guard against concurrent runs with a session-scoped advisory lock:
- acquire via
prisma.$queryRaw\SELECT pg_try_advisory_lock()``
- release via
prisma.$executeRaw\SELECT pg_advisory_unlock()`in afinally`
With the pooled @prisma/adapter-pg connection (src/lib/prisma.ts, pg.Pool), a bare $queryRaw/$executeRaw runs on whatever idle pool connection is checked out per call — so the lock and the unlock can land on different backend sessions. When that happens the unlock is a no-op and the original session keeps the lock until that connection is physically closed (it isn't — it's recycled into the pool).
Observed symptom: running the FSR bootstrap twice in quick succession, the second run returns outcome: "skipped_locked" even though no recompute is actually in progress.
Severity
Low. The daily crons are single-flight at the platform level, and each recompute is the last meaningful step, so worst case is a skipped recompute → one day of stale ratings. No corruption, no crash. It is, however, latent and confusing, and it's duplicated across two call sites.
Fix
Switch to a transaction-scoped lock so acquire + release are guaranteed same-connection and auto-released on commit/rollback:
SELECT pg_try_advisory_xact_lock(<id>)
acquired as the first statement inside the recompute's own interactive $transaction, with the lock automatically released when that transaction ends. (FSR already does its writes in one interactive transaction, so this composes cleanly; TSR would need its lock + write wrapped together, or a short pinned transaction around the lock lifecycle.)
Apply the same change to both recomputeAllFsr and recomputeAllTsrs in the same PR — keeping two copies of a subtly-broken lock pattern is worse than one.
Context
Identified during the FSR engine build (branch staging). FSR uses lock id 732402, TSR uses 732401.
Problem
Both
recomputeAllFsr()(src/lib/fsr/compute.ts) andrecomputeAllTsrs()(src/lib/tsr/replay.ts) guard against concurrent runs with a session-scoped advisory lock:prisma.$queryRaw\SELECT pg_try_advisory_lock()``prisma.$executeRaw\SELECT pg_advisory_unlock()`in afinally`With the pooled
@prisma/adapter-pgconnection (src/lib/prisma.ts,pg.Pool), a bare$queryRaw/$executeRawruns on whatever idle pool connection is checked out per call — so the lock and the unlock can land on different backend sessions. When that happens the unlock is a no-op and the original session keeps the lock until that connection is physically closed (it isn't — it's recycled into the pool).Observed symptom: running the FSR bootstrap twice in quick succession, the second run returns
outcome: "skipped_locked"even though no recompute is actually in progress.Severity
Low. The daily crons are single-flight at the platform level, and each recompute is the last meaningful step, so worst case is a skipped recompute → one day of stale ratings. No corruption, no crash. It is, however, latent and confusing, and it's duplicated across two call sites.
Fix
Switch to a transaction-scoped lock so acquire + release are guaranteed same-connection and auto-released on commit/rollback:
acquired as the first statement inside the recompute's own interactive
$transaction, with the lock automatically released when that transaction ends. (FSR already does its writes in one interactive transaction, so this composes cleanly; TSR would need its lock + write wrapped together, or a short pinned transaction around the lock lifecycle.)Apply the same change to both
recomputeAllFsrandrecomputeAllTsrsin the same PR — keeping two copies of a subtly-broken lock pattern is worse than one.Context
Identified during the FSR engine build (branch
staging). FSR uses lock id732402, TSR uses732401.