import type { DurableOperationHandle, OperationExecutor, OperationRecord, OperationRunnerConfig, OperationSubmitOptions } from '../types/operations.js'; /** * Runs operations against a durable store. * * The runner owns the whole lifecycle: it persists a record before doing any work, claims a lease, * heartbeats while the executor runs, retries with backoff, dead-letters what never succeeds, and * emits signed webhooks. A crashed worker leaves a record whose lease simply lapses, which * `recover()` then picks up — that is the entire mechanism behind surviving a restart. * * With the default `MemoryOperationStore` this is a process-local runner with full lifecycle * semantics and no external dependency; swapping in `RedisOperationStore` makes it durable without * any other change. */ export declare class OperationRunner { private readonly config; private readonly store; private readonly owner; private readonly leaseMs; private readonly heartbeatMs; private readonly now; private operationCounter; constructor(config?: OperationRunnerConfig); /** Identifier this runner writes into leases. */ get workerId(): string; /** * Accepts an operation and starts running it. * * Returns before the executor has done anything, so the caller can stream events or persist the * id. An `idempotencyKey` that matches an existing record replays that operation instead of * starting a second one, which is what stops an ambiguous timeout from double-charging. */ submit(executor: OperationExecutor, options?: OperationSubmitOptions): Promise>; /** Reads the persisted record, without starting anything. */ read(id: string): Promise | undefined>; /** * Cancels a persisted operation, including one owned by another worker. * * The running worker notices through its heartbeat, which is why cancellation is observed rather * than immediate across processes. */ cancel(id: string, reason?: string): Promise; /** * Re-runs operations whose lease lapsed, typically after a worker crashed. * * A record past its `expiresAt` is expired rather than retried, and one that has used every * attempt is dead-lettered, so a permanently failing operation cannot be recovered forever. */ recover(executor: OperationExecutor, limit?: number): Promise>>; private startHandle; private execute; /** Moves a claimable record to `running` and stamps a lease. */ private claim; private startHeartbeat; private buildContext; private persistSuccess; private persistCancelled; private settleDeadLetter; private settleExpired; /** Applies a checked transition and bumps the concurrency token. */ private advance; /** * Rebuilds a handle for an operation this process did not start. * * Used for an idempotency replay: the caller gets a handle that resolves from the stored record * rather than a second execution. */ private attachToRecord; private followRecord; private decorate; private emitWebhook; private createOperationId; }