/** * Create-and-deliver machinery for {@link startOrSignal}: building the atomic * start-with-signal batch, running it, and recovering from every way the create * can lose its CAS (keyed-mapping loss, caller-`id` reservation collision, or a * pre-buffered signal). Split from `start-or-signal.ts` to keep that module * focused on the public `startOrSignal` / `startWithIdempotency` entry points. * * @module core/engine/lifecycle/start-or-signal-create */ import type { StartOrSignalOptions, StartOrSignalSignal } from '../../types.ts'; import { type StartOrSignalOutcome, type WorkflowHandle } from '../handles.ts'; import type { EngineInternals } from '../internals.ts'; import { type BuildIdempotentStartOperations } from './start-commit.ts'; import { type StartOrSignalCallbacks } from './start-or-signal-resolution.ts'; /** * Build the `(workflowId) => { operations, conditions }` callback that folds the * idempotency mapping and (optionally) the create-batch signal into the start * batch, gated on the mapping key being absent. Every caller supplies at least * one of `idempotencyKey` / `signal` (the plain start path skips this builder * entirely), so the returned callback always contributes at least one operation. */ export declare function idempotentStartOperationsFor(internals: EngineInternals, idempotencyKey: string | undefined, signal: { name: string; payload: unknown; signalId: string; } | undefined): BuildIdempotentStartOperations; /** * A resolved start-or-signal handle paired with which atomic path produced it * (#466), computed during the call at zero extra cost. */ export type StartOrSignalResult = { handle: WorkflowHandle; outcome: StartOrSignalOutcome; }; /** * Create the workflow and deliver the signal atomically, recovering from a lost * create batch: * * - **Lost to a keyed winner** — idempotency-mapping CAS loss * ({@link StartIdempotencyRaceLostError} on the keyed path): the mapping commits * atomically with the record, so the winner is guaranteed committed — resolve it * and signal it (or conflict if terminal). * - **Lost to a caller-`id` winner** — collision on the winner's in-memory * `pendingStarts` reservation ({@link WorkflowAlreadyExistsError}): the * reservation is held BEFORE the durable commit, so it may clear without a run * ever existing (the winner aborted: storage failure, oversized payload, a * throwing start interceptor). Wait for the reservation to clear, then signal a * committed winner or — if it aborted — retry the create. Bounded by * {@link CALLER_ID_CREATE_MAX_ATTEMPTS}. * - **Signal already buffered** — `StartIdempotencyRaceLostError` on the * caller-`id` path: the only CAS condition there is the signal's `sigres:` * accepted-response marker, so the loss means a signal with this signalId was * pre-buffered and (the batch being atomic) the `wf:` record was NOT written. * Plain-create the workflow; the buffered signal is consumed on first drive * (scan-then-park), and the caller's payload loses to the pre-buffered one by * the same first-wins dedup. */ export declare function createWithSignalOrFallback(internals: EngineInternals, type: string, input: unknown, signalSpec: StartOrSignalSignal, signalId: string, options: StartOrSignalOptions | undefined, callbacks: StartOrSignalCallbacks): Promise;