/** * @pwngh/economy-lab * * Copyright (c) Preston Neal * * This source code is licensed under the MIT license found in the * LICENSE.md file in the root directory of this source tree. * * @license MIT */ import type { Reservations } from '../netting.js'; import type { Store } from '../ports.js'; import type { WorkerCtx } from '../contract.js'; /** The structural subset of WorkerCtx the sweeps need; the worker passes its full ctx through. */ export type OrphanSweepCtx = Pick; export interface OrphanSweepSummary { /** Session ids inspected this run (bounded by `limit`). */ scanned: number; /** Unsettled sessions and the age of their newest movement. */ orphans: Array<{ sessionId: string; ageMs: number; }>; /** Sessions this run finished (opt-in via `settleOlderThanMs`). */ settled: Array<{ sessionId: string; mode: string; }>; /** Prefund escrow remainders this run returned to their owners (crashed-refund repair). */ escrowRefunds: Array<{ sessionId: string; userId: string; minor: string; }>; failed: Array<{ sessionId: string; code: string; }>; /** Set when the store offers no session enumeration. */ skipped?: true; } export interface OrphanSweepInput { now: number; /** Max sessions to inspect per run; enumeration resumes from the top next run. */ limit: number; /** Finish orphans older than this. Absent = report-only (the default; settling moves money). */ settleOlderThanMs?: number; /** * The registry recovered sessions release into. A multi-node host passes its shared registry * so a finished orphan frees the dead node's pending; the default builds one from the store's * counter when present, else a throwaway process registry (release then affects nothing * beyond this run, which is correct for single-node use of the sweep). */ reservations?: Reservations; } /** One sweep pass; see the module doc for the live/dead discrimination the host owes it. */ export declare function sweepOrphanSessions(store: Store, ctx: OrphanSweepCtx, input: OrphanSweepInput): Promise; /** * The prefund repair for one settled session: every escrow account its journaled movements * touched gives its remainder back to the owner's spendable, by the same deterministic txn id * the lane's own refund uses — so lane, orphan sweep, and retention sweep can never double-post * it. */ export declare function refundSessionEscrows(store: Store, sessionId: string, summary: Pick): Promise; /** Epoch ms of the session's newest journal row; 0 when the session has none. */ export declare function newestMovementAt(store: Store, sessionId: string): Promise; /** * Quiesced-maintenance repair for the shared reservation counter: recomputes every account's * journal-derived pending (the sum over unsettled sessions' accepted movements) and adjusts each * counter row to match. This erases the conservative leaks a crash can leave (unflushed * acceptances, a release interrupted mid-run). * * Must run with the tier quiesced — no node accepting movements — because live sessions' * in-flight reservations are indistinguishable from leaks here; running it live would erase * them and reopen the cross-node overdraft window. That makes this an operator action, never a * scheduled sweep. */ export declare function reconcileReservations(store: Store, ctx: OrphanSweepCtx): Promise<{ accounts: number; adjusted: number; }>;