import type { ContextOperationRequest } from '../context.ts'; import type { EngineInternals } from './internals.ts'; /** * The largest delay a host `setTimeout` can hold without overflow. Node and Bun * store the delay in a 32-bit signed integer, so a value above this wraps and * the timer fires almost immediately. A multi-day race-branch sleep must be * chunked under this ceiling and re-armed, or it would win its race instantly. */ export declare const MAX_TIMER_DELAY_MS = 2147483647; /** * Compute the next host-timer delay for a race-branch sleep: the milliseconds * remaining until the deterministic `scheduledFireAt` deadline, clamped to * `[0, MAX_TIMER_DELAY_MS]`. Clamping to the ceiling is what prevents a multi-day * sleep from overflowing `setTimeout` and firing instantly — the caller re-arms * against the same deadline until the remaining delay reaches `0`. */ export declare function nextSleepTimerDelayMs(scheduledFireAt: number, now: number): number; /** * Abortable in-process `sleep` branch for `ctx.race` / `ctx.all`. * * Unlike a top-level `ctx.sleep` (which arms a durable timer and parks the whole * generator), a sleep branch inside a coordination operation is a TRANSIENT * in-process wait: the coordination operation as a whole is the durable unit, and * on replay the cached winner short-circuits before any branch re-runs. So this * must NOT touch `internals.scheduler` (a durable timer write would corrupt the * timer index) — it waits with a plain timer that the race's AbortController can * cancel when another branch wins. * * The deadline is the operation's deterministic `scheduledFireAt`, compared * against the engine clock (`internals.options.getNow()`), not wall-clock * `Date.now()`, so a clock-overriding deployment stays consistent. The remaining * delay is recomputed against that absolute deadline on every chunk, which both * chunks delays beyond {@link MAX_TIMER_DELAY_MS} (so a multi-day sleep does not * overflow `setTimeout` and fire instantly) and self-corrects for timer drift. * * Note: because the timer is a real event-loop timer, a long sleep that WINS its * race is not driven by a virtual-clock `advanceTime`; tests should use short * real durations for sleep-wins paths (sleep-loses paths need no timing — the * abort fires). * * The timer also observes the engine abort signal so a long sleep branch does * not outlive engine disposal. `ctx.all` does not abort siblings (it has no * loser), so without watching `internals.abortController.signal` a multi-day * `ctx.all([ctx.sleep('30d')])` branch would keep a host timer alive after the * engine is gone. */ export declare function executeSleepSubOperation(internals: EngineInternals, operation: Extract, signal?: AbortSignal): Promise; /** * Abortable in-process `wait-signal` branch for `ctx.race` / `ctx.all`. * * A wait-signal branch must never consume its durable signal record itself — * when it is woken it does not yet know whether it WON its race. So on delivery * it resolves with a {@link createDeferredConsumeEnvelope | deferred-consume * envelope}: the single atomic {@link consumeSignalWithAtomicWorkflowCommit} is wrapped in * `finalize` and performed ONLY by the coordinator, on the winner, strictly * after `Promise.race` / `Promise.all` settles. A losing branch (race settled by * a sibling → `signal` aborts) drops its envelope unfinalized and releases its * waiter via {@link releaseSignalWaiter} WITHOUT consuming, so the signal * survives for a later `waitForSignal` or a replay. * * Reads are non-destructive {@link peekSignal}s until the coordinator finalizes; * the identity-guarded release (`expectedResolve === deliver`) ensures a loser * never clobbers another waiter (e.g. a later top-level `waitForSignal`) that * reused the shared `${workflowId}:${signalName}` key. */ export declare function executeWaitSignalSubOperation(internals: EngineInternals, workflowId: string, operation: Extract, signal?: AbortSignal): Promise;