@dudousxd/nestjs-durable-core 0.72.1 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +150 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -5
- package/dist/index.d.ts +35 -5
- package/dist/index.js +145 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -919,6 +919,17 @@ interface StateStore {
|
|
|
919
919
|
* module's `autoSchema` is on. Optional: stores that need no setup (in-memory) omit it.
|
|
920
920
|
*/
|
|
921
921
|
ensureSchema?(): Promise<void>;
|
|
922
|
+
/**
|
|
923
|
+
* Atomically read active runs sharing workflow/tag in this store's read scope, preserve durable
|
|
924
|
+
* admitted holders, and claim a free slot for an eligible FIFO waiter. The claim persists the
|
|
925
|
+
* reserved SINGLETON_ADMITTED_TAG in tags. Execution lease expiry never releases a slot; terminal
|
|
926
|
+
* status does. Optional for general stores, required when using singleton workflows. Implement
|
|
927
|
+
* with a database transaction that serializes competing claims BEFORE reading; list/update alone
|
|
928
|
+
* is unsafe across engine instances. If retryWakeAt is supplied, denial must atomically suspend
|
|
929
|
+
* the still-active candidate with that wakeAt while the same locks are held. Never overwrite a
|
|
930
|
+
* cancelling or terminal run on denial. Return false for missing/terminal/out-of-scope runs.
|
|
931
|
+
*/
|
|
932
|
+
tryAdmitSingleton?(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
|
|
922
933
|
createRun(run: WorkflowRun): Promise<void>;
|
|
923
934
|
updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;
|
|
924
935
|
getRun(runId: string): Promise<WorkflowRun | null>;
|
|
@@ -3441,8 +3452,8 @@ interface StartOptions {
|
|
|
3441
3452
|
/**
|
|
3442
3453
|
* Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).
|
|
3443
3454
|
* Excess runs are admitted in creation order, `limit` at a time; the rest wait (suspended) and retry
|
|
3444
|
-
* admission on a timer until a slot frees.
|
|
3445
|
-
*
|
|
3455
|
+
* admission on a timer until a slot frees. The store atomically reserves durable slots before
|
|
3456
|
+
* ordering unadmitted waiters by `(createdAt, id)`, so later starts cannot displace a holder.
|
|
3446
3457
|
*/
|
|
3447
3458
|
interface SingletonConfig {
|
|
3448
3459
|
/** Derive the serialization key from the workflow input. */
|
|
@@ -3453,7 +3464,7 @@ interface SingletonConfig {
|
|
|
3453
3464
|
* Max GATED (waiting-for-admission) runs allowed to queue behind the `limit` in-flight ones. When
|
|
3454
3465
|
* set, `start` rejects with {@link SingletonQueueFullError} once in-flight + gated reaches
|
|
3455
3466
|
* `limit + maxQueueDepth` — back-pressure against an unbounded same-key backlog. Omit for the
|
|
3456
|
-
* default unbounded queue. Counts
|
|
3467
|
+
* default unbounded queue. Counts pending/running/suspended/blocked/cancelling runs sharing the key.
|
|
3457
3468
|
*/
|
|
3458
3469
|
maxQueueDepth?: number;
|
|
3459
3470
|
}
|
|
@@ -4427,6 +4438,8 @@ declare class WorkflowEngine {
|
|
|
4427
4438
|
private completeStep;
|
|
4428
4439
|
/** Checkpoint a step that failed terminally, so the failure point is visible (not just the run). */
|
|
4429
4440
|
private failStep;
|
|
4441
|
+
/** Admission persists the wait atomically; never overwrite a cancellation after it returns. */
|
|
4442
|
+
private singletonWaitResult;
|
|
4430
4443
|
private execute;
|
|
4431
4444
|
/**
|
|
4432
4445
|
* Advance a remote (cross-SDK) workflow one turn: hand its history to the executor (which dispatches
|
|
@@ -5328,6 +5341,8 @@ interface PayloadCodec {
|
|
|
5328
5341
|
declare class CodecStateStore implements StateStore {
|
|
5329
5342
|
private readonly inner;
|
|
5330
5343
|
private readonly codec;
|
|
5344
|
+
/** Atomic claims touch only searchable metadata and bypass payload encoding. */
|
|
5345
|
+
readonly tryAdmitSingleton?: (runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number) => Promise<boolean>;
|
|
5331
5346
|
/**
|
|
5332
5347
|
* Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches
|
|
5333
5348
|
* (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store
|
|
@@ -5796,8 +5811,9 @@ declare class InMemoryStateStore implements StateStore {
|
|
|
5796
5811
|
private key;
|
|
5797
5812
|
/** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */
|
|
5798
5813
|
private reindexAttributes;
|
|
5814
|
+
tryAdmitSingleton(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
|
|
5799
5815
|
createRun(run: WorkflowRun): Promise<void>;
|
|
5800
|
-
updateRun(runId: string,
|
|
5816
|
+
updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void>;
|
|
5801
5817
|
getRun(runId: string): Promise<WorkflowRun | null>;
|
|
5802
5818
|
deleteRun(runId: string): Promise<void>;
|
|
5803
5819
|
deleteRuns(runIds: string[]): Promise<void>;
|
|
@@ -5891,4 +5907,18 @@ declare class InMemoryTransport implements Transport, ControlPlane {
|
|
|
5891
5907
|
onControl(handler: (msg: ControlMessage) => void): void;
|
|
5892
5908
|
}
|
|
5893
5909
|
|
|
5894
|
-
|
|
5910
|
+
/** Reserved engine metadata: a durable singleton slot, independent of the execution lease. */
|
|
5911
|
+
declare const SINGLETON_ADMITTED_TAG = "durable:singleton:admitted";
|
|
5912
|
+
declare const SINGLETON_ACTIVE_STATUSES: RunStatus[];
|
|
5913
|
+
/** Call only inside a store's atomic admission transaction/critical section. */
|
|
5914
|
+
declare function singletonAdmissionTags(runs: WorkflowRun[], runId: string, tag: string, workflow: string, limit: number): string[] | null;
|
|
5915
|
+
/** Terminal runs release admission, including when later resumed directly rather than requeued. */
|
|
5916
|
+
declare function clearTerminalSingletonAdmission(runId: string, patch: Partial<WorkflowRun>, getRun: (id: string) => Promise<WorkflowRun | null>): Promise<Partial<WorkflowRun>>;
|
|
5917
|
+
/** Persist denial while admission locks are held; a cancelling/terminal run must never revive. */
|
|
5918
|
+
declare function singletonAdmissionDenialPatch(runs: WorkflowRun[], runId: string, tag: string, workflow: string, retryWakeAt?: number): {
|
|
5919
|
+
status: 'suspended';
|
|
5920
|
+
wakeAt: number;
|
|
5921
|
+
updatedAt: Date;
|
|
5922
|
+
} | undefined;
|
|
5923
|
+
|
|
5924
|
+
export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AnnouncedWorkflow, type AnnouncementEvidence, type AttributeFilter, type AttributeOp, type AttributePredicateOperand, type AttributeValue, type BackoffStrategy, type BlockedDispatch, type BlockedResolution, CONTROL_FLOW_SIGNAL, CURRENT_PROTOCOL_VERSION, type CapabilityRequirement, type ChildCallOptions, CodecStateStore, type ConcurrencyConfig, ConcurrencyLimitError, type ConcurrencyQuota, ContinueAsNew, type ControlMessage, type ControlPlane, DEFAULT_CONCURRENCY_STATUSES, DEFAULT_PARTITION, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, DURABLE_STEP_CONFIG, DURABLE_STEP_NAME, type Disagreement, type DispatchDiagnostics, type DispatchPlan, type DurableExecution, type DurableExecutionWrapper, type DurableTopology, type DurableWebhook, DurableWorkflow, type DynamicWorkflowCtx, ENGINE_MINTED_TAG_PREFIXES, EVENT_BUFFER_SCAN_LIMIT, EVENT_TOKEN_PREFIX, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, EventAccumulators, type EventBatchConfig, FatalError, GatherError, type GroupHealth, type Heartbeat, type HeartbeatSighting, type HeartbeatStatus, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type InferSearchAttributes, LEGACY_V1_CAPABILITIES, LEGACY_V1_PROTOCOL, type MetricsCollector, type MetricsSnapshot, type NamedTransport, type NegotiateOptions, type NegotiationOutcome, type NegotiationReason, type NegotiationResult, NestedWorkflowCallError, NonDeterminismError, type PartitionSighting, type PayloadCodec, type QueueConfig, QueueController, RUN_VALUE_FACET_LIMIT, RUN_VALUE_FACET_SCAN, type RawWorkerDescriptor, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RetentionPolicy, type RoutableDispatch, type RoutableResolution, type RoutingResolution, type RunAttributeRow, type RunDetail, type RunDispatcher, type RunFacetQuery, type RunFacetRow, RunGateway, type RunListItem, type RunQuery, type RunReply, type RunReplyResult, type RunRequest, type RunRequestKind, type RunResult, type RunSchedulesOptions, type RunScope, type RunStatus, type RunValueAxis, type RunValueFacetOptions, type RunValueFacetOrder, type RunValueFacetRow, type RunWaiting, SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG, STATE_STORE, STATE_STORE_CANONICAL, type ScalarAttributeFilter, ScheduleAlreadyExistsError, ScheduleClient, type ScheduleClientOptions, type ScheduleDescription, type ScheduleHost, type ScheduleListQuery, ScheduleNotFoundError, type ScheduleOptions, type ScheduleQuery, type ScheduleRecord, type ScheduledWorkflow, type SearchAttributes, type SearchAttributesSchema, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, StandardSchemaV1, type StartOptions, type StartRunMessage, type StateStore, type StepCheckpoint, type StepConfig, type StepDef, type StepDispatchOpts, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepRef, type StepResult, type StepScope, type StepUndo, type StoreTransaction, type SubProcessHandle, TERMINAL_RUN_STATUSES, TRANSPORT, TRANSPORT_CANONICAL, type TenantEvent, type Transport, type UndoOf, type UpdateResult, type UpdateValidator, VERSION_UNDECLARED_TAG, WORKFLOW_NAME_KEY, type WireDates, type WorkerAdjust, type WorkerConcurrencyStatus, type WorkerDescriptor, type WorkerHeartbeat, type WorkerLifecycle, type WorkerStatus, type WorkflowAnnouncement, WorkflowBlocked, type WorkflowClass, type WorkflowCommand, type WorkflowCtx, type WorkflowDecision, type WorkflowDirectory, WorkflowEngine, type WorkflowEngineDeps, type WorkflowExecutor, type WorkflowHandler, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRef, type WorkflowRegistration, type WorkflowRun, type WorkflowStartClient, type WorkflowStepEvent, WorkflowSuspended, type WorkflowTask, aggregateAnnouncements, announcementsOf, applyAttributeQuery, assertConcurrency, attributeColumnFor, attributeOperand, attributePredicateOperands, axisIsRunColumn, bindWorkflowClass, breakpointToken, buildWorkflowDirectory, canRoute, capableWorkers, classifyWaiterToken, clearDurableExecutionWrappers, clearTerminalSingletonAdmission, collectMetrics, concurrencyTag, controlPlaneDescriptor, countRuns, coveredTokens, createStepLogger, currentStep, currentStepScope, currentWorkflowCtx, debug, describeWorker, descriptorHash, error, eventMatchOf, eventMatches, eventNameOf, eventPrefix, eventToken, facetOrigin, hasDurableExecutionWrappers, heartbeatStatus, indexWaitersByRun, info, isEngineMintedTag, isEventToken, isLegacyDescriptor, isNonEmptyRunScope, isWorkflowControlFlowSignal, log, matchesAttributes, mergeRunFacetRows, mergeRunValueFacetRows, missingCapabilities, negotiate, nextCronFireMs, normalizeAttributeRows, normalizeDescriptor, observedAnnouncements, parseDuration, partitionOfToken, planDispatch, prevCronFireMs, readSearchAttributes, requiredCapabilities, resolveConcurrency, resolveRouting, resolveRunWaiting, runDurableExecution, runInStepLogger, runInStepScope, runInWorkflowCtx, runOutsideWorkflowCtx, runSchedules, runStepHandler, runValueFacetsFromRuns, sanitizeQueueToken, scheduledRunId, singletonAdmissionDenialPatch, singletonAdmissionTags, sqlComparator, stepConfigOf, stepId, stepNameOf, sub, subEvent, subProcess, tenantGroup, useDurableExecution, warn, workflowName };
|
package/dist/index.d.ts
CHANGED
|
@@ -919,6 +919,17 @@ interface StateStore {
|
|
|
919
919
|
* module's `autoSchema` is on. Optional: stores that need no setup (in-memory) omit it.
|
|
920
920
|
*/
|
|
921
921
|
ensureSchema?(): Promise<void>;
|
|
922
|
+
/**
|
|
923
|
+
* Atomically read active runs sharing workflow/tag in this store's read scope, preserve durable
|
|
924
|
+
* admitted holders, and claim a free slot for an eligible FIFO waiter. The claim persists the
|
|
925
|
+
* reserved SINGLETON_ADMITTED_TAG in tags. Execution lease expiry never releases a slot; terminal
|
|
926
|
+
* status does. Optional for general stores, required when using singleton workflows. Implement
|
|
927
|
+
* with a database transaction that serializes competing claims BEFORE reading; list/update alone
|
|
928
|
+
* is unsafe across engine instances. If retryWakeAt is supplied, denial must atomically suspend
|
|
929
|
+
* the still-active candidate with that wakeAt while the same locks are held. Never overwrite a
|
|
930
|
+
* cancelling or terminal run on denial. Return false for missing/terminal/out-of-scope runs.
|
|
931
|
+
*/
|
|
932
|
+
tryAdmitSingleton?(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
|
|
922
933
|
createRun(run: WorkflowRun): Promise<void>;
|
|
923
934
|
updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;
|
|
924
935
|
getRun(runId: string): Promise<WorkflowRun | null>;
|
|
@@ -3441,8 +3452,8 @@ interface StartOptions {
|
|
|
3441
3452
|
/**
|
|
3442
3453
|
* Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).
|
|
3443
3454
|
* Excess runs are admitted in creation order, `limit` at a time; the rest wait (suspended) and retry
|
|
3444
|
-
* admission on a timer until a slot frees.
|
|
3445
|
-
*
|
|
3455
|
+
* admission on a timer until a slot frees. The store atomically reserves durable slots before
|
|
3456
|
+
* ordering unadmitted waiters by `(createdAt, id)`, so later starts cannot displace a holder.
|
|
3446
3457
|
*/
|
|
3447
3458
|
interface SingletonConfig {
|
|
3448
3459
|
/** Derive the serialization key from the workflow input. */
|
|
@@ -3453,7 +3464,7 @@ interface SingletonConfig {
|
|
|
3453
3464
|
* Max GATED (waiting-for-admission) runs allowed to queue behind the `limit` in-flight ones. When
|
|
3454
3465
|
* set, `start` rejects with {@link SingletonQueueFullError} once in-flight + gated reaches
|
|
3455
3466
|
* `limit + maxQueueDepth` — back-pressure against an unbounded same-key backlog. Omit for the
|
|
3456
|
-
* default unbounded queue. Counts
|
|
3467
|
+
* default unbounded queue. Counts pending/running/suspended/blocked/cancelling runs sharing the key.
|
|
3457
3468
|
*/
|
|
3458
3469
|
maxQueueDepth?: number;
|
|
3459
3470
|
}
|
|
@@ -4427,6 +4438,8 @@ declare class WorkflowEngine {
|
|
|
4427
4438
|
private completeStep;
|
|
4428
4439
|
/** Checkpoint a step that failed terminally, so the failure point is visible (not just the run). */
|
|
4429
4440
|
private failStep;
|
|
4441
|
+
/** Admission persists the wait atomically; never overwrite a cancellation after it returns. */
|
|
4442
|
+
private singletonWaitResult;
|
|
4430
4443
|
private execute;
|
|
4431
4444
|
/**
|
|
4432
4445
|
* Advance a remote (cross-SDK) workflow one turn: hand its history to the executor (which dispatches
|
|
@@ -5328,6 +5341,8 @@ interface PayloadCodec {
|
|
|
5328
5341
|
declare class CodecStateStore implements StateStore {
|
|
5329
5342
|
private readonly inner;
|
|
5330
5343
|
private readonly codec;
|
|
5344
|
+
/** Atomic claims touch only searchable metadata and bypass payload encoding. */
|
|
5345
|
+
readonly tryAdmitSingleton?: (runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number) => Promise<boolean>;
|
|
5331
5346
|
/**
|
|
5332
5347
|
* Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches
|
|
5333
5348
|
* (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store
|
|
@@ -5796,8 +5811,9 @@ declare class InMemoryStateStore implements StateStore {
|
|
|
5796
5811
|
private key;
|
|
5797
5812
|
/** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */
|
|
5798
5813
|
private reindexAttributes;
|
|
5814
|
+
tryAdmitSingleton(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
|
|
5799
5815
|
createRun(run: WorkflowRun): Promise<void>;
|
|
5800
|
-
updateRun(runId: string,
|
|
5816
|
+
updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void>;
|
|
5801
5817
|
getRun(runId: string): Promise<WorkflowRun | null>;
|
|
5802
5818
|
deleteRun(runId: string): Promise<void>;
|
|
5803
5819
|
deleteRuns(runIds: string[]): Promise<void>;
|
|
@@ -5891,4 +5907,18 @@ declare class InMemoryTransport implements Transport, ControlPlane {
|
|
|
5891
5907
|
onControl(handler: (msg: ControlMessage) => void): void;
|
|
5892
5908
|
}
|
|
5893
5909
|
|
|
5894
|
-
|
|
5910
|
+
/** Reserved engine metadata: a durable singleton slot, independent of the execution lease. */
|
|
5911
|
+
declare const SINGLETON_ADMITTED_TAG = "durable:singleton:admitted";
|
|
5912
|
+
declare const SINGLETON_ACTIVE_STATUSES: RunStatus[];
|
|
5913
|
+
/** Call only inside a store's atomic admission transaction/critical section. */
|
|
5914
|
+
declare function singletonAdmissionTags(runs: WorkflowRun[], runId: string, tag: string, workflow: string, limit: number): string[] | null;
|
|
5915
|
+
/** Terminal runs release admission, including when later resumed directly rather than requeued. */
|
|
5916
|
+
declare function clearTerminalSingletonAdmission(runId: string, patch: Partial<WorkflowRun>, getRun: (id: string) => Promise<WorkflowRun | null>): Promise<Partial<WorkflowRun>>;
|
|
5917
|
+
/** Persist denial while admission locks are held; a cancelling/terminal run must never revive. */
|
|
5918
|
+
declare function singletonAdmissionDenialPatch(runs: WorkflowRun[], runId: string, tag: string, workflow: string, retryWakeAt?: number): {
|
|
5919
|
+
status: 'suspended';
|
|
5920
|
+
wakeAt: number;
|
|
5921
|
+
updatedAt: Date;
|
|
5922
|
+
} | undefined;
|
|
5923
|
+
|
|
5924
|
+
export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AnnouncedWorkflow, type AnnouncementEvidence, type AttributeFilter, type AttributeOp, type AttributePredicateOperand, type AttributeValue, type BackoffStrategy, type BlockedDispatch, type BlockedResolution, CONTROL_FLOW_SIGNAL, CURRENT_PROTOCOL_VERSION, type CapabilityRequirement, type ChildCallOptions, CodecStateStore, type ConcurrencyConfig, ConcurrencyLimitError, type ConcurrencyQuota, ContinueAsNew, type ControlMessage, type ControlPlane, DEFAULT_CONCURRENCY_STATUSES, DEFAULT_PARTITION, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, DURABLE_STEP_CONFIG, DURABLE_STEP_NAME, type Disagreement, type DispatchDiagnostics, type DispatchPlan, type DurableExecution, type DurableExecutionWrapper, type DurableTopology, type DurableWebhook, DurableWorkflow, type DynamicWorkflowCtx, ENGINE_MINTED_TAG_PREFIXES, EVENT_BUFFER_SCAN_LIMIT, EVENT_TOKEN_PREFIX, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, EventAccumulators, type EventBatchConfig, FatalError, GatherError, type GroupHealth, type Heartbeat, type HeartbeatSighting, type HeartbeatStatus, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type InferSearchAttributes, LEGACY_V1_CAPABILITIES, LEGACY_V1_PROTOCOL, type MetricsCollector, type MetricsSnapshot, type NamedTransport, type NegotiateOptions, type NegotiationOutcome, type NegotiationReason, type NegotiationResult, NestedWorkflowCallError, NonDeterminismError, type PartitionSighting, type PayloadCodec, type QueueConfig, QueueController, RUN_VALUE_FACET_LIMIT, RUN_VALUE_FACET_SCAN, type RawWorkerDescriptor, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RetentionPolicy, type RoutableDispatch, type RoutableResolution, type RoutingResolution, type RunAttributeRow, type RunDetail, type RunDispatcher, type RunFacetQuery, type RunFacetRow, RunGateway, type RunListItem, type RunQuery, type RunReply, type RunReplyResult, type RunRequest, type RunRequestKind, type RunResult, type RunSchedulesOptions, type RunScope, type RunStatus, type RunValueAxis, type RunValueFacetOptions, type RunValueFacetOrder, type RunValueFacetRow, type RunWaiting, SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG, STATE_STORE, STATE_STORE_CANONICAL, type ScalarAttributeFilter, ScheduleAlreadyExistsError, ScheduleClient, type ScheduleClientOptions, type ScheduleDescription, type ScheduleHost, type ScheduleListQuery, ScheduleNotFoundError, type ScheduleOptions, type ScheduleQuery, type ScheduleRecord, type ScheduledWorkflow, type SearchAttributes, type SearchAttributesSchema, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, StandardSchemaV1, type StartOptions, type StartRunMessage, type StateStore, type StepCheckpoint, type StepConfig, type StepDef, type StepDispatchOpts, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepRef, type StepResult, type StepScope, type StepUndo, type StoreTransaction, type SubProcessHandle, TERMINAL_RUN_STATUSES, TRANSPORT, TRANSPORT_CANONICAL, type TenantEvent, type Transport, type UndoOf, type UpdateResult, type UpdateValidator, VERSION_UNDECLARED_TAG, WORKFLOW_NAME_KEY, type WireDates, type WorkerAdjust, type WorkerConcurrencyStatus, type WorkerDescriptor, type WorkerHeartbeat, type WorkerLifecycle, type WorkerStatus, type WorkflowAnnouncement, WorkflowBlocked, type WorkflowClass, type WorkflowCommand, type WorkflowCtx, type WorkflowDecision, type WorkflowDirectory, WorkflowEngine, type WorkflowEngineDeps, type WorkflowExecutor, type WorkflowHandler, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRef, type WorkflowRegistration, type WorkflowRun, type WorkflowStartClient, type WorkflowStepEvent, WorkflowSuspended, type WorkflowTask, aggregateAnnouncements, announcementsOf, applyAttributeQuery, assertConcurrency, attributeColumnFor, attributeOperand, attributePredicateOperands, axisIsRunColumn, bindWorkflowClass, breakpointToken, buildWorkflowDirectory, canRoute, capableWorkers, classifyWaiterToken, clearDurableExecutionWrappers, clearTerminalSingletonAdmission, collectMetrics, concurrencyTag, controlPlaneDescriptor, countRuns, coveredTokens, createStepLogger, currentStep, currentStepScope, currentWorkflowCtx, debug, describeWorker, descriptorHash, error, eventMatchOf, eventMatches, eventNameOf, eventPrefix, eventToken, facetOrigin, hasDurableExecutionWrappers, heartbeatStatus, indexWaitersByRun, info, isEngineMintedTag, isEventToken, isLegacyDescriptor, isNonEmptyRunScope, isWorkflowControlFlowSignal, log, matchesAttributes, mergeRunFacetRows, mergeRunValueFacetRows, missingCapabilities, negotiate, nextCronFireMs, normalizeAttributeRows, normalizeDescriptor, observedAnnouncements, parseDuration, partitionOfToken, planDispatch, prevCronFireMs, readSearchAttributes, requiredCapabilities, resolveConcurrency, resolveRouting, resolveRunWaiting, runDurableExecution, runInStepLogger, runInStepScope, runInWorkflowCtx, runOutsideWorkflowCtx, runSchedules, runStepHandler, runValueFacetsFromRuns, sanitizeQueueToken, scheduledRunId, singletonAdmissionDenialPatch, singletonAdmissionTags, sqlComparator, stepConfigOf, stepId, stepNameOf, sub, subEvent, subProcess, tenantGroup, useDurableExecution, warn, workflowName };
|
package/dist/index.js
CHANGED
|
@@ -2288,6 +2288,54 @@ function errorMessage(error2) {
|
|
|
2288
2288
|
}
|
|
2289
2289
|
__name(errorMessage, "errorMessage");
|
|
2290
2290
|
|
|
2291
|
+
// src/singleton-admission.ts
|
|
2292
|
+
var SINGLETON_ADMITTED_TAG = "durable:singleton:admitted";
|
|
2293
|
+
var SINGLETON_ACTIVE_STATUSES = [
|
|
2294
|
+
"pending",
|
|
2295
|
+
"running",
|
|
2296
|
+
"suspended",
|
|
2297
|
+
"blocked",
|
|
2298
|
+
"cancelling"
|
|
2299
|
+
];
|
|
2300
|
+
function singletonAdmissionTags(runs, runId, tag, workflow, limit) {
|
|
2301
|
+
if (!Number.isInteger(limit) || limit < 1) throw new Error("singleton limit must be a positive integer");
|
|
2302
|
+
const active = runs.filter((run) => run.workflow === workflow && SINGLETON_ACTIVE_STATUSES.includes(run.status) && run.tags?.includes(tag));
|
|
2303
|
+
const candidate = active.find((run) => run.id === runId);
|
|
2304
|
+
if (!candidate) return null;
|
|
2305
|
+
if (candidate.tags?.includes(SINGLETON_ADMITTED_TAG)) return candidate.tags;
|
|
2306
|
+
if (candidate.status === "cancelling") return null;
|
|
2307
|
+
const holders = active.filter((run) => run.tags?.includes(SINGLETON_ADMITTED_TAG));
|
|
2308
|
+
const remaining = limit - holders.length;
|
|
2309
|
+
if (remaining <= 0) return null;
|
|
2310
|
+
const waiters = active.filter((run) => !run.tags?.includes(SINGLETON_ADMITTED_TAG)).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));
|
|
2311
|
+
if (!waiters.slice(0, remaining).some((run) => run.id === runId)) return null;
|
|
2312
|
+
return [
|
|
2313
|
+
...candidate.tags ?? [],
|
|
2314
|
+
SINGLETON_ADMITTED_TAG
|
|
2315
|
+
];
|
|
2316
|
+
}
|
|
2317
|
+
__name(singletonAdmissionTags, "singletonAdmissionTags");
|
|
2318
|
+
async function clearTerminalSingletonAdmission(runId, patch, getRun) {
|
|
2319
|
+
if (!patch.status || !TERMINAL_RUN_STATUSES.includes(patch.status)) return patch;
|
|
2320
|
+
const tags = "tags" in patch ? patch.tags : (await getRun(runId))?.tags;
|
|
2321
|
+
return {
|
|
2322
|
+
...patch,
|
|
2323
|
+
tags: tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG)
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
__name(clearTerminalSingletonAdmission, "clearTerminalSingletonAdmission");
|
|
2327
|
+
function singletonAdmissionDenialPatch(runs, runId, tag, workflow, retryWakeAt) {
|
|
2328
|
+
if (retryWakeAt === void 0) return void 0;
|
|
2329
|
+
const candidate = runs.find((run) => run.id === runId && run.workflow === workflow && run.tags?.includes(tag) && SINGLETON_ACTIVE_STATUSES.includes(run.status));
|
|
2330
|
+
if (!candidate || candidate.status === "cancelling") return void 0;
|
|
2331
|
+
return {
|
|
2332
|
+
status: "suspended",
|
|
2333
|
+
wakeAt: retryWakeAt,
|
|
2334
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
__name(singletonAdmissionDenialPatch, "singletonAdmissionDenialPatch");
|
|
2338
|
+
|
|
2291
2339
|
// src/singleton-gate.ts
|
|
2292
2340
|
var SINGLETON_RETRY_MS = 1e3;
|
|
2293
2341
|
var SINGLETON_RETRY_JITTER_MS = 250;
|
|
@@ -2301,6 +2349,9 @@ var SingletonGate = class {
|
|
|
2301
2349
|
}
|
|
2302
2350
|
/** The tag a singleton run carries, so the gate can find others sharing its key. */
|
|
2303
2351
|
tag(cfg, input) {
|
|
2352
|
+
if (!this.deps.store.tryAdmitSingleton) {
|
|
2353
|
+
throw new Error("Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission");
|
|
2354
|
+
}
|
|
2304
2355
|
return `singleton:${cfg.key(input)}`;
|
|
2305
2356
|
}
|
|
2306
2357
|
/** Next wake time for a gated run: the base retry delay jittered to avoid a wakeup stampede. */
|
|
@@ -2309,7 +2360,7 @@ var SingletonGate = class {
|
|
|
2309
2360
|
}
|
|
2310
2361
|
/**
|
|
2311
2362
|
* Reject a start that would grow the same-key backlog past `limit + maxQueueDepth` (counting
|
|
2312
|
-
* `pending`/`running`/`suspended` runs sharing the key in one scan). No-op when no `maxQueueDepth`
|
|
2363
|
+
* `pending`/`running`/`suspended`/`blocked`/`cancelling` runs sharing the key in one scan). No-op when no `maxQueueDepth`
|
|
2313
2364
|
* is configured.
|
|
2314
2365
|
*/
|
|
2315
2366
|
async assertCapacity(workflow, cfg, input) {
|
|
@@ -2318,34 +2369,25 @@ var SingletonGate = class {
|
|
|
2318
2369
|
const queued = await this.deps.store.listRuns({
|
|
2319
2370
|
tag: this.tag(cfg, input),
|
|
2320
2371
|
workflow,
|
|
2321
|
-
statuses:
|
|
2322
|
-
"pending",
|
|
2323
|
-
"running",
|
|
2324
|
-
"suspended",
|
|
2325
|
-
"cancelling"
|
|
2326
|
-
]
|
|
2372
|
+
statuses: SINGLETON_ACTIVE_STATUSES
|
|
2327
2373
|
});
|
|
2328
2374
|
if (queued.length >= cap) {
|
|
2329
2375
|
throw new SingletonQueueFullError(workflow, cfg.key(input), cfg.maxQueueDepth);
|
|
2330
2376
|
}
|
|
2331
2377
|
}
|
|
2332
|
-
/**
|
|
2333
|
-
* Whether `run` may run now under its key: it's among the `limit` oldest in-flight (running or
|
|
2334
|
-
* suspended) runs sharing the key, by `(createdAt, id)` order. A consistent store gives every
|
|
2335
|
-
* instance the same ordering, so admission is race-free + FIFO.
|
|
2336
|
-
*/
|
|
2378
|
+
/** Preserve durable holders and atomically claim one of the remaining slots. */
|
|
2337
2379
|
async admit(run, cfg) {
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
return
|
|
2380
|
+
if (!this.deps.store.tryAdmitSingleton) {
|
|
2381
|
+
throw new Error("Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission");
|
|
2382
|
+
}
|
|
2383
|
+
const admitted = await this.deps.store.tryAdmitSingleton(run.id, this.tag(cfg, run.input), run.workflow, cfg.limit ?? 1, this.retryWakeAt());
|
|
2384
|
+
if (admitted && !run.tags?.includes(SINGLETON_ADMITTED_TAG)) {
|
|
2385
|
+
run.tags = [
|
|
2386
|
+
...run.tags ?? [],
|
|
2387
|
+
SINGLETON_ADMITTED_TAG
|
|
2388
|
+
];
|
|
2389
|
+
}
|
|
2390
|
+
return admitted;
|
|
2349
2391
|
}
|
|
2350
2392
|
/**
|
|
2351
2393
|
* Notify-on-release: a singleton run settled (freeing a slot), so dispatch the oldest gated
|
|
@@ -3862,7 +3904,7 @@ var WorkflowEngine = class {
|
|
|
3862
3904
|
VERSION_UNDECLARED_TAG
|
|
3863
3905
|
] : []
|
|
3864
3906
|
];
|
|
3865
|
-
const tags = mergeTags(registered.tags, stampedTags);
|
|
3907
|
+
const tags = mergeTags(registered.tags, stampedTags)?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG);
|
|
3866
3908
|
if (registered.singleton) {
|
|
3867
3909
|
await this.singletons.assertCapacity(name, registered.singleton, input);
|
|
3868
3910
|
}
|
|
@@ -3937,6 +3979,12 @@ var WorkflowEngine = class {
|
|
|
3937
3979
|
await this.store.releaseRunLock(runId);
|
|
3938
3980
|
throw new NamespaceMismatch();
|
|
3939
3981
|
}
|
|
3982
|
+
if (run.status === "failed" && run.tags?.includes(SINGLETON_ADMITTED_TAG)) {
|
|
3983
|
+
run.tags = run.tags.filter((tag) => tag !== SINGLETON_ADMITTED_TAG);
|
|
3984
|
+
await this.store.updateRun(run.id, {
|
|
3985
|
+
tags: run.tags
|
|
3986
|
+
});
|
|
3987
|
+
}
|
|
3940
3988
|
const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ?? await this.findInheritedRegistration(run) ?? await this.resolveRemoteByConvention(run);
|
|
3941
3989
|
if (!registered) {
|
|
3942
3990
|
throw new Error(`workflow ${run.workflow}@${run.workflowVersion} is not registered \u2014 keep the prior version deployed so in-flight runs can drain (skew protection)`);
|
|
@@ -4086,7 +4134,10 @@ var WorkflowEngine = class {
|
|
|
4086
4134
|
/** Track an in-flight execution so {@link drain} can wait for it. */
|
|
4087
4135
|
track(p) {
|
|
4088
4136
|
this.inflight.add(p);
|
|
4089
|
-
|
|
4137
|
+
const done = /* @__PURE__ */ __name(() => {
|
|
4138
|
+
this.inflight.delete(p);
|
|
4139
|
+
}, "done");
|
|
4140
|
+
void p.then(done, done);
|
|
4090
4141
|
return p;
|
|
4091
4142
|
}
|
|
4092
4143
|
/**
|
|
@@ -4437,7 +4488,8 @@ var WorkflowEngine = class {
|
|
|
4437
4488
|
status: "pending",
|
|
4438
4489
|
error: void 0,
|
|
4439
4490
|
...resurrecting ? {
|
|
4440
|
-
recoveryAttempts: 0
|
|
4491
|
+
recoveryAttempts: 0,
|
|
4492
|
+
tags: run.tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG)
|
|
4441
4493
|
} : {},
|
|
4442
4494
|
updatedAt: /* @__PURE__ */ new Date()
|
|
4443
4495
|
});
|
|
@@ -4556,10 +4608,19 @@ var WorkflowEngine = class {
|
|
|
4556
4608
|
off();
|
|
4557
4609
|
resolve(toResult(run));
|
|
4558
4610
|
}, "finish");
|
|
4611
|
+
const fail = /* @__PURE__ */ __name((error2) => {
|
|
4612
|
+
if (done) return;
|
|
4613
|
+
done = true;
|
|
4614
|
+
if (timer) clearTimeout(timer);
|
|
4615
|
+
if (poller) clearInterval(poller);
|
|
4616
|
+
off();
|
|
4617
|
+
reject(error2);
|
|
4618
|
+
}, "fail");
|
|
4559
4619
|
const check = /* @__PURE__ */ __name(() => {
|
|
4620
|
+
if (done) return;
|
|
4560
4621
|
void this.store.getRun(runId).then((run) => {
|
|
4561
4622
|
if (run && isSettled(run)) finish(run);
|
|
4562
|
-
});
|
|
4623
|
+
}, fail);
|
|
4563
4624
|
}, "check");
|
|
4564
4625
|
const poller = opts?.until === "terminal" ? (() => {
|
|
4565
4626
|
const interval = setInterval(check, 250);
|
|
@@ -5342,6 +5403,26 @@ var WorkflowEngine = class {
|
|
|
5342
5403
|
durationMs: Date.now() - step.startedAt.getTime()
|
|
5343
5404
|
});
|
|
5344
5405
|
}
|
|
5406
|
+
/** Admission persists the wait atomically; never overwrite a cancellation after it returns. */
|
|
5407
|
+
async singletonWaitResult(run) {
|
|
5408
|
+
const current = await this.store.getRun(run.id);
|
|
5409
|
+
await this.store.releaseRunLock(run.id);
|
|
5410
|
+
if (!current) throw new Error(`run ${run.id} was deleted during singleton admission`);
|
|
5411
|
+
if (current.status === "suspended") {
|
|
5412
|
+
this.emit({
|
|
5413
|
+
type: "run.suspended",
|
|
5414
|
+
runId: current.id,
|
|
5415
|
+
workflow: current.workflow,
|
|
5416
|
+
namespace: current.namespace
|
|
5417
|
+
});
|
|
5418
|
+
}
|
|
5419
|
+
return {
|
|
5420
|
+
runId: current.id,
|
|
5421
|
+
status: current.status,
|
|
5422
|
+
output: current.output,
|
|
5423
|
+
error: current.error
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5345
5426
|
async execute(run, fn) {
|
|
5346
5427
|
const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ?? await this.findInheritedRegistration(run) ?? await this.resolveRemoteByConvention(run);
|
|
5347
5428
|
const lockNow = this.clock();
|
|
@@ -5511,23 +5592,7 @@ var WorkflowEngine = class {
|
|
|
5511
5592
|
});
|
|
5512
5593
|
}
|
|
5513
5594
|
if (registered.singleton && !await this.singletons.admit(run, registered.singleton)) {
|
|
5514
|
-
|
|
5515
|
-
await this.store.updateRun(run.id, {
|
|
5516
|
-
status: "suspended",
|
|
5517
|
-
wakeAt,
|
|
5518
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
5519
|
-
});
|
|
5520
|
-
this.emit({
|
|
5521
|
-
type: "run.suspended",
|
|
5522
|
-
runId: run.id,
|
|
5523
|
-
workflow: run.workflow,
|
|
5524
|
-
namespace: run.namespace
|
|
5525
|
-
});
|
|
5526
|
-
await this.store.releaseRunLock(run.id);
|
|
5527
|
-
return {
|
|
5528
|
-
runId: run.id,
|
|
5529
|
-
status: "suspended"
|
|
5530
|
-
};
|
|
5595
|
+
return this.singletonWaitResult(run);
|
|
5531
5596
|
}
|
|
5532
5597
|
const wfPlan = await this.planRoute(tenantGroup(sanitizeQueueToken(remote.group), void 0), registered.requires);
|
|
5533
5598
|
if (wfPlan?.status === "blocked") return this.parkBlocked(run, wfPlan);
|
|
@@ -6141,23 +6206,7 @@ var WorkflowEngine = class {
|
|
|
6141
6206
|
});
|
|
6142
6207
|
}
|
|
6143
6208
|
if (run.status !== "cancelling" && registered?.singleton && !await this.singletons.admit(run, registered.singleton)) {
|
|
6144
|
-
|
|
6145
|
-
await this.store.updateRun(run.id, {
|
|
6146
|
-
status: "suspended",
|
|
6147
|
-
wakeAt,
|
|
6148
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
6149
|
-
});
|
|
6150
|
-
this.emit({
|
|
6151
|
-
type: "run.suspended",
|
|
6152
|
-
runId: run.id,
|
|
6153
|
-
workflow: run.workflow,
|
|
6154
|
-
namespace: run.namespace
|
|
6155
|
-
});
|
|
6156
|
-
await this.store.releaseRunLock(run.id);
|
|
6157
|
-
return {
|
|
6158
|
-
runId: run.id,
|
|
6159
|
-
status: "suspended"
|
|
6160
|
-
};
|
|
6209
|
+
return this.singletonWaitResult(run);
|
|
6161
6210
|
}
|
|
6162
6211
|
const compensations = [];
|
|
6163
6212
|
const snapshot = await this.store.listCheckpoints(run.id);
|
|
@@ -7176,6 +7225,8 @@ var CodecStateStore = class {
|
|
|
7176
7225
|
}
|
|
7177
7226
|
inner;
|
|
7178
7227
|
codec;
|
|
7228
|
+
/** Atomic claims touch only searchable metadata and bypass payload encoding. */
|
|
7229
|
+
tryAdmitSingleton;
|
|
7179
7230
|
/**
|
|
7180
7231
|
* Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches
|
|
7181
7232
|
* (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store
|
|
@@ -7208,6 +7259,7 @@ var CodecStateStore = class {
|
|
|
7208
7259
|
constructor(inner, codec) {
|
|
7209
7260
|
this.inner = inner;
|
|
7210
7261
|
this.codec = codec;
|
|
7262
|
+
if (inner.tryAdmitSingleton) this.tryAdmitSingleton = inner.tryAdmitSingleton.bind(inner);
|
|
7211
7263
|
const deleteRuns = inner.deleteRuns;
|
|
7212
7264
|
if (deleteRuns) this.deleteRuns = (ids) => deleteRuns.call(inner, ids);
|
|
7213
7265
|
const prune = inner.pruneTerminalRuns;
|
|
@@ -7660,6 +7712,28 @@ var InMemoryStateStore = class {
|
|
|
7660
7712
|
byRun.set(runId, row);
|
|
7661
7713
|
}
|
|
7662
7714
|
}
|
|
7715
|
+
async tryAdmitSingleton(runId, tag, workflow, limit, retryWakeAt) {
|
|
7716
|
+
const runs = [
|
|
7717
|
+
...this.runs.values()
|
|
7718
|
+
];
|
|
7719
|
+
const tags = singletonAdmissionTags(runs, runId, tag, workflow, limit);
|
|
7720
|
+
if (!tags) {
|
|
7721
|
+
const patch = singletonAdmissionDenialPatch(runs, runId, tag, workflow, retryWakeAt);
|
|
7722
|
+
const candidate = this.runs.get(runId);
|
|
7723
|
+
if (patch && candidate) this.runs.set(runId, {
|
|
7724
|
+
...candidate,
|
|
7725
|
+
...patch
|
|
7726
|
+
});
|
|
7727
|
+
return false;
|
|
7728
|
+
}
|
|
7729
|
+
const run = this.runs.get(runId);
|
|
7730
|
+
if (!run) return false;
|
|
7731
|
+
this.runs.set(runId, {
|
|
7732
|
+
...run,
|
|
7733
|
+
tags
|
|
7734
|
+
});
|
|
7735
|
+
return true;
|
|
7736
|
+
}
|
|
7663
7737
|
async createRun(run) {
|
|
7664
7738
|
this.runs.set(run.id, {
|
|
7665
7739
|
...run,
|
|
@@ -7667,7 +7741,11 @@ var InMemoryStateStore = class {
|
|
|
7667
7741
|
});
|
|
7668
7742
|
this.reindexAttributes(run.id, run.searchAttributes);
|
|
7669
7743
|
}
|
|
7670
|
-
async updateRun(runId,
|
|
7744
|
+
async updateRun(runId, inputPatch) {
|
|
7745
|
+
const patch = inputPatch.status && TERMINAL_RUN_STATUSES.includes(inputPatch.status) ? {
|
|
7746
|
+
...inputPatch,
|
|
7747
|
+
tags: ("tags" in inputPatch ? inputPatch.tags : this.runs.get(runId)?.tags)?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG)
|
|
7748
|
+
} : inputPatch;
|
|
7671
7749
|
const existing = this.runs.get(runId);
|
|
7672
7750
|
if (!existing) throw new Error(`run ${runId} not found`);
|
|
7673
7751
|
const next = {
|
|
@@ -8091,6 +8169,8 @@ export {
|
|
|
8091
8169
|
RemoteWorkflowExecutor,
|
|
8092
8170
|
RemoteWorkflowTimeout,
|
|
8093
8171
|
RunGateway,
|
|
8172
|
+
SINGLETON_ACTIVE_STATUSES,
|
|
8173
|
+
SINGLETON_ADMITTED_TAG,
|
|
8094
8174
|
STATE_STORE,
|
|
8095
8175
|
STATE_STORE_CANONICAL,
|
|
8096
8176
|
ScheduleAlreadyExistsError,
|
|
@@ -8121,6 +8201,7 @@ export {
|
|
|
8121
8201
|
capableWorkers,
|
|
8122
8202
|
classifyWaiterToken,
|
|
8123
8203
|
clearDurableExecutionWrappers,
|
|
8204
|
+
clearTerminalSingletonAdmission,
|
|
8124
8205
|
collectMetrics,
|
|
8125
8206
|
concurrencyTag,
|
|
8126
8207
|
controlPlaneDescriptor,
|
|
@@ -8178,6 +8259,8 @@ export {
|
|
|
8178
8259
|
runValueFacetsFromRuns,
|
|
8179
8260
|
sanitizeQueueToken,
|
|
8180
8261
|
scheduledRunId,
|
|
8262
|
+
singletonAdmissionDenialPatch,
|
|
8263
|
+
singletonAdmissionTags,
|
|
8181
8264
|
sqlComparator,
|
|
8182
8265
|
stepConfigOf,
|
|
8183
8266
|
stepId,
|