import { type BatchOperation, type ConditionalBatchCondition } from '../../storage/interface.ts'; import type { ScheduleState, WorkflowState } from '../types.ts'; import type { EngineInternals } from './internals.ts'; import { type WorkflowClaimTransitionFragment } from './workflow-claim-transitions.ts'; /** Run a workflow-state write after any earlier write for that workflow has settled. */ export declare function runSerializedWorkflowStateWrite(internals: EngineInternals, workflowId: string, writeOperation: () => Promise): Promise; /** * Serialize a schedule read-modify-write operation with its timer callback. * * Unlike workflow-state write serialization, a failed predecessor is propagated * to callers that were already queued behind it. In particular, an update that * arrives while a scanned timer callback is rearming must not delete the fired * timer after that callback fails; rejecting the queued update leaves the durable * timer available for the scheduler (or a lease successor) to retry. */ export declare function runSerializedScheduleStateOperation(internals: EngineInternals, scheduleId: string, operation: () => Promise): Promise; /** Load and decode persisted workflow state by workflow ID. */ export declare function loadWorkflowState(internals: EngineInternals, workflowId: string): Promise; /** * Derive a terminal result (or throw the persisted terminal error) from an * ALREADY-LOADED `WorkflowState` — pure, no storage read. Callers that hold a * state snapshot they have already validated as terminal (e.g. * `bootstrapWorkflowResultResolver`) must use this instead of * {@link loadWorkflowResult}: a second independent `loadWorkflowState` read * can observe a DIFFERENT run than the one the caller validated, if * `onTerminalConflict: 'start-new'` replaces the workflow between the two * reads — attributing a replacement run's result (or a spurious "still * running") to a waiter that was made terminal by the original run. */ export declare function deriveWorkflowResultFromState(state: WorkflowState): unknown; /** Load a terminal workflow result or throw the persisted terminal error. */ export declare function loadWorkflowResult(internals: EngineInternals, workflowId: string): Promise; type WorkflowStateCommitOptions = { includePendingAtomicSideEffects?: boolean; }; /** * Build the `wf-owner-epoch:` / `wf-owner-holder:` ROTATION fragment * for an EXTERNAL terminal transition — cancel, timeout, suspend, purge (ADR * 0002 § "External terminal transitions must rotate the epoch"). Any engine * may commit these against a workflow it does not own; deleting the holder * alone is not sufficient to make that safe, so the epoch is rotated in the * SAME atomic batch that writes the terminal/suspended state, deposing a * still-running owner — its next write carries the now-stale epoch and loses * its CAS. Meant to be folded (via `[...fragment.operations]` / * `[...fragment.conditions]`) into the caller's own operations/conditions, * never committed standalone. * * Under `ownership: 'none'` or `'lease'` this returns an EMPTY fragment with * NO storage read: the `wf-owner-*` keyspace is not in play under those * modes, and this function must not touch it — that is what keeps external * terminal commits byte-for-byte unchanged there. */ export declare function buildExternalTerminalRotationFragment(internals: EngineInternals, workflowId: string): Promise; /** * Commit a SELF-transition workflow-state advance (complete, fail): this * engine is finishing its OWN workflow, so the write is workflow-scoped and * fenced on THIS engine's claim epoch under `ownership: 'workflow-lease'` * (via {@link commitFencedEngineWrite}'s `workflowId` parameter), or the * global lease epoch under `ownership: 'lease'`. A deposed engine's write * loses its CAS instead of corrupting the successor's state; the deposition * is detected and the engine (or, under `workflow-lease`, just this one * workflow) halts. Under `ownership: 'none'` this is byte-for-byte the * pre-ADR commit shape. Never rotates `wf-owner-epoch:` — that is the * external-transition shape below. Operator/external mutations * (search-attribute and tag edits) do NOT use this helper; they batch * directly and are intentionally never fenced. */ export declare function commitSelfWorkflowStateOperations(internals: EngineInternals, state: WorkflowState, operations: BatchOperation[], options?: WorkflowStateCommitOptions): Promise; /** * Commit an EXTERNAL terminal workflow-state transition — cancel, timeout, or * suspend (ADR 0002 § "External terminal transitions must rotate the * epoch"). ANY engine may commit these against a workflow it does not own, so * — unlike {@link commitSelfWorkflowStateOperations} — this is never fenced * on this engine's own workflow claim (`workflowId: null` is passed to * {@link commitFencedEngineWrite}). Instead {@link * buildExternalTerminalRotationFragment} folds a claim ROTATION into the same * atomic batch under `ownership: 'workflow-lease'`, deposing a still-running * owner. Under `ownership: 'lease'` the write still carries the global lease * epoch condition (via `commitFencedEngineWrite`'s `workflowId: null` path); * under `'none'` it is byte-for-byte unchanged. */ export declare function commitExternalTerminalWorkflowStateOperations(internals: EngineInternals, state: WorkflowState, operations: BatchOperation[], options?: WorkflowStateCommitOptions): Promise; /** Load and decode persisted schedule state by schedule ID. */ export declare function loadScheduleState(internals: EngineInternals, scheduleId: string): Promise; /** Load a schedule state. */ export declare function requireScheduleState(internals: EngineInternals, scheduleId: string): Promise; /** * Persist schedule state and optionally write the next schedule timer. * * `extraConditions` (WFT-20) additionally fences the commit on caller-supplied * preconditions — used by a `revisionPolicy: 'pinned'` create/update to fence * the write on `buildCatalogEntryRevisionCondition(type, pinnedRevision)` so a * concurrent `removeWorkflowRevision()` landing between pin capture and this * commit cannot let a pin to an already-removed revision durably land. When * the commit's `extraConditions` are the ones that lost the CAS, * `onExtraConditionsLost` (required whenever `extraConditions` is non-empty) * supplies the thrown error instead of this function's own generic * lost-precondition error, so the caller sees an actionable, typed failure * (e.g. `WorkflowRevisionUnavailableError`) rather than a bare "lost its * precondition" message. Every existing caller passes neither option and gets * byte-for-byte the pre-WFT-20 commit shape. */ export declare function writeScheduleState(internals: EngineInternals, state: ScheduleState, options?: { includeTimer?: boolean; replaceTimerFrom?: ScheduleState; additionalOperations?: BatchOperation[]; extraConditions?: ConditionalBatchCondition[]; onExtraConditionsLost?: () => Error; }): Promise; /** Load persisted workflow start headers by workflow ID. */ export declare function loadWorkflowStartHeaders(internals: EngineInternals, workflowId: string): Promise | undefined>; export {};