/** * The durable application delivery outbox (WFT-85). * * An outbox is a storage-backed, at-least-once delivery queue scoped to one * opaque `(namespace, ownerId)` pair. Enqueue returns a durable receipt before * any transport attempt begins; attempts are fenced so two workers can never * both hold a valid claim; the send is durably marked `attempting` before the * transport is called, so a lost result is never mistaken for a safe retry; * cancellation is durable before it reaches anyone; and every transition * commits atomically with its fleet event when an event sink is configured. * * What it does not do: manufacture exactly-once external effects. A transport * write completing is evidence the adapter reports; only the durable * disposition the outbox commits on it moves a delivery. An unknown outcome is * retried only when the delivery carries external idempotency evidence and its * policy allows it; otherwise it is parked or dead-lettered, never duplicated. * * @module core/outbox */ import type { Storage } from '../storage/interface.ts'; import type { JSONValue } from './json.ts'; import type { ApplicationDeliveryAdmission, ApplicationDeliveryCancellationResult, ApplicationDeliveryCleanupResult, ApplicationDeliveryHeartbeatResult, ApplicationDeliveryInput, ApplicationDeliveryOperatorResult, ApplicationDeliveryOutcome, ApplicationDeliveryReceipt, ApplicationDeliverySettleResult, OutboxCapacity, OutboxClaimResult, OutboxDeliverResult, OutboxDrainReport, OutboxListOptions, OutboxMaintenanceReport, OutboxOptions, OutboxWaitOptions } from './outbox-contract.ts'; /** * A durable, at-least-once application delivery outbox. * * @example * ```ts * import { Outbox, MemoryStorage } from '@lostgradient/weft'; * * await using storage = new MemoryStorage(); * using outbox = new Outbox({ * storage, * namespace: 'bureau', * ownerId: 'agent-7', * adapter: { async send() { return { status: 'acknowledged' }; } }, * }); * * const admission = await outbox.enqueue({ * destinationRef: 'webhook:orders', * kind: 'order.shipped', * payload: { form: 'inline', value: { orderId: 42 } }, * idempotencyKey: 'order-42-shipped', * }); * console.log(admission.status); // 'enqueued' * * const delivered = await outbox.deliverNext(); * console.log(delivered.status === 'settled' && delivered.receipt.state); // 'acknowledged' * ``` */ export declare class Outbox { #private; constructor(options: OutboxOptions); /** The opaque application namespace this outbox is scoped to. */ get namespace(): string; /** The opaque owner identifier this outbox is scoped to. */ get ownerId(): string; /** The durable backend every transition compares and swaps against. */ get storage(): Storage; /** * Offer a delivery. An exact retry of the same idempotency identity returns * the original receipt; a reused key with a different destination, kind, or * payload returns a conflict; a full backlog is rejected before any write. */ enqueue(delivery: ApplicationDeliveryInput): Promise; /** Read one delivery's immutable receipt, or `null` when it is unknown or retired. */ receipt(deliveryId: string): Promise; /** List receipts in enqueue order, bounded and non-consuming. */ list(options?: OutboxListOptions): Promise; /** Current backlog accounting. Counts only. */ capacity(): Promise; /** * Lease the earliest due delivery to one attempt, for a host that drives the * transport itself. Call `beginAttempt()` before sending and `settle()` * after; heartbeat in between. */ claim(options?: { readonly signal?: AbortSignal | undefined; }): Promise; /** Durably mark the current attempt as about to call the transport. */ beginAttempt(options: { readonly deliveryId: string; readonly attemptToken: string; }): Promise; /** Record liveness and extend visibility, clamped to the fixed attempt deadline. */ heartbeat(options: { readonly deliveryId: string; readonly attemptToken: string; readonly transportActivity?: JSONValue | undefined; }): Promise; /** * Settle the current attempt on what the transport reported. A malformed * outcome is treated as `unknown`, never as a retry. */ settle(options: { readonly deliveryId: string; readonly attemptToken: string; readonly outcome: ApplicationDeliveryOutcome; }): Promise; /** Claim, begin, send through the configured adapter, and settle one delivery. */ deliverNext(options?: { readonly signal?: AbortSignal | undefined; }): Promise; /** * Deliver everything due within a bounded budget, running maintenance * between rounds. Reports counts only; `pending` is what the durable header * still holds open when the drain stops. */ drain(options: { readonly timeoutMs: number; readonly signal?: AbortSignal | undefined; readonly pollIntervalMs?: number | undefined; }): Promise; /** Durably request cancellation and abort an in-process attempt. */ requestCancellation(options: { readonly deliveryId: string; readonly reason?: string | undefined; }): Promise; /** Read whether a cancelled delivery's attempt has finished. Non-consuming. */ cleanupState(deliveryId: string): Promise; /** Wait, bounded, for a cancelled delivery's attempt to settle. */ awaitCleanup(options: { readonly deliveryId: string; readonly timeoutMs: number; readonly signal?: AbortSignal | undefined; readonly pollIntervalMs?: number | undefined; }): Promise; /** Return a parked, dead-lettered, or rejected delivery to the queue with at least one more attempt: an unspent budget is kept, a spent one is raised by one. */ retry(options: { readonly deliveryId: string; }): Promise; /** Close a parked `unknown-outcome` delivery as dead-lettered. */ deadLetter(options: { readonly deliveryId: string; readonly reason?: string | undefined; }): Promise; /** * Wait, bounded and abortably, until a delivery is due. `timeoutMs` defaults * to `0`: one check, no wait. */ waitForDue(options?: OutboxWaitOptions): Promise; /** * Run one bounded maintenance pass: recover lapsed leases and retire * terminal receipts past retention. Under `backgroundTasks: 'manual'` this is * the only thing that advances time-driven recovery. */ runMaintenance(now?: number): Promise; /** * Release every process-local resource: the maintenance timer, in-flight * waits, and every attempt-scoped signal this handle holds. Disposal never * deletes durable work; a claim this process held stays leased until it * lapses and maintenance recovers it. */ dispose(): void; /** `using`-compatible disposal. */ [Symbol.dispose](): void; }