/** * The process-local registry of live claim attempts for one scope of an * application primitive (WFT-84, WFT-85), and the lease-commit serial that * fences reconciliation against it. * * Registrations live here rather than in durable storage because an * `AbortSignal` is process-local by construction; the registry is what lets a * cancellation, settlement, or maintenance pass in this process reach a * claimant in this process. Another process learns from renewal instead. * * @module core/application-primitive-attempt-registry */ import type { Storage } from '../storage/interface.ts'; /** * One live attempt in this process: its abort controller plus the callback that * forgets it from the handle that claimed it. * * Carrying the release alongside the controller is what lets a *sibling* handle * — one running maintenance, or settling with a token it was handed — release * ownership from the handle that actually owns it. Without that, the claiming * handle's ownership set leaks one entry per attempt settled elsewhere. */ export type AttemptRegistration = { readonly controller: AbortController; readonly release: () => void; /** * The subject (command, delivery) the attempt belongs to, so a caller-supplied * token cannot release another subject's attempt. */ readonly subjectId: string; /** * The process-local lease-commit serial this attempt's lease landed under, or * `null` while its compare-and-swap is still in flight. A reconciliation from * a durable snapshot releases only attempts that committed BEFORE the * snapshot was read: a snapshot cannot speak for a lease that landed after it. */ committedSerial: number | null; }; /** * The process-local attempt registry for one scope: a map from attempt token * to registration, with a secondary index from subject id to the tokens * registered for it, so reconciling one subject costs its own attempts rather * than a walk over every live claim in the scope. */ export declare class AttemptRegistry extends Map { #private; constructor(); set(attemptToken: string, registration: AttemptRegistration): this; delete(attemptToken: string): boolean; clear(): void; /** The tokens currently registered for one subject, as a snapshot safe to release from. */ tokensFor(subjectId: string): string[]; } /** Record one more lease committed by this process and return its serial. */ export declare function nextLeaseCommitSerial(): number; /** The serial of the latest lease this process committed; read before a snapshot to fence reconciliation. */ export declare function leaseCommitSerial(): number; /** * Acquire the shared attempt-controller registry for one scope in this process. * Every acquisition is balanced by {@link releaseAttemptControllerRegistry} * from the handle's `dispose()`. */ export declare function attemptControllerRegistry(storage: Storage, primitive: string, namespace: string, scopeId: string): AttemptRegistry; /** * Release one handle's hold on a scope registry. * * The scope is forgotten once no handle holds it and no attempt is live in it. * A service that creates short-lived handles for many resource ids over one * long-lived storage would otherwise retain a map per historical resource. A * live attempt owned by a sibling handle keeps the scope until it settles. */ export declare function releaseAttemptControllerRegistry(storage: Storage, primitive: string, namespace: string, scopeId: string): void; /** Whether this process still tracks a registry for the scope. Diagnostics and tests. */ export declare function hasAttemptControllerScope(storage: Storage, primitive: string, namespace: string, scopeId: string): boolean;