fix: skip hourly terms overlapped by a long walk (WealthLedger/backend#54)
Backend verify / commits (push) Skipped
Backend verify / security (push) Successful in 13s
Backend verify / verify (push) Failing after 6m56s

This commit was merged in pull request #93.
This commit is contained in:
2026-10-14 22:43:08 +03:00
parent 14bcb9da5f
commit 6975853656
2 changed files with 89 additions and 2 deletions
@@ -183,7 +183,8 @@ export class TbankSyncRepository {
// The timer only proposes work; this reservation is the durable fence. The
// attempt start (createdAt) is the basis of the next hourly term, including
// failed and interrupted attempts.
// failed and interrupted attempts. After downtime the next tick is due at
// once, so no catch-up queue forms.
reserveHourly(userId: string, runId: string, hourMs: number) {
return this.prisma.$transaction(async (tx) => {
const connection = await tx.tbankConnection.findFirst({
@@ -201,7 +202,16 @@ export class TbankSyncRepository {
});
const now = new Date();
if (previous) {
const due = now.valueOf() - previous.createdAt.valueOf() >= hourMs;
// Terms are hourMs steps from the attempt start; a walk still running
// at a term consumes it. A dead process's attempt has no known end, so
// it consumes only its own term.
const started = previous.createdAt.valueOf();
const ended =
previous.state === 'running' ? started : previous.updatedAt.valueOf();
const dueAt =
started +
Math.max(hourMs, Math.ceil((ended - started) / hourMs) * hourMs);
const due = now.valueOf() >= dueAt;
if (previous.state === 'running') {
if (previous.processRunId === runId) return null;
// A dead process cannot finish its attempt; close it from its