@lostgradient/weft 0.12.0 → 0.14.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/README.md +1 -1
- package/dist/cli/api.d.ts +2 -0
- package/dist/cli/api.js +3 -4
- package/dist/cli/generated/operation-catalog.snapshot.json +508 -12
- package/dist/cli/generated/operation-client.generated.d.ts +118 -10
- package/dist/cli/generated/operation-client.generated.js +74 -1
- package/dist/cli/help-text.d.ts +3 -3
- package/dist/cli/help-text.js +4 -4
- package/dist/cli/operation-catalog-snapshot.d.ts +12 -3
- package/dist/cli/operation-catalog-snapshot.js +14 -5
- package/dist/cli/operation-client-runtime.d.ts +29 -0
- package/dist/cli/schedule.js +1 -3
- package/dist/cli/serve-registrations.d.ts +3 -3
- package/dist/cli/serve-registrations.js +2 -2
- package/dist/cli/shutdown.d.ts +11 -0
- package/dist/cli/shutdown.js +25 -0
- package/dist/cli/validate.d.ts +1 -1
- package/dist/cli/version-check.d.ts +1 -1
- package/dist/cli/version-check.js +1 -1
- package/dist/cli-main.js +10 -29
- package/dist/client/client-storage.d.ts +24 -0
- package/dist/client/client-storage.js +14 -0
- package/dist/client/handle-delegation.d.ts +3 -3
- package/dist/client/handle-delegation.js +2 -2
- package/dist/client/http-client-requests.d.ts +5 -3
- package/dist/client/http-client-requests.js +20 -2
- package/dist/client/http-client-storage.d.ts +3 -0
- package/dist/client/http-client-storage.js +82 -0
- package/dist/client/http-client.d.ts +9 -6
- package/dist/client/http-client.js +13 -18
- package/dist/client/http-operations.d.ts +3 -1
- package/dist/client/http-operations.js +77 -1
- package/dist/client/http-request.d.ts +20 -14
- package/dist/client/http-request.js +21 -31
- package/dist/client/in-process-operations.d.ts +2 -2
- package/dist/client/in-process-operations.js +2 -2
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.js +13 -2
- package/dist/client/interface.d.ts +26 -26
- package/dist/client/local.d.ts +9 -6
- package/dist/client/local.js +9 -4
- package/dist/client/search-params.js +10 -6
- package/dist/client/start-body.d.ts +3 -1
- package/dist/client/start-body.js +9 -0
- package/dist/core/bulk-workflow-filter.d.ts +2 -1
- package/dist/core/bulk-workflow-filter.js +5 -1
- package/dist/core/context/parallel-operations.d.ts +0 -2
- package/dist/core/context/parallel-operations.js +0 -7
- package/dist/core/engine/async-activity-records.d.ts +12 -1
- package/dist/core/engine/async-activity-records.js +81 -2
- package/dist/core/engine/bulk-operations-purge.js +16 -1
- package/dist/core/engine/bulk-operations-shared.js +2 -0
- package/dist/core/engine/callback-checkpoint-persistence.d.ts +2 -0
- package/dist/core/engine/callback-checkpoint-persistence.js +6 -3
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -1
- package/dist/core/engine/callback-creators-schedule.js +3 -3
- package/dist/core/engine/callback-creators.js +4 -22
- package/dist/core/engine/checkpoint-io.d.ts +1 -1
- package/dist/core/engine/checkpoint-reads.js +11 -1
- package/dist/core/engine/child-workflow.js +15 -6
- package/dist/core/engine/construction.js +3 -0
- package/dist/core/engine/disposal.js +2 -0
- package/dist/core/engine/engine-internal-types.d.ts +4 -1
- package/dist/core/engine/fenced-write.d.ts +5 -3
- package/dist/core/engine/finalizer-status.d.ts +10 -0
- package/dist/core/engine/finalizer-status.js +82 -0
- package/dist/core/engine/index.d.ts +26 -2
- package/dist/core/engine/index.js +71 -8
- package/dist/core/engine/internals.d.ts +3 -0
- package/dist/core/engine/lease-health.d.ts +64 -0
- package/dist/core/engine/lease-health.js +0 -0
- package/dist/core/engine/lease-manager.d.ts +4 -2
- package/dist/core/engine/lease-manager.js +32 -4
- package/dist/core/engine/lifecycle/recovered-services.js +0 -2
- package/dist/core/engine/lifecycle/shared.d.ts +11 -8
- package/dist/core/engine/lifecycle/start-batch.js +12 -0
- package/dist/core/engine/lifecycle/start.d.ts +1 -1
- package/dist/core/engine/lifecycle/start.js +34 -5
- package/dist/core/engine/operations-coordination.d.ts +1 -12
- package/dist/core/engine/operations-coordination.js +58 -11
- package/dist/core/engine/operations-speculate.d.ts +1 -1
- package/dist/core/engine/operations-speculate.js +19 -5
- package/dist/core/engine/parallel-dispatch.d.ts +1 -1
- package/dist/core/engine/parallel-dispatch.js +1 -1
- package/dist/core/engine/registration.js +14 -0
- package/dist/core/engine/review-list-entries.d.ts +1 -1
- package/dist/core/engine/review-list-entries.js +6 -30
- package/dist/core/engine/schedule-handle.d.ts +4 -4
- package/dist/core/engine/schedule-handle.js +2 -2
- package/dist/core/engine/schedule-overlap.d.ts +11 -0
- package/dist/core/engine/schedule-overlap.js +50 -0
- package/dist/core/engine/schedule-run.d.ts +11 -3
- package/dist/core/engine/schedule-run.js +27 -4
- package/dist/core/engine/schedule-timer.js +10 -1
- package/dist/core/engine/schedules.d.ts +5 -4
- package/dist/core/engine/schedules.js +62 -56
- package/dist/core/engine/state-utilities.js +1 -1
- package/dist/core/engine/storage-io.d.ts +12 -0
- package/dist/core/engine/storage-io.js +49 -10
- package/dist/core/engine/termination/finalizer-claim.d.ts +8 -6
- package/dist/core/engine/termination/finalizer-claim.js +2 -1
- package/dist/core/engine/termination/finalizer.js +10 -14
- package/dist/core/engine/timeline-coordinator-constants.d.ts +3 -0
- package/dist/core/engine/timeline-coordinator-constants.js +1 -0
- package/dist/core/engine/timeline-coordinator-detail.d.ts +13 -0
- package/dist/core/engine/timeline-coordinator-detail.js +76 -0
- package/dist/core/engine/validation/schedule-options.d.ts +8 -1
- package/dist/core/engine/validation/schedule-options.js +18 -0
- package/dist/core/engine/validation/schedule.d.ts +1 -1
- package/dist/core/engine/validation/schedule.js +27 -3
- package/dist/core/engine/validation.js +66 -2
- package/dist/core/engine/workflow-state-stream.d.ts +5 -1
- package/dist/core/engine/workflow-state-stream.js +37 -14
- package/dist/core/events/schedule-events.d.ts +3 -4
- package/dist/core/events/workflow-events.d.ts +2 -1
- package/dist/core/list-filter-validation.d.ts +3 -0
- package/dist/core/list-filter-validation.js +11 -0
- package/dist/core/registry-snapshot.d.ts +32 -0
- package/dist/core/registry-snapshot.js +28 -0
- package/dist/core/review/index.d.ts +91 -4
- package/dist/core/review/index.js +29 -0
- package/dist/core/types/activity.d.ts +52 -5
- package/dist/core/types/bulk.d.ts +1 -0
- package/dist/core/types/list-options.d.ts +6 -0
- package/dist/core/types/options.d.ts +6 -5
- package/dist/core/types/reviews.d.ts +2 -2
- package/dist/core/types/schedules.d.ts +45 -2
- package/dist/core/types/services-resolution.d.ts +5 -5
- package/dist/core/types/state.d.ts +64 -0
- package/dist/core/types/workflow-log.d.ts +3 -2
- package/dist/core/types/workflow-observability.d.ts +50 -0
- package/dist/core/types/workflow-observability.js +0 -0
- package/dist/core/types/workflow-registry.d.ts +7 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.js +1 -0
- package/dist/diagnostics/validate.d.ts +9 -30
- package/dist/diagnostics/validate.js +83 -21
- package/dist/diagnostics/version-check.d.ts +2 -2
- package/dist/http.js +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/indexeddb.js +1 -1
- package/dist/server/access-policy-metadata.d.ts +92 -0
- package/dist/server/access-policy-metadata.js +78 -0
- package/dist/server/fault-to-http.d.ts +3 -7
- package/dist/server/fault-to-http.js +2 -34
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/route-dispatch.d.ts +10 -3
- package/dist/server/handler/route-dispatch.js +19 -4
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/interactive-operations.js +2 -0
- package/dist/server/openapi-error-responses.js +41 -4
- package/dist/server/openapi.d.ts +3 -1
- package/dist/server/openapi.js +4 -0
- package/dist/server/openrpc-document-schema.d.ts +64 -0
- package/dist/server/openrpc-document-schema.js +6 -26
- package/dist/server/openrpc.d.ts +4 -0
- package/dist/server/openrpc.js +9 -33
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/raise-fault.d.ts +2 -1
- package/dist/server/operation-catalog/types.d.ts +2 -1
- package/dist/server/operation-fault.d.ts +22 -8
- package/dist/server/operation-fault.js +65 -13
- package/dist/server/operation-registry.d.ts +1 -1
- package/dist/server/operations/aggregate-workflows.d.ts +6 -0
- package/dist/server/operations/aggregate-workflows.js +3 -2
- package/dist/server/operations/async-activity.d.ts +14 -0
- package/dist/server/operations/async-activity.js +88 -4
- package/dist/server/operations/bulk-filter-helpers.d.ts +3 -0
- package/dist/server/operations/bulk-filter-helpers.js +27 -3
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +6 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +6 -0
- package/dist/server/operations/get-stream-chunks.js +2 -7
- package/dist/server/operations/get-system-lease.d.ts +19 -0
- package/dist/server/operations/get-system-lease.js +48 -0
- package/dist/server/operations/get-workflow-observability.d.ts +24 -0
- package/dist/server/operations/get-workflow-observability.js +80 -0
- package/dist/server/operations/get-workflow-result.js +2 -2
- package/dist/server/operations/get-workflow.d.ts +2 -2
- package/dist/server/operations/list-filter-query-extractor.js +15 -0
- package/dist/server/operations/list-reviews.js +2 -19
- package/dist/server/operations/list-workflows.d.ts +6 -0
- package/dist/server/operations/list-workflows.js +12 -3
- package/dist/server/operations/operation-helpers.d.ts +9 -18
- package/dist/server/operations/operation-helpers.js +5 -23
- package/dist/server/operations/purge-workflows.d.ts +3 -0
- package/dist/server/operations/recover-all.js +1 -9
- package/dist/server/operations/single-workflow-control-operation.d.ts +2 -1
- package/dist/server/operations/single-workflow-tag-mutation.js +2 -2
- package/dist/server/operations/sse-stream.js +2 -7
- package/dist/server/operations/storage-capabilities.d.ts +34 -0
- package/dist/server/operations/storage-capabilities.js +38 -0
- package/dist/server/operations/storage.js +8 -17
- package/dist/server/operations/stream-workflow-sse.js +3 -9
- package/dist/server/operations/update-schedule.d.ts +8 -0
- package/dist/server/operations/update-schedule.js +70 -7
- package/dist/server/operations/workflow-events-sse.js +2 -2
- package/dist/server/rest-binding.d.ts +7 -6
- package/dist/server/rest-bindings.d.ts +2 -13
- package/dist/server/rest-bindings.js +19 -10
- package/dist/server/task-queue.d.ts +7 -5
- package/dist/storage/bounded-ndjson-response.d.ts +5 -0
- package/dist/storage/bounded-ndjson-response.js +33 -0
- package/dist/storage/capabilities.d.ts +1 -1
- package/dist/storage/cloudflare-value-codec.d.ts +5 -3
- package/dist/storage/cloudflare-value-codec.js +1 -1
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/http.js +5 -37
- package/dist/storage/index.d.ts +7 -1
- package/dist/storage/interface.d.ts +16 -4
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +4 -0
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.d.ts +3 -16
- package/dist/storage/neon.js +4 -4
- package/dist/storage/postgres.js +4 -4
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -1
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ import { asyncActivityWorkflowPrefix } from "./async-activity-records.js";
|
|
|
12
12
|
import { forgetCommittedCheckpointBytes } from "./checkpoint-commit-snapshots.js";
|
|
13
13
|
import { commitFencedEngineWrite } from "./fenced-write.js";
|
|
14
14
|
import { streamWorkflowStates } from "./listing.js";
|
|
15
|
+
import { decodeScheduleRunMetadata } from "./schedule-run-metadata.js";
|
|
15
16
|
import { createTerminalCleanupTimerId } from "./state-utilities.js";
|
|
16
17
|
import {
|
|
17
18
|
decodeWorkflowState,
|
|
@@ -181,12 +182,22 @@ async function collectWorkflowPurgeDeleteKeys(internals, state) {
|
|
|
181
182
|
const workflowId = state.id, deleteKeys = buildBaseWorkflowDeleteKeys(state);
|
|
182
183
|
addExecutionDeadlineDeleteKeys(deleteKeys, state);
|
|
183
184
|
addTerminalCleanupDeleteKey(deleteKeys, state);
|
|
185
|
+
await addScheduleRunHistoryDeleteKeys(internals.storage, deleteKeys, workflowId);
|
|
184
186
|
await addUpdateRequestDeleteKeys(internals.storage, deleteKeys, workflowId);
|
|
185
187
|
await addWorkflowPrefixDeleteKeys(internals.storage, deleteKeys, workflowId);
|
|
186
188
|
return deleteKeys;
|
|
187
189
|
}
|
|
190
|
+
async function addScheduleRunHistoryDeleteKeys(storage, deleteKeys, workflowId) {
|
|
191
|
+
const linkKey = KEYS.scheduleRunLink(workflowId), linkBytes = await storage.get(linkKey);
|
|
192
|
+
deleteKeys.add(linkKey);
|
|
193
|
+
if (linkBytes === null)
|
|
194
|
+
return;
|
|
195
|
+
const metadata = decodeScheduleRunMetadata(linkBytes);
|
|
196
|
+
if (metadata !== null)
|
|
197
|
+
deleteKeys.add(KEYS.scheduleRunBySchedule(metadata.id, workflowId));
|
|
198
|
+
}
|
|
188
199
|
function buildBaseWorkflowDeleteKeys(state) {
|
|
189
|
-
|
|
200
|
+
const keys = new Set([
|
|
190
201
|
KEYS.workflow(state.id),
|
|
191
202
|
KEYS.checkpoint(state.id),
|
|
192
203
|
KEYS.workflowHeaders(state.id),
|
|
@@ -196,9 +207,13 @@ function buildBaseWorkflowDeleteKeys(state) {
|
|
|
196
207
|
KEYS.workflowHasServices(state.id),
|
|
197
208
|
KEYS.finalizerState(state.id),
|
|
198
209
|
KEYS.teardownOwed(state.id),
|
|
210
|
+
KEYS.teardownSucceeded(state.id),
|
|
199
211
|
KEYS.attribute(state.id),
|
|
200
212
|
KEYS.terminalWorkflow(state.updatedAt, state.id)
|
|
201
213
|
]);
|
|
214
|
+
if (state.parentWorkflowId !== void 0)
|
|
215
|
+
keys.add(KEYS.childWorkflowByParent(state.parentWorkflowId, state.parentWorkflowExecutionToken, state.id));
|
|
216
|
+
return keys;
|
|
202
217
|
}
|
|
203
218
|
function addExecutionDeadlineDeleteKeys(deleteKeys, state) {
|
|
204
219
|
if (state.executionDeadline === void 0)
|
|
@@ -63,6 +63,8 @@ function summarizeBulkFilter(filter) {
|
|
|
63
63
|
summary.status = Array.isArray(filter.status) ? uniqueSorted(filter.status) : filter.status;
|
|
64
64
|
if (filter.type !== void 0)
|
|
65
65
|
summary.type = filter.type;
|
|
66
|
+
if (filter.scheduleId !== void 0)
|
|
67
|
+
summary.scheduleId = filter.scheduleId;
|
|
66
68
|
const normalizedTags = normalizeWorkflowTags(filter.tags);
|
|
67
69
|
if (normalizedTags !== void 0)
|
|
68
70
|
summary.tags = normalizedTags;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ContextOperationRequest } from '../context.ts';
|
|
2
|
+
import { type PersistCheckpointCallbacks } from './checkpoint-io.ts';
|
|
2
3
|
import type { Engine } from './index.ts';
|
|
4
|
+
export declare function createCheckpointPersistenceCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): PersistCheckpointCallbacks;
|
|
3
5
|
export declare function persistCheckpointForDataOperation<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, workflowId: string, operation: ContextOperationRequest): Promise<void>;
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
import { getInternals } from "./internals.js";
|
|
10
10
|
import { swallowPromiseRejection } from "./strategy-helpers.js";
|
|
11
11
|
import { terminateWorkflow } from "./termination.js";
|
|
12
|
-
export function
|
|
13
|
-
return
|
|
12
|
+
export function createCheckpointPersistenceCallbacks(engine) {
|
|
13
|
+
return {
|
|
14
14
|
appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
|
|
15
15
|
swallowPromiseRejection: (promise) => {
|
|
16
16
|
swallowPromiseRejection(promise);
|
|
@@ -21,5 +21,8 @@ export function persistCheckpointForDataOperation(engine, workflowId, operation)
|
|
|
21
21
|
engine.dispatchEvent(event);
|
|
22
22
|
},
|
|
23
23
|
enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function persistCheckpointForDataOperation(engine, workflowId, operation) {
|
|
27
|
+
return persistCheckpoint(getInternals(engine), workflowId, operation, void 0, createCheckpointPersistenceCallbacks(engine), { timeline: "preserve-pending" });
|
|
25
28
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ScheduleState, TimerEntry } from '../types.ts';
|
|
2
2
|
import type { Engine } from './index.ts';
|
|
3
3
|
import type { ReviewOperationCallbacks, SubmitReviewCallbacks } from './reviews.ts';
|
|
4
|
+
import type { ScheduledRunStartOptions } from './schedule-run.ts';
|
|
4
5
|
import { type RefreshedScheduleState, type ScheduleCallbacks } from './schedules.ts';
|
|
5
6
|
export declare function createScheduleCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): ScheduleCallbacks;
|
|
6
7
|
export declare function createReviewOperationCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): ReviewOperationCallbacks;
|
|
7
8
|
export declare function createSubmitReviewCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): SubmitReviewCallbacks;
|
|
8
9
|
export declare function refreshScheduledWorkflowStateForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState): Promise<RefreshedScheduleState>;
|
|
9
|
-
export declare function startScheduledRunForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState,
|
|
10
|
+
export declare function startScheduledRunForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState, options?: ScheduledRunStartOptions): Promise<string>;
|
|
10
11
|
export declare function applyScheduleOccurrenceForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState, occurrence?: number): Promise<ScheduleState>;
|
|
11
12
|
export declare function settleBackfillScheduleStateForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState): Promise<ScheduleState>;
|
|
12
13
|
export declare function handleScheduleTimerForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, entry: TimerEntry): Promise<void>;
|
|
@@ -27,7 +27,7 @@ export function createScheduleCallbacks(engine) {
|
|
|
27
27
|
cancelWorkflow: (workflowId) => engine.cancel(workflowId),
|
|
28
28
|
getWorkflowResult: (workflowId) => engine.getHandle(workflowId).result(),
|
|
29
29
|
refreshScheduledWorkflowState: (state) => refreshScheduledWorkflowStateForEngine(engine, state),
|
|
30
|
-
startScheduledRun: (state,
|
|
30
|
+
startScheduledRun: (state, options) => startScheduledRunForEngine(engine, state, options),
|
|
31
31
|
applyScheduleOccurrence: (state, occurrence) => applyScheduleOccurrenceForEngine(engine, state, occurrence),
|
|
32
32
|
settleBackfillScheduleState: (state) => settleBackfillScheduleStateForEngine(engine, state),
|
|
33
33
|
flushQueuedInlineWorkflowStartsDirectly: () => flushQueuedInlineWorkflowStartsDirectly(getInternals(engine), createInlineLaunchQueueCallbacks(engine)),
|
|
@@ -51,8 +51,8 @@ export function createSubmitReviewCallbacks(engine) {
|
|
|
51
51
|
export async function refreshScheduledWorkflowStateForEngine(engine, state) {
|
|
52
52
|
return refreshScheduledWorkflowState(getInternals(engine), state, createScheduleCallbacks(engine));
|
|
53
53
|
}
|
|
54
|
-
export async function startScheduledRunForEngine(engine, state,
|
|
55
|
-
return startScheduledRun(getInternals(engine), state, createScheduleCallbacks(engine),
|
|
54
|
+
export async function startScheduledRunForEngine(engine, state, options) {
|
|
55
|
+
return startScheduledRun(getInternals(engine), state, createScheduleCallbacks(engine), options);
|
|
56
56
|
}
|
|
57
57
|
export async function applyScheduleOccurrenceForEngine(engine, state, occurrence) {
|
|
58
58
|
return applyScheduleOccurrence(getInternals(engine), state, createScheduleCallbacks(engine), occurrence);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { KEYS } from "../../storage/interface.js";
|
|
2
|
-
import {
|
|
3
|
-
import { validateAttributeValueSizes } from "./attributes-tags.js";
|
|
2
|
+
import { createCheckpointPersistenceCallbacks } from "./callback-checkpoint-persistence.js";
|
|
4
3
|
import {
|
|
5
4
|
createConstraintCallbacks,
|
|
6
5
|
createLifecycleCallbacks,
|
|
@@ -8,12 +7,7 @@ import {
|
|
|
8
7
|
registerEnsureRetentionSweepInterval
|
|
9
8
|
} from "./callback-creators-core.js";
|
|
10
9
|
import { createOperationRouterCallbacks } from "./callback-creators-router.js";
|
|
11
|
-
import {
|
|
12
|
-
appendTimelineBatchOperations,
|
|
13
|
-
persistCheckpoint,
|
|
14
|
-
pruneCheckpointHistory,
|
|
15
|
-
validateDevelopmentCheckpoint
|
|
16
|
-
} from "./checkpoint-io.js";
|
|
10
|
+
import { persistCheckpoint, validateDevelopmentCheckpoint } from "./checkpoint-io.js";
|
|
17
11
|
import { evaluateConstraints } from "./constraints.js";
|
|
18
12
|
import {
|
|
19
13
|
getParkedWorkflowResumeDisposition,
|
|
@@ -30,8 +24,7 @@ import {
|
|
|
30
24
|
} from "./retention.js";
|
|
31
25
|
import { hasBufferedSignal } from "./signals.js";
|
|
32
26
|
import { loadWorkflowState, runSerializedWorkflowStateWrite } from "./storage-io.js";
|
|
33
|
-
import {
|
|
34
|
-
import { cleanupWaiters, terminateWorkflow } from "./termination.js";
|
|
27
|
+
import { cleanupWaiters } from "./termination.js";
|
|
35
28
|
export { createUpdateCallbacks } from "./callback-creators-bundles.js";
|
|
36
29
|
export {
|
|
37
30
|
createBroadcastCallbacks,
|
|
@@ -64,18 +57,7 @@ export function createInlineParkingCallbacks(engine) {
|
|
|
64
57
|
};
|
|
65
58
|
}
|
|
66
59
|
export function persistCheckpointForEngine(engine, workflowId, operation, workerCheckpointBytes) {
|
|
67
|
-
return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes,
|
|
68
|
-
appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
|
|
69
|
-
swallowPromiseRejection: (promise) => {
|
|
70
|
-
swallowPromiseRejection(promise);
|
|
71
|
-
},
|
|
72
|
-
validateAttributeValueSizes,
|
|
73
|
-
pruneCheckpointHistory: (id, step) => pruneCheckpointHistory(getInternals(engine), id, step),
|
|
74
|
-
dispatchEvent: (event) => {
|
|
75
|
-
engine.dispatchEvent(event);
|
|
76
|
-
},
|
|
77
|
-
enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
|
|
78
|
-
});
|
|
60
|
+
return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes, createCheckpointPersistenceCallbacks(engine));
|
|
79
61
|
}
|
|
80
62
|
function ensureRetentionSweepIntervalForEngine(engine) {
|
|
81
63
|
ensureRetentionSweepInterval(getInternals(engine), {
|
|
@@ -9,7 +9,7 @@ type PendingTimelineEntryValue = {
|
|
|
9
9
|
export type PersistCheckpointOptions = {
|
|
10
10
|
timeline?: 'record-operation' | 'preserve-pending';
|
|
11
11
|
};
|
|
12
|
-
type PersistCheckpointCallbacks = {
|
|
12
|
+
export type PersistCheckpointCallbacks = {
|
|
13
13
|
appendTimelineBatchOperations: (workflowId: string, operation: ContextOperationRequest, step: number, timestamp: number, operations: BatchOperation[]) => PendingTimelineEntryValue;
|
|
14
14
|
swallowPromiseRejection: (promise: Promise<void>) => void;
|
|
15
15
|
validateAttributeValueSizes: (attributes: Record<string, SearchAttributeValue>) => void;
|
|
@@ -66,12 +66,22 @@ export async function getTimeline(internals, workflowId) {
|
|
|
66
66
|
inputSummary: sanitizeTimelineSummary(decoded.inputSummary) ?? decoded.inputSummary,
|
|
67
67
|
...decoded.outputSummary !== void 0 ? {
|
|
68
68
|
outputSummary: sanitizeTimelineSummary(decoded.outputSummary) ?? decoded.outputSummary
|
|
69
|
-
} : {}
|
|
69
|
+
} : {},
|
|
70
|
+
...decoded.branches === void 0 ? {} : { branches: decoded.branches.map(sanitizeTimelineOperationDetail) },
|
|
71
|
+
...decoded.children === void 0 ? {} : { children: decoded.children.map(sanitizeTimelineOperationDetail) }
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
timeline.sort((left, right) => left.step - right.step);
|
|
73
75
|
return timeline;
|
|
74
76
|
}
|
|
77
|
+
function sanitizeTimelineOperationDetail(detail) {
|
|
78
|
+
if (detail.errorSummary === void 0)
|
|
79
|
+
return detail;
|
|
80
|
+
return {
|
|
81
|
+
...detail,
|
|
82
|
+
errorSummary: sanitizeTimelineSummary(detail.errorSummary) ?? detail.errorSummary
|
|
83
|
+
};
|
|
84
|
+
}
|
|
75
85
|
export async function replayTo(internals, workflowId, step) {
|
|
76
86
|
const bytes = await internals.storage.get(KEYS.checkpointHistory(workflowId, step));
|
|
77
87
|
if (!bytes)
|
|
@@ -22,6 +22,8 @@ function applyPendingChildExecutionContext(internals, context) {
|
|
|
22
22
|
internals.pendingNestingDepth = context.pendingNestingDepth;
|
|
23
23
|
internals.pendingParentHeaders = context.pendingParentHeaders;
|
|
24
24
|
internals.pendingExecutionStateOwnerId = context.pendingExecutionStateOwnerId;
|
|
25
|
+
internals.pendingParentWorkflowId = context.pendingParentWorkflowId;
|
|
26
|
+
internals.pendingParentWorkflowExecutionToken = context.pendingParentWorkflowExecutionToken;
|
|
25
27
|
}
|
|
26
28
|
function clearPendingChildExecutionContext(internals, context) {
|
|
27
29
|
if (internals.pendingNestingDepth === context.pendingNestingDepth)
|
|
@@ -30,15 +32,20 @@ function clearPendingChildExecutionContext(internals, context) {
|
|
|
30
32
|
internals.pendingParentHeaders = void 0;
|
|
31
33
|
if (internals.pendingExecutionStateOwnerId === context.pendingExecutionStateOwnerId)
|
|
32
34
|
internals.pendingExecutionStateOwnerId = void 0;
|
|
35
|
+
if (internals.pendingParentWorkflowId === context.pendingParentWorkflowId)
|
|
36
|
+
internals.pendingParentWorkflowId = void 0;
|
|
37
|
+
if (internals.pendingParentWorkflowExecutionToken === context.pendingParentWorkflowExecutionToken)
|
|
38
|
+
internals.pendingParentWorkflowExecutionToken = void 0;
|
|
33
39
|
}
|
|
34
|
-
function existingChildMatchesRequest(existingState, operation, executionStateOwnerId) {
|
|
35
|
-
|
|
40
|
+
function existingChildMatchesRequest(existingState, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken) {
|
|
41
|
+
const lineageMatches = existingState.parentWorkflowId === void 0 && existingState.parentWorkflowExecutionToken === void 0 || existingState.parentWorkflowId === parentWorkflowId && existingState.parentWorkflowExecutionToken === parentWorkflowExecutionToken;
|
|
42
|
+
return existingState.type === operation.workflowType && encodedValuesEqual(existingState.input, operation.input) && existingState.executionStateOwnerId === executionStateOwnerId && lineageMatches;
|
|
36
43
|
}
|
|
37
|
-
async function resolveCollisionChildHandle(childWorkflowId, operation, executionStateOwnerId, collisionError, callbacks) {
|
|
44
|
+
async function resolveCollisionChildHandle(childWorkflowId, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, collisionError, callbacks) {
|
|
38
45
|
const existingState = await callbacks.loadWorkflowState(childWorkflowId);
|
|
39
46
|
if (!existingState)
|
|
40
47
|
throw collisionError;
|
|
41
|
-
if (!existingChildMatchesRequest(existingState, operation, executionStateOwnerId))
|
|
48
|
+
if (!existingChildMatchesRequest(existingState, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken))
|
|
42
49
|
throw Error(`Child workflow id collision for "${childWorkflowId}" does not match the requested child workflow`, { cause: collisionError });
|
|
43
50
|
return callbacks.getHandle(childWorkflowId);
|
|
44
51
|
}
|
|
@@ -52,7 +59,7 @@ async function dispatchChildWorkflowStart(internals, childWorkflowId, operation,
|
|
|
52
59
|
} catch (error) {
|
|
53
60
|
if (!(error instanceof WorkflowAlreadyExistsError))
|
|
54
61
|
throw error;
|
|
55
|
-
return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId ?? void 0, error, callbacks);
|
|
62
|
+
return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId ?? void 0, context.pendingParentWorkflowId, context.pendingParentWorkflowExecutionToken, error, callbacks);
|
|
56
63
|
} finally {
|
|
57
64
|
clearPendingChildExecutionContext(internals, context);
|
|
58
65
|
}
|
|
@@ -62,7 +69,9 @@ export async function executeChildWorkflow(internals, workflowId, operation, cur
|
|
|
62
69
|
const context = {
|
|
63
70
|
pendingNestingDepth: currentDepth + 1,
|
|
64
71
|
pendingParentHeaders: internals.workflowHeaders.get(workflowId),
|
|
65
|
-
pendingExecutionStateOwnerId: executionStateOwnerId
|
|
72
|
+
pendingExecutionStateOwnerId: executionStateOwnerId,
|
|
73
|
+
pendingParentWorkflowId: workflowId,
|
|
74
|
+
pendingParentWorkflowExecutionToken: parentState?.workflowExecutionToken
|
|
66
75
|
}, childHandle = await dispatchChildWorkflowStart(internals, childWorkflowId, operation, context, callbacks);
|
|
67
76
|
if (parentClosePolicy === "abandon")
|
|
68
77
|
return createChildWorkflowHandleReference(childHandle.id);
|
|
@@ -72,6 +72,9 @@ export function copyWorkflowDefinition(type, registration) {
|
|
|
72
72
|
...registration.description === void 0 ? {} : { description: registration.description },
|
|
73
73
|
...registration.inputSchema === void 0 ? {} : { inputSchema: registration.inputSchema },
|
|
74
74
|
...registration.outputSchema === void 0 ? {} : { outputSchema: registration.outputSchema },
|
|
75
|
+
...registration.signals === void 0 ? {} : { signals: { ...registration.signals } },
|
|
76
|
+
...registration.updates === void 0 ? {} : { updates: { ...registration.updates } },
|
|
77
|
+
...registration.queries === void 0 ? {} : { queries: { ...registration.queries } },
|
|
75
78
|
...registration.searchAttributes === void 0 ? {} : { searchAttributes: registration.searchAttributes },
|
|
76
79
|
...registration.concurrency === void 0 ? {} : { concurrency: registration.concurrency }
|
|
77
80
|
};
|
|
@@ -53,6 +53,8 @@ export function disposeEngine(internals) {
|
|
|
53
53
|
internals.sleepTimersFiredWithoutResolver.clear();
|
|
54
54
|
internals.checkpoints.clear();
|
|
55
55
|
internals.pendingExecutionStateOwnerId = void 0;
|
|
56
|
+
internals.pendingParentWorkflowId = void 0;
|
|
57
|
+
internals.pendingParentWorkflowExecutionToken = void 0;
|
|
56
58
|
internals.workflowNestingDepths.clear();
|
|
57
59
|
internals.workflowServices.clear();
|
|
58
60
|
internals.workflowHeaders.clear();
|
|
@@ -2,7 +2,7 @@ import type { Storage as WeftStorage } from '../../storage/interface.ts';
|
|
|
2
2
|
import type { ConstraintDefinition } from '../constraint.ts';
|
|
3
3
|
import type { ExecutionStrategy } from '../execution-strategy.ts';
|
|
4
4
|
import type { InlineExecutionStrategy } from '../inline-execution-strategy.ts';
|
|
5
|
-
import type { AnyActivityDefinition, ArchiveAdapter, Checkpoint, DefinitionSchema, EngineOptions, NormalizedHistoryPolicy, NormalizedPayloadSizePolicy, NormalizedRetentionPolicy, SearchAttributeSchema, WorkflowConcurrencyOptions, WorkflowFunction, WorkflowTimelineEntry } from '../types.ts';
|
|
5
|
+
import type { AnyActivityDefinition, ArchiveAdapter, Checkpoint, DefinitionSchema, EngineOptions, NormalizedHistoryPolicy, NormalizedPayloadSizePolicy, NormalizedRetentionPolicy, QueryDefinition, SearchAttributeSchema, SignalDefinition, UpdateDefinition, WorkflowConcurrencyOptions, WorkflowFunction, WorkflowTimelineEntry } from '../types.ts';
|
|
6
6
|
export interface RegistrationEntry {
|
|
7
7
|
handler: WorkflowFunction;
|
|
8
8
|
version: string;
|
|
@@ -10,6 +10,9 @@ export interface RegistrationEntry {
|
|
|
10
10
|
tags?: ReadonlyArray<string>;
|
|
11
11
|
inputSchema?: DefinitionSchema;
|
|
12
12
|
outputSchema?: DefinitionSchema;
|
|
13
|
+
signals?: Readonly<Record<string, Readonly<SignalDefinition<unknown>>>>;
|
|
14
|
+
updates?: Readonly<Record<string, Readonly<UpdateDefinition<unknown>>>>;
|
|
15
|
+
queries?: Readonly<Record<string, Readonly<QueryDefinition<unknown>>>>;
|
|
13
16
|
searchAttributes?: SearchAttributeSchema;
|
|
14
17
|
retention?: NormalizedRetentionPolicy;
|
|
15
18
|
concurrency?: WorkflowConcurrencyOptions;
|
|
@@ -27,9 +27,11 @@ import type { EngineInternals } from './internals.ts';
|
|
|
27
27
|
* work before `recoverAll()` would otherwise durably write workflow state without
|
|
28
28
|
* single-writer ownership and without having recovered existing runs. Placed at
|
|
29
29
|
* each public awaited entry so the caller gets a clean {@link EngineLeaseNotHeldError}
|
|
30
|
-
* — without this, fork
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* — without this, fork, resume, and the schedule mutators (`schedule`,
|
|
31
|
+
* `pauseSchedule`, `resumeSchedule`, `cancelSchedule`, and `updateSchedule`) would
|
|
32
|
+
* reach `resolveFenceEpochOrHalt` with no held epoch and be misreported as a
|
|
33
|
+
* deposition (warn + teardown) rather than the true "lease not held yet"
|
|
34
|
+
* condition. A no-op under `ownership: 'none'`.
|
|
33
35
|
*/
|
|
34
36
|
export declare function assertLeaseHeldForEngineWork(internals: EngineInternals): void;
|
|
35
37
|
/**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type BatchOperation } from '../../storage/interface.ts';
|
|
2
|
+
import type { WorkflowFinalizerStatus, WorkflowState } from '../types.ts';
|
|
3
|
+
import type { EngineInternals } from './internals.ts';
|
|
4
|
+
export interface TeardownSucceededRecord {
|
|
5
|
+
attempts: number;
|
|
6
|
+
completedAt: number;
|
|
7
|
+
workflowExecutionToken?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildTeardownSuccessOperations(workflowId: string, attempts: number, completedAt: number, workflowExecutionToken: string | undefined): BatchOperation[];
|
|
10
|
+
export declare function getFinalizerStatus(internals: EngineInternals, workflowId: string, state: WorkflowState | null): Promise<WorkflowFinalizerStatus | null>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { KEYS } from "../../storage/interface.js";
|
|
2
|
+
import { decode, encode } from "../codec.js";
|
|
3
|
+
import { isRecord } from "../debug-output.js";
|
|
4
|
+
import { isTeardownClaim } from "./state-utilities.js";
|
|
5
|
+
export function buildTeardownSuccessOperations(workflowId, attempts, completedAt, workflowExecutionToken) {
|
|
6
|
+
const outcome = {
|
|
7
|
+
attempts,
|
|
8
|
+
completedAt,
|
|
9
|
+
...workflowExecutionToken === void 0 ? {} : { workflowExecutionToken }
|
|
10
|
+
};
|
|
11
|
+
return [
|
|
12
|
+
{ type: "delete", key: KEYS.teardownOwed(workflowId) },
|
|
13
|
+
{ type: "delete", key: KEYS.finalizerState(workflowId) },
|
|
14
|
+
{ type: "put", key: KEYS.teardownSucceeded(workflowId), value: encode(outcome) }
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
function decodeUnknown(bytes) {
|
|
18
|
+
try {
|
|
19
|
+
return decode(bytes);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isNonNegativeSafeInteger(value) {
|
|
25
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
26
|
+
}
|
|
27
|
+
function isNonNegativeFiniteNumber(value) {
|
|
28
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
29
|
+
}
|
|
30
|
+
function recordBelongsToRun(record, state) {
|
|
31
|
+
const recordToken = record.workflowExecutionToken;
|
|
32
|
+
if (recordToken !== void 0 && typeof recordToken !== "string")
|
|
33
|
+
return !1;
|
|
34
|
+
if (state === null)
|
|
35
|
+
return !0;
|
|
36
|
+
return recordToken === state.workflowExecutionToken;
|
|
37
|
+
}
|
|
38
|
+
export async function getFinalizerStatus(internals, workflowId, state) {
|
|
39
|
+
const claimBytes = await internals.storage.get(KEYS.teardownOwed(workflowId)), claimStatus = decodeClaimStatus(claimBytes);
|
|
40
|
+
if (claimStatus !== null)
|
|
41
|
+
return claimStatus;
|
|
42
|
+
const deadLetterBytes = await internals.storage.get(KEYS.teardownDeadLetter(workflowId)), failedStatus = decodeFailedStatus(deadLetterBytes, state);
|
|
43
|
+
if (failedStatus !== null)
|
|
44
|
+
return failedStatus;
|
|
45
|
+
const succeededBytes = await internals.storage.get(KEYS.teardownSucceeded(workflowId));
|
|
46
|
+
return decodeSucceededStatus(succeededBytes, state);
|
|
47
|
+
}
|
|
48
|
+
function decodeClaimStatus(bytes) {
|
|
49
|
+
if (bytes === null)
|
|
50
|
+
return null;
|
|
51
|
+
const claim = decodeUnknown(bytes);
|
|
52
|
+
if (!isTeardownClaim(claim))
|
|
53
|
+
return null;
|
|
54
|
+
if (claim.status === "running" && claim.claimedAt !== void 0)
|
|
55
|
+
return { status: "running", attempts: claim.attempts + 1, startedAt: claim.claimedAt };
|
|
56
|
+
return { status: "pending", attempts: claim.attempts };
|
|
57
|
+
}
|
|
58
|
+
function decodeFailedStatus(bytes, state) {
|
|
59
|
+
if (bytes === null)
|
|
60
|
+
return null;
|
|
61
|
+
const record = decodeUnknown(bytes);
|
|
62
|
+
if (!isRecord(record) || !recordBelongsToRun(record, state) || typeof record.lastError !== "string" || !isNonNegativeSafeInteger(record.attempts) || !isNonNegativeFiniteNumber(record.deadLetteredAt))
|
|
63
|
+
return null;
|
|
64
|
+
return {
|
|
65
|
+
status: "failed",
|
|
66
|
+
attempts: record.attempts,
|
|
67
|
+
failedAt: record.deadLetteredAt,
|
|
68
|
+
error: record.lastError
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function decodeSucceededStatus(bytes, state) {
|
|
72
|
+
if (bytes === null)
|
|
73
|
+
return null;
|
|
74
|
+
const record = decodeUnknown(bytes);
|
|
75
|
+
if (!isRecord(record) || !recordBelongsToRun(record, state) || !isNonNegativeSafeInteger(record.attempts) || !isNonNegativeFiniteNumber(record.completedAt))
|
|
76
|
+
return null;
|
|
77
|
+
return {
|
|
78
|
+
status: "succeeded",
|
|
79
|
+
attempts: record.attempts,
|
|
80
|
+
completedAt: record.completedAt
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -5,7 +5,7 @@ import type { TypedEventTarget, WeftEventMap } from '../events.ts';
|
|
|
5
5
|
import type { Interceptor } from '../interceptor.ts';
|
|
6
6
|
import { type ReviewRequest } from '../review/index.ts';
|
|
7
7
|
import { Scheduler } from '../scheduler.ts';
|
|
8
|
-
import { type AnyActivityDefinition, type AnyWorkflowDefinition, type AttributeFilterKey, type BulkCancelResult, type BulkDeleteResult, type BulkOperationCommitOptions, type BulkOperationDryRunOptions, type BulkOperationDryRunResult, type BulkRetryFailedResult, type BulkSignalAllCommitOptions, type BulkSignalAllDryRunOptions, type BulkSignalResult, type BulkTagResult, type CheckpointState, type CheckpointSummary, type CoordinatedUpdateResult, type DefaultActivityTypes, type DefaultWorkflowRegistry, type ForkOptions, type InferActivityEntries, type InferActivityEntry, type InferWorkflowEntries, type InferWorkflowEntry, type ListFilter, type ListOptions, type PaginatedResult, type PurgeResult, type QueryDefinition, type RegisteredWorkflowDefinition, type RetentionOverview, type ReviewListEntry, type ReviewListFilter, type ScheduleDefinition, type ScheduleFilter, type ScheduleOptions, type ScheduleSpec, type ScheduleSummary, type SearchAttributeValue, type SignalDefinition, type SignalDeliveryOptions, type StartOrSignalOptions, type StartOrSignalSignal, type StartWorkflowOptions, type SubmitReviewOptions, type TypedListFilter, type UpdateDefinition, type WorkflowEvent, type WorkflowInput, type WorkflowOutput, type WorkflowReplay, type WorkflowServices, type WorkflowServicesUnion, type WorkflowState, type WorkflowSummary, type WorkflowTimelineEntry } from '../types.ts';
|
|
8
|
+
import { type AnyActivityDefinition, type AnyWorkflowDefinition, type AttributeFilterKey, type BulkCancelResult, type BulkDeleteResult, type BulkOperationCommitOptions, type BulkOperationDryRunOptions, type BulkOperationDryRunResult, type BulkRetryFailedResult, type BulkSignalAllCommitOptions, type BulkSignalAllDryRunOptions, type BulkSignalResult, type BulkTagResult, type CheckpointState, type CheckpointSummary, type CoordinatedUpdateResult, type DefaultActivityTypes, type DefaultWorkflowRegistry, type ForkOptions, type InferActivityEntries, type InferActivityEntry, type InferWorkflowEntries, type InferWorkflowEntry, type ListFilter, type ListOptions, type PaginatedResult, type PendingAsyncActivityListOptions, type PendingAsyncActivityPage, type PurgeResult, type QueryDefinition, type RegisteredWorkflowDefinition, type RetentionOverview, type ReviewListEntry, type ReviewListFilter, type ScheduleDefinition, type ScheduleFilter, type ScheduleOptions, type ScheduleSpec, type ScheduleSummary, type ScheduleUpdateOptions, type SearchAttributeValue, type SignalDefinition, type SignalDeliveryOptions, type StartOrSignalOptions, type StartOrSignalSignal, type StartWorkflowOptions, type SubmitReviewOptions, type TypedListFilter, type UpdateDefinition, type WorkflowEvent, type WorkflowFinalizerStatus, type WorkflowInput, type WorkflowOutput, type WorkflowReplay, type WorkflowScheduleProvenance, type WorkflowServices, type WorkflowServicesUnion, type WorkflowState, type WorkflowSummary, type WorkflowTimelineEntry } from '../types.ts';
|
|
9
9
|
import type { TimerEntry } from '../types/checkpoint.ts';
|
|
10
10
|
import type { WorkflowAlreadyRegistered } from '../types/workflow-builder.ts';
|
|
11
11
|
import { type AggregateOptions, type AggregateResult } from './aggregate.ts';
|
|
@@ -15,6 +15,7 @@ import type { EngineConstructorOptions } from './engine-internal-types.ts';
|
|
|
15
15
|
import type { EngineStateNamespace } from './engine-state-namespace.ts';
|
|
16
16
|
import { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
|
|
17
17
|
import { ENGINE_LEASE_LOST_WARNING_NAME } from './lease-deposition.ts';
|
|
18
|
+
import type { EngineLeaseHealth } from './lease-health.ts';
|
|
18
19
|
import { type RecoverAllOptions, type StartOrSignalResult } from './lifecycle.ts';
|
|
19
20
|
import { assertCompatiblePersistedDataVersion } from './persisted-data-version.ts';
|
|
20
21
|
import { ScheduleHandle } from './schedule-handle.ts';
|
|
@@ -26,6 +27,7 @@ export type { PendingTimelineEntry, RegistrationEntry, ResolvedOptions, TrackedW
|
|
|
26
27
|
export { ActivityResolutionError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, EngineCreateNameMismatchError, EngineDisposedError, IdempotencyKeyPurgedError, PersistedDataIncompatibleError, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './errors.ts';
|
|
27
28
|
export { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
|
|
28
29
|
export { EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, } from './lease-errors.ts';
|
|
30
|
+
export type { EngineLeaseHealth, LeaseLostReason } from './lease-health.ts';
|
|
29
31
|
export type { RecoverAllOptions, RecoveredWorkflowInfo } from './lifecycle.ts';
|
|
30
32
|
export { ScheduleHandle } from './schedule-handle.ts';
|
|
31
33
|
export type { WorkflowFeedListener, WorkflowFeedRecord, WorkflowFeedSelector, } from './workflow-feed.ts';
|
|
@@ -304,7 +306,7 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
304
306
|
pauseSchedule(scheduleId: string): Promise<void>;
|
|
305
307
|
resumeSchedule(scheduleId: string): Promise<void>;
|
|
306
308
|
cancelSchedule(scheduleId: string): Promise<void>;
|
|
307
|
-
updateSchedule(scheduleId: string, newSpec: string | ScheduleSpec): Promise<void>;
|
|
309
|
+
updateSchedule(scheduleId: string, newSpec: string | ScheduleSpec, options?: ScheduleUpdateOptions): Promise<void>;
|
|
308
310
|
[HANDLE_RESULT_PROMISE](workflowId: string): Promise<unknown>;
|
|
309
311
|
[ENGINE_PARKED_WORKFLOW_COUNT_FOR_TESTING](): number;
|
|
310
312
|
[ENGINE_SIGNAL_WAITER_COUNT_FOR_TESTING](): number;
|
|
@@ -394,6 +396,13 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
394
396
|
* the token (unknown, or already completed/failed — tokens are single-use).
|
|
395
397
|
*/
|
|
396
398
|
completeAsyncActivity(token: string, result: unknown): Promise<void>;
|
|
399
|
+
/**
|
|
400
|
+
* List a bounded page of durable async activities awaiting out-of-band
|
|
401
|
+
* completion for one workflow. This reads storage directly, so callers can
|
|
402
|
+
* recover tokens after a process restart before `recoverAll()` repopulates
|
|
403
|
+
* the in-memory completion map.
|
|
404
|
+
*/
|
|
405
|
+
listPendingAsyncActivities(workflowId: string, options?: PendingAsyncActivityListOptions): Promise<PendingAsyncActivityPage>;
|
|
397
406
|
/**
|
|
398
407
|
* Fail a deferred activity out-of-band with `error`. The error is thrown into
|
|
399
408
|
* the workflow generator at the parked step — identical to an inline activity
|
|
@@ -425,6 +434,21 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
425
434
|
suspend(workflowId: string): Promise<void>;
|
|
426
435
|
timeout(workflowId: string): Promise<void>;
|
|
427
436
|
get(workflowId: string): Promise<WorkflowState | null>;
|
|
437
|
+
/** Return the schedule occurrence that launched a workflow, when applicable. */
|
|
438
|
+
getScheduleProvenance(workflowId: string): Promise<WorkflowScheduleProvenance | null>;
|
|
439
|
+
/** Return durable post-terminal finalizer progress or outcome, when applicable. */
|
|
440
|
+
getFinalizerStatus(workflowId: string): Promise<WorkflowFinalizerStatus | null>;
|
|
441
|
+
/**
|
|
442
|
+
* Return this process's last-known ownership-lease health.
|
|
443
|
+
*
|
|
444
|
+
* This is a synchronous diagnostic snapshot: it never performs a storage read
|
|
445
|
+
* and therefore remains available to operator transports after a confirmed
|
|
446
|
+
* deposition has detached the lease manager. Holder identifiers and timestamps
|
|
447
|
+
* are present only while the manager still has its own last-written holder
|
|
448
|
+
* record; a detached deposed engine reports the confirmed loss without
|
|
449
|
+
* inventing successor details.
|
|
450
|
+
*/
|
|
451
|
+
getLeaseHealth(): EngineLeaseHealth;
|
|
428
452
|
getCurrentCheckpointStep(workflowId: string): Promise<number | null>;
|
|
429
453
|
getAttributes(workflowId: string): Promise<Record<string, SearchAttributeValue> | null>;
|
|
430
454
|
setAttributes(workflowId: string, attributes: Record<string, SearchAttributeValue>): Promise<void>;
|
|
@@ -22,7 +22,10 @@ import {
|
|
|
22
22
|
completeAsyncActivity as completeAsyncActivityFromInternals,
|
|
23
23
|
failAsyncActivity as failAsyncActivityFromInternals
|
|
24
24
|
} from "./async-activity-completion.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
listPendingAsyncActivities as listPendingAsyncActivitiesFromInternals,
|
|
27
|
+
recoverPendingAsyncActivities
|
|
28
|
+
} from "./async-activity-records.js";
|
|
26
29
|
import { broadcast as broadcastFromInternals } from "./broadcast.js";
|
|
27
30
|
import {
|
|
28
31
|
cancelAll as cancelAllWorkflows,
|
|
@@ -81,6 +84,7 @@ import {
|
|
|
81
84
|
} from "./errors.js";
|
|
82
85
|
import { assertLeaseHeldForEngineWork, commitFencedEngineWrite } from "./fenced-write.js";
|
|
83
86
|
import { recordFinalizerState } from "./finalizer-state.js";
|
|
87
|
+
import { getFinalizerStatus as getFinalizerStatusFromInternals } from "./finalizer-status.js";
|
|
84
88
|
import {
|
|
85
89
|
createWorkflowHandleWithResultPromise as createWorkflowHandleWithResultPromiseFromInternals,
|
|
86
90
|
getWorkflowResultPromise as getWorkflowResultPromiseFromInternals
|
|
@@ -134,6 +138,7 @@ import {
|
|
|
134
138
|
submitReview as submitReviewFromInternals
|
|
135
139
|
} from "./reviews.js";
|
|
136
140
|
import { ScheduleHandle } from "./schedule-handle.js";
|
|
141
|
+
import { decodeScheduleRunMetadata } from "./schedule-run-metadata.js";
|
|
137
142
|
import {
|
|
138
143
|
cancelSchedule as cancelScheduleFromInternals,
|
|
139
144
|
listSchedules as listSchedulesFromInternals,
|
|
@@ -306,9 +311,12 @@ export class Engine extends EventTarget {
|
|
|
306
311
|
getInternals(this).pendingNestingDepth = void 0;
|
|
307
312
|
getInternals(this).pendingParentHeaders = void 0;
|
|
308
313
|
getInternals(this).pendingExecutionStateOwnerId = void 0;
|
|
314
|
+
getInternals(this).pendingParentWorkflowId = void 0;
|
|
315
|
+
getInternals(this).pendingParentWorkflowExecutionToken = void 0;
|
|
309
316
|
getInternals(this).workflowNestingDepths = new Map;
|
|
310
317
|
getInternals(this).workflowHeaders = new Map;
|
|
311
318
|
getInternals(this).workflowStateWriteChains = new Map;
|
|
319
|
+
getInternals(this).scheduleStateOperationChains = new Map;
|
|
312
320
|
getInternals(this).finalizationRegistry = new FinalizationRegistry(createHandleCacheFinalizer(getInternals(this).handleCache));
|
|
313
321
|
getInternals(this).options = resolvedOptions;
|
|
314
322
|
getInternals(this).scheduler = new Scheduler({
|
|
@@ -641,11 +649,13 @@ export class Engine extends EventTarget {
|
|
|
641
649
|
return untagAllWorkflows(getInternals(this), filter, tags, options);
|
|
642
650
|
}
|
|
643
651
|
async schedule(typeOrDefinition, input, spec, options) {
|
|
652
|
+
const internals = getInternals(this);
|
|
653
|
+
assertLeaseHeldForEngineWork(internals);
|
|
644
654
|
if (typeof typeOrDefinition === "object")
|
|
645
|
-
return scheduleDefinitionFromInternals(
|
|
655
|
+
return scheduleDefinitionFromInternals(internals, typeOrDefinition);
|
|
646
656
|
if (spec === void 0)
|
|
647
657
|
throw Error("A cron string or schedule spec must be provided when scheduling by workflow type.");
|
|
648
|
-
return scheduleFromInternals(
|
|
658
|
+
return scheduleFromInternals(internals, typeOrDefinition, input, spec, options);
|
|
649
659
|
}
|
|
650
660
|
async getSchedule(scheduleId) {
|
|
651
661
|
const normalizedScheduleId = coerceScheduleId(scheduleId, "scheduleId"), state = await loadScheduleState(getInternals(this), normalizedScheduleId);
|
|
@@ -655,16 +665,24 @@ export class Engine extends EventTarget {
|
|
|
655
665
|
return listSchedulesFromInternals(getInternals(this), filter);
|
|
656
666
|
}
|
|
657
667
|
async pauseSchedule(scheduleId) {
|
|
658
|
-
|
|
668
|
+
const internals = getInternals(this);
|
|
669
|
+
assertLeaseHeldForEngineWork(internals);
|
|
670
|
+
return pauseScheduleFromInternals(internals, scheduleId);
|
|
659
671
|
}
|
|
660
672
|
async resumeSchedule(scheduleId) {
|
|
661
|
-
|
|
673
|
+
const internals = getInternals(this);
|
|
674
|
+
assertLeaseHeldForEngineWork(internals);
|
|
675
|
+
return resumeScheduleFromInternals(internals, scheduleId);
|
|
662
676
|
}
|
|
663
677
|
async cancelSchedule(scheduleId) {
|
|
664
|
-
|
|
678
|
+
const internals = getInternals(this);
|
|
679
|
+
assertLeaseHeldForEngineWork(internals);
|
|
680
|
+
return cancelScheduleFromInternals(internals, scheduleId);
|
|
665
681
|
}
|
|
666
|
-
async updateSchedule(scheduleId, newSpec) {
|
|
667
|
-
|
|
682
|
+
async updateSchedule(scheduleId, newSpec, options) {
|
|
683
|
+
const internals = getInternals(this);
|
|
684
|
+
assertLeaseHeldForEngineWork(internals);
|
|
685
|
+
return updateScheduleFromInternals(internals, scheduleId, newSpec, options);
|
|
668
686
|
}
|
|
669
687
|
[HANDLE_RESULT_PROMISE](workflowId) {
|
|
670
688
|
return getWorkflowResultPromiseFromInternals(getInternals(this), workflowId);
|
|
@@ -721,6 +739,9 @@ export class Engine extends EventTarget {
|
|
|
721
739
|
finalizeTimeline: (workflowId, status, output) => finalizePendingTimelineEntry(getInternals(this), workflowId, status, output)
|
|
722
740
|
});
|
|
723
741
|
}
|
|
742
|
+
async listPendingAsyncActivities(workflowId, options) {
|
|
743
|
+
return listPendingAsyncActivitiesFromInternals(getInternals(this), workflowId, options);
|
|
744
|
+
}
|
|
724
745
|
async failAsyncActivity(token, error) {
|
|
725
746
|
await failAsyncActivityFromInternals(getInternals(this), token, error, {
|
|
726
747
|
feedOperationResult: (workflowId, outcome, originalReason) => feedOperationResult(getInternals(this), workflowId, outcome, originalReason),
|
|
@@ -742,6 +763,48 @@ export class Engine extends EventTarget {
|
|
|
742
763
|
return { ...state, status: "pending" };
|
|
743
764
|
return state;
|
|
744
765
|
}
|
|
766
|
+
async getScheduleProvenance(workflowId) {
|
|
767
|
+
const bytes = await getInternals(this).storage.get(KEYS.scheduleRunLink(workflowId));
|
|
768
|
+
if (bytes === null)
|
|
769
|
+
return null;
|
|
770
|
+
const metadata = decodeScheduleRunMetadata(bytes);
|
|
771
|
+
if (metadata === null)
|
|
772
|
+
return null;
|
|
773
|
+
return {
|
|
774
|
+
scheduleId: metadata.id,
|
|
775
|
+
...metadata.occurrence === void 0 ? {} : { occurrence: metadata.occurrence }
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
async getFinalizerStatus(workflowId) {
|
|
779
|
+
const internals = getInternals(this), state = await loadWorkflowState(internals, workflowId);
|
|
780
|
+
return getFinalizerStatusFromInternals(internals, workflowId, state);
|
|
781
|
+
}
|
|
782
|
+
getLeaseHealth() {
|
|
783
|
+
const internals = getInternals(this);
|
|
784
|
+
if (internals.options.ownershipMode === "none")
|
|
785
|
+
return { mode: "none", status: "disabled", holdsLease: !1 };
|
|
786
|
+
if (internals.deposed) {
|
|
787
|
+
const lastKnownLease = internals.leaseManager?.health();
|
|
788
|
+
if (lastKnownLease !== void 0 && lastKnownLease.status !== "no-lease")
|
|
789
|
+
return {
|
|
790
|
+
mode: "lease",
|
|
791
|
+
...lastKnownLease,
|
|
792
|
+
status: "contested",
|
|
793
|
+
holdsLease: !1,
|
|
794
|
+
lossReason: "deposed"
|
|
795
|
+
};
|
|
796
|
+
return {
|
|
797
|
+
mode: "lease",
|
|
798
|
+
status: "contested",
|
|
799
|
+
holdsLease: !1,
|
|
800
|
+
lossReason: "deposed"
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
return {
|
|
804
|
+
mode: "lease",
|
|
805
|
+
...internals.leaseManager?.health() ?? { status: "no-lease", holdsLease: !1 }
|
|
806
|
+
};
|
|
807
|
+
}
|
|
745
808
|
async getCurrentCheckpointStep(workflowId) {
|
|
746
809
|
const inMemory = getInternals(this).checkpoints.get(workflowId);
|
|
747
810
|
if (inMemory !== void 0)
|