LibreChat/api/server
Danny Avila c7f3f8983b feat: scheduled-run lifecycle epoch, durable resume lease, DB-enforced capacity
Foundation for the new merge blockers. Collapses B1/B3/B8/B10 (and B7's per-run half)
into one coherent ScheduleRun state machine rather than four overlapping patches, since
they all mutate the same row.

B1 - pause epoch + CAS: ScheduleRun.resumeSeq is a monotonic per-occurrence segment
counter, incremented by every resume reservation. recordRunOutcome's pause branch now
CASes on expectResumeSeq (both the guard read and the row flip), so a stale
requires_action callback from a superseded segment can no longer demote a run that a
resume already promoted. resume.js threads its segment's resumeSeq into the re-pause.

B3 - durable resuming state: promoteRunToStarted (whose lossy 'missing' -> 'ok' admitted
both racers) is replaced by acquireResumeLease/markResumeClaimed/commitResumeLease/
releaseResumeLease. The lease is holder-fenced and deadline-bounded, and records whether
the approval was already consumed: a PRE-claim crash is adoptable (rolled back to
requires_action, slot freed, approval stays actionable), a POST-claim crash must roll
forward. resume.js drives all four transitions.

B8 - atomic global capacity: a unique partial index on {capacitySlot} where
status:'started' makes fireConcurrency a DB-enforced bound instead of a read-then-compare
count. Both admissions (fire insert, resume promotion) claim a slot in the SAME write via
withCapacitySlot, so two admissions of DIFFERENT schedules can no longer both pass a
cap-1 check. Capacity is now refused BEFORE inserting, so the old reserve-then-rollback
path is gone.

B10 - settlement: requestRunAbort records abortRequestedAt WITHOUT freeing the slot; the
slot is released only by a terminal outcome, i.e. when the generation owner confirms the
run actually stopped. Aborted runs therefore keep counting capacity until settled.

B7 (per-run half) - ScheduleRun.configRevision captures the schedule's revision at claim
time; applyTerminalBookkeeping filters on it so a run started under older config cannot
apply counters or auto-disable a schedule the owner has since edited. Schedule.
configRevision is bumped ONLY by updateScheduleById (owner edits), atomically with the
claimToken rotation.

B2 (field only) - User.deletionRequestedAt added as the durable deletion-barrier field;
the barrier logic itself is not wired yet.

Also fixes a latent discriminator bug: isActiveRunConflict matched any duplicate-key
lacking scheduledFor, so the new {capacitySlot} index would have been misread as a
per-schedule overlap. It now matches scheduleId exactly.

Absent fields disable each fence, so existing rows/schedules keep current behavior and
no migration is required.
2026-07-22 23:51:28 -04:00
..
controllers feat: scheduled-run lifecycle epoch, durable resume lease, DB-enforced capacity 2026-07-22 23:51:28 -04:00
middleware 🔍 refactor: Surface primary OpenID JWT failure reason in auth failure log (#14346) 2026-07-20 21:05:20 -04:00
routes fix: Codex round — owner-edit rollback, resume self-overlap, retention count, evidence on failure 2026-07-22 12:42:19 -04:00
services feat: scheduled-run lifecycle epoch, durable resume lease, DB-enforced capacity 2026-07-22 23:51:28 -04:00
utils 🔄 feat: Continue Shared Conversations as Personal Copies (#13714) 2026-06-24 16:27:01 -04:00
cleanup.js
experimental.js fix: Codex round 7 - checkpoint prune, topology env, SSE denial, wire shape, pause recovery 2026-07-22 14:43:50 -04:00
index.js fix: Codex round 7 - checkpoint prune, topology env, SSE denial, wire shape, pause recovery 2026-07-22 14:43:50 -04:00
index.metrics.spec.js ⚖️ feat: Add Operational Prometheus Metrics (#13265) 2026-05-22 20:47:41 -04:00
index.spec.js fix: Codex round 6 - scheduled abort/quiesce/index-gate hardening 2026-07-22 13:54:22 -04:00
socialLogins.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
socialLogins.spec.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
telemetry.js
telemetry.spec.js