@lostgradient/weft 0.8.0 → 0.10.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 +9 -5
- package/dist/alerting/alert-manager.d.ts +3 -1
- package/dist/alerting/alert-manager.js +5 -2
- package/dist/cli/generated/operation-client.generated.d.ts +1 -0
- package/dist/cli-main.js +78 -78
- package/dist/core/context/durable-operations.js +1 -1
- package/dist/core/context/index.d.ts +3 -1
- package/dist/core/context/index.js +10 -0
- package/dist/core/context/operation-request.d.ts +4 -0
- package/dist/core/context/parallel-cache-entry.d.ts +1 -1
- package/dist/core/context/parallel-cache-entry.js +12 -8
- package/dist/core/context/parallel-operations.d.ts +1 -1
- package/dist/core/context/parallel-operations.js +50 -8
- package/dist/core/context/run-operation.js +3 -2
- package/dist/core/context/speculative-child.js +1 -0
- package/dist/core/context/types.d.ts +1 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +1 -1
- package/dist/core/engine/activity-heartbeat-tracking.js +5 -1
- package/dist/core/engine/anonymous-signal-sequence.js +0 -2
- package/dist/core/engine/async-activity-completion.d.ts +24 -54
- package/dist/core/engine/async-activity-completion.js +25 -90
- package/dist/core/engine/async-activity-records.d.ts +106 -0
- package/dist/core/engine/async-activity-records.js +124 -0
- package/dist/core/engine/bulk-operations-purge.js +2 -1
- package/dist/core/engine/bulk-operations.js +10 -29
- package/dist/core/engine/callback-creators-bundles.js +1 -1
- package/dist/core/engine/callback-creators-core.js +1 -0
- package/dist/core/engine/construction.d.ts +1 -3
- package/dist/core/engine/construction.js +2 -5
- package/dist/core/engine/deferred-consume-envelope.d.ts +10 -1
- package/dist/core/engine/deferred-consume-envelope.js +9 -1
- package/dist/core/engine/disposal.js +1 -0
- package/dist/core/engine/engine-internal-types.d.ts +2 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +8 -0
- package/dist/core/engine/engine-runtime-helpers.js +9 -0
- package/dist/core/engine/errors.js +1 -1
- package/dist/core/engine/index.d.ts +12 -2
- package/dist/core/engine/index.js +35 -16
- package/dist/core/engine/inline-launch-queue.js +1 -1
- package/dist/core/engine/internals.d.ts +25 -3
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -0
- package/dist/core/engine/lifecycle/recovered-services.d.ts +4 -2
- package/dist/core/engine/lifecycle/recovered-services.js +37 -7
- package/dist/core/engine/lifecycle/resume.d.ts +2 -2
- package/dist/core/engine/lifecycle/resume.js +45 -7
- package/dist/core/engine/lifecycle/shared.d.ts +34 -0
- package/dist/core/engine/lifecycle/start-exec.d.ts +2 -2
- package/dist/core/engine/lifecycle/start-exec.js +6 -4
- package/dist/core/engine/lifecycle/start.js +1 -0
- package/dist/core/engine/lifecycle/transition.d.ts +1 -1
- package/dist/core/engine/lifecycle/transition.js +9 -3
- package/dist/core/engine/lifecycle.d.ts +1 -1
- package/dist/core/engine/memo-durable-activity.js +8 -10
- package/dist/core/engine/operations-activity.d.ts +1 -1
- package/dist/core/engine/operations-activity.js +8 -6
- package/dist/core/engine/operations-coordination.d.ts +15 -1
- package/dist/core/engine/operations-coordination.js +43 -10
- package/dist/core/engine/operations-time.d.ts +2 -2
- package/dist/core/engine/operations-time.js +40 -6
- package/dist/core/engine/ownership-options.d.ts +1 -0
- package/dist/core/engine/ownership-options.js +14 -0
- package/dist/core/engine/retention.js +4 -0
- package/dist/core/engine/schedule-run-metadata.d.ts +3 -0
- package/dist/core/engine/schedule-run-metadata.js +29 -0
- package/dist/core/engine/schedule-run.js +19 -4
- package/dist/core/engine/schedules.js +7 -3
- package/dist/core/engine/sub-operation.js +6 -13
- package/dist/core/engine/termination/cleanup.js +18 -14
- package/dist/core/engine/termination/finalizer-activity.d.ts +1 -1
- package/dist/core/engine/termination/finalizer-activity.js +5 -1
- package/dist/core/engine/termination/finalizer.js +1 -1
- package/dist/core/engine/validation/schedule-options.d.ts +9 -0
- package/dist/core/engine/validation/schedule-options.js +59 -0
- package/dist/core/engine/validation/schedule.d.ts +3 -8
- package/dist/core/engine/validation/schedule.js +40 -56
- package/dist/core/engine/validation.js +1 -0
- package/dist/core/execution-strategy.d.ts +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +1 -0
- package/dist/core/inline-execution-strategy.context-options.js +3 -0
- package/dist/core/types/activity.d.ts +11 -0
- package/dist/core/types/checkpoint.d.ts +1 -0
- package/dist/core/types/options.d.ts +12 -0
- package/dist/core/types/schedules.d.ts +10 -0
- package/dist/core/types/services-resolution.d.ts +8 -3
- package/dist/core/types/state.d.ts +6 -0
- package/dist/core/types/workflow-builder.d.ts +2 -2
- package/dist/core/types/workflow-context.d.ts +40 -0
- package/dist/core/worker-execution-strategy.d.ts +1 -0
- package/dist/core/worker-inbound-message.d.ts +1 -0
- package/dist/core/worker-inbound-message.js +3 -0
- package/dist/index.d.ts +2 -2
- package/dist/json-schema.js +2 -2
- package/dist/mcp/cli.js +32 -32
- package/dist/observability/index.js +2 -2
- package/dist/runtime/portable.d.ts +1 -1
- package/dist/server/authorization.d.ts +3 -3
- package/dist/server/fault-to-json-rpc.d.ts +2 -1
- package/dist/server/handler.js +28 -28
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +30 -30
- package/dist/server/json-rpc-dispatch.d.ts +2 -2
- package/dist/server/json-rpc-parse.d.ts +1 -1
- package/dist/server/json-rpc-protocol.d.ts +2 -2
- package/dist/server/json-rpc-websocket.d.ts +1 -1
- package/dist/server/operation-fault.d.ts +3 -1
- package/dist/server/operations/async-activity.js +2 -2
- package/dist/server/operations/create-schedule.d.ts +2 -0
- package/dist/server/operations/create-schedule.js +13 -2
- package/dist/server/principal.d.ts +2 -2
- package/dist/server/rest-binding.d.ts +1 -1
- package/dist/server/runtime/task-dispatch.js +6 -0
- package/dist/server/runtime/task-polling.js +9 -1
- package/dist/server/runtime/task-reconciliation.js +2 -1
- package/dist/server/stdio-session.d.ts +4 -4
- package/dist/server/task-queue-types.d.ts +2 -0
- package/dist/server/task-state.d.ts +4 -0
- package/dist/service-worker/index.d.ts +15 -14
- package/dist/service-worker/index.js +28 -28
- package/dist/service-worker/scheduler.d.ts +41 -1
- package/dist/storage/auto.d.ts +36 -18
- package/dist/storage/auto.js +1 -1
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/indexeddb.d.ts +6 -1
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +1 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +1 -1
- 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 +1 -1
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.d.ts +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +33 -33
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/execute-with-interceptors.d.ts +9 -3
- package/dist/worker/execute-with-interceptors.js +14 -2
- package/dist/worker/long-poll.d.ts +2 -1
- package/dist/worker/long-poll.js +1 -1
- package/dist/worker/protocol-messages.d.ts +2 -0
- package/dist/worker/protocol-schemas.d.ts +8 -0
- package/dist/worker/protocol-schemas.js +1 -0
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/remote-activity-context.d.ts +2 -0
- package/dist/workers/activity-runner.d.ts +2 -0
- package/dist/workers/activity-runner.js +9 -1
- package/dist/workers/workflow-runner.d.ts +2 -1
- package/dist/workers/workflow-runner.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable record layer for out-of-band ("async") activity completion.
|
|
3
|
+
*
|
|
4
|
+
* Two record shapes share the `async-act:v1:` keyspace, discriminated by their
|
|
5
|
+
* decode guards (never by key shape):
|
|
6
|
+
*
|
|
7
|
+
* - **Pending token records** ({@link KEYS.asyncActivity}): an activity that
|
|
8
|
+
* deferred via `ctx.completeAsync()` and is awaiting an external completion.
|
|
9
|
+
* - **Resolution records** ({@link KEYS.asyncActivityResolution}): an
|
|
10
|
+
* acknowledged completion or failure whose resumed-workflow checkpoint has
|
|
11
|
+
* not committed yet. Written atomically with the token-record delete so the
|
|
12
|
+
* acknowledgement is durable before the caller learns it succeeded.
|
|
13
|
+
*
|
|
14
|
+
* The completion orchestration (park, consume, deliver, resume) lives in
|
|
15
|
+
* `async-activity-completion.ts`; this module owns the persisted shapes, the
|
|
16
|
+
* key derivations, and the in-memory resolution queue that recovery drains.
|
|
17
|
+
*/
|
|
18
|
+
import { type BatchOperation } from '../../storage/interface.ts';
|
|
19
|
+
import type { OperationOutcome } from '../types.ts';
|
|
20
|
+
import type { EngineInternals } from './internals.ts';
|
|
21
|
+
/**
|
|
22
|
+
* Storage-key prefix for durable async-activity records. Matches the base of
|
|
23
|
+
* {@link KEYS.asyncActivity}; the full key appends `<workflowId>:<token>` (and
|
|
24
|
+
* `:resolution` for resolution records). The trailing colon (absent from the
|
|
25
|
+
* token prefix) scopes the global recovery scan to record keys only.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ASYNC_ACTIVITY_KEY_PREFIX = "async-act:v1:";
|
|
28
|
+
/**
|
|
29
|
+
* Per-workflow prefix for all async-activity storage keys — pending token
|
|
30
|
+
* records AND resolution records. Used by cleanup and purge paths that need to
|
|
31
|
+
* sweep every async-activity record for a workflow without enumerating
|
|
32
|
+
* individual tokens.
|
|
33
|
+
*/
|
|
34
|
+
export declare function asyncActivityWorkflowPrefix(workflowId: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* In-memory record of an activity that deferred to out-of-band completion and
|
|
37
|
+
* is awaiting `completeAsyncActivity` / `failAsyncActivity`.
|
|
38
|
+
*/
|
|
39
|
+
export type PendingAsyncActivity = {
|
|
40
|
+
readonly token: string;
|
|
41
|
+
readonly workflowId: string;
|
|
42
|
+
readonly activityName: string;
|
|
43
|
+
readonly operationId: string;
|
|
44
|
+
readonly step: number;
|
|
45
|
+
readonly attempt: number;
|
|
46
|
+
readonly createdAt: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* In-memory form of an acknowledged outcome awaiting delivery into the workflow
|
|
50
|
+
* generator. `originalReason` (the raw thrown value on the failure path) exists
|
|
51
|
+
* only within the acknowledging process — it is not persisted, so a resolution
|
|
52
|
+
* reloaded by recovery reconstructs the error from the recorded outcome.
|
|
53
|
+
*/
|
|
54
|
+
export type PendingAsyncActivityResolution = {
|
|
55
|
+
readonly token: string;
|
|
56
|
+
readonly outcome: OperationOutcome;
|
|
57
|
+
readonly originalReason?: {
|
|
58
|
+
value: unknown;
|
|
59
|
+
};
|
|
60
|
+
readonly timelineStatus: 'completed' | 'failed';
|
|
61
|
+
readonly timelineOutput: unknown;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Derive the durable, deterministic task token for an async activity.
|
|
65
|
+
*
|
|
66
|
+
* The token is anchored to the workflow id, the activity state key, and the
|
|
67
|
+
* dispatch attempt — all of which are stable across replay — so a workflow that
|
|
68
|
+
* crashes while parked on an async activity mints the identical token after
|
|
69
|
+
* recovery. Plain `ctx.run()` uses the workflow step as the state key.
|
|
70
|
+
* `operationId` is deliberately excluded because it is regenerated on every
|
|
71
|
+
* yield and would change on replay.
|
|
72
|
+
*/
|
|
73
|
+
export declare function deriveAsyncActivityToken(workflowId: string, step: number | string, attempt: number): string;
|
|
74
|
+
/**
|
|
75
|
+
* Build the acknowledgement batch for a consumed token: delete the pending
|
|
76
|
+
* token record and persist the resolution record carrying `outcome`, in one
|
|
77
|
+
* batch, so the acknowledgement is durable before the caller learns it
|
|
78
|
+
* succeeded.
|
|
79
|
+
*/
|
|
80
|
+
export declare function buildAsyncActivityAcknowledgementOperations(pending: PendingAsyncActivity, outcome: OperationOutcome): BatchOperation[];
|
|
81
|
+
/**
|
|
82
|
+
* Register a deferred activity: record it in memory and durably, then announce
|
|
83
|
+
* the token via {@link ActivityAsyncPendingEvent}. Idempotent on `token`: if the
|
|
84
|
+
* token is already registered (e.g. because `recoverPendingAsyncActivities` loaded
|
|
85
|
+
* it before the workflow replayed and re-deferred), the durable record is
|
|
86
|
+
* refreshed but the event is NOT re-emitted, preventing duplicate side-effects
|
|
87
|
+
* (e.g. re-sending a webhook notification) on replay.
|
|
88
|
+
*/
|
|
89
|
+
export declare function registerPendingAsyncActivity(internals: EngineInternals, pending: PendingAsyncActivity): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Reload async-activity records from storage into memory. Called by
|
|
92
|
+
* `recoverAll()` so a token minted before a crash is resolvable again — even
|
|
93
|
+
* before the recovered workflow has replayed far enough to re-register it —
|
|
94
|
+
* and so an acknowledged-but-not-yet-checkpointed resolution is redelivered
|
|
95
|
+
* when replay re-parks on the same deterministic token.
|
|
96
|
+
*/
|
|
97
|
+
export declare function recoverPendingAsyncActivities(internals: EngineInternals): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* True when a resolution cannot be delivered yet because inline replay has not
|
|
100
|
+
* adopted the workflow generator (the post-recovery window).
|
|
101
|
+
*/
|
|
102
|
+
export declare function shouldBufferPendingAsyncActivityResolution(internals: EngineInternals, workflowId: string): boolean;
|
|
103
|
+
/** Queue a resolution for delivery when replay reaches its token again. */
|
|
104
|
+
export declare function queuePendingAsyncActivityResolution(internals: EngineInternals, workflowId: string, resolution: PendingAsyncActivityResolution): void;
|
|
105
|
+
/** Take the queued resolution for `token`, if one is waiting. */
|
|
106
|
+
export declare function takePendingAsyncActivityResolution(internals: EngineInternals, workflowId: string, token: string): PendingAsyncActivityResolution | undefined;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { KEYS, encodeStorageKeyComponent } from "../../storage/interface.js";
|
|
2
|
+
import { decode, encode } from "../codec.js";
|
|
3
|
+
import { ActivityAsyncPendingEvent } from "../events.js";
|
|
4
|
+
import { commitFencedEngineWrite } from "./fenced-write.js";
|
|
5
|
+
const ASYNC_ACTIVITY_TOKEN_PREFIX = "async-act:v1";
|
|
6
|
+
export const ASYNC_ACTIVITY_KEY_PREFIX = "async-act:v1:";
|
|
7
|
+
export function asyncActivityWorkflowPrefix(workflowId) {
|
|
8
|
+
return `${ASYNC_ACTIVITY_KEY_PREFIX}${encodeStorageKeyComponent(workflowId)}:`;
|
|
9
|
+
}
|
|
10
|
+
function isPersistedAsyncActivity(value) {
|
|
11
|
+
if (typeof value !== "object" || value === null)
|
|
12
|
+
return !1;
|
|
13
|
+
const record = value;
|
|
14
|
+
return record.version === 1 && typeof record.token === "string" && typeof record.workflowId === "string" && typeof record.activityName === "string" && typeof record.operationId === "string" && typeof record.step === "number" && typeof record.attempt === "number" && typeof record.createdAt === "number";
|
|
15
|
+
}
|
|
16
|
+
function isPersistedOperationOutcome(value) {
|
|
17
|
+
if (typeof value !== "object" || value === null)
|
|
18
|
+
return !1;
|
|
19
|
+
const record = value;
|
|
20
|
+
if (record.status === "completed")
|
|
21
|
+
return "value" in record;
|
|
22
|
+
if (record.status === "failed")
|
|
23
|
+
return typeof record.error === "string";
|
|
24
|
+
return !1;
|
|
25
|
+
}
|
|
26
|
+
function isPersistedAsyncActivityResolution(value) {
|
|
27
|
+
if (typeof value !== "object" || value === null)
|
|
28
|
+
return !1;
|
|
29
|
+
const record = value;
|
|
30
|
+
return record.version === 1 && record.kind === "resolution" && typeof record.token === "string" && typeof record.workflowId === "string" && isPersistedOperationOutcome(record.outcome);
|
|
31
|
+
}
|
|
32
|
+
export function deriveAsyncActivityToken(workflowId, step, attempt) {
|
|
33
|
+
return `${ASYNC_ACTIVITY_TOKEN_PREFIX}:${workflowId}:${step}:${attempt}`;
|
|
34
|
+
}
|
|
35
|
+
function buildPersistPendingAsyncActivityOperation(pending) {
|
|
36
|
+
const record = {
|
|
37
|
+
version: 1,
|
|
38
|
+
token: pending.token,
|
|
39
|
+
workflowId: pending.workflowId,
|
|
40
|
+
activityName: pending.activityName,
|
|
41
|
+
operationId: pending.operationId,
|
|
42
|
+
step: pending.step,
|
|
43
|
+
attempt: pending.attempt,
|
|
44
|
+
createdAt: pending.createdAt
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
type: "put",
|
|
48
|
+
key: KEYS.asyncActivity(pending.workflowId, pending.token),
|
|
49
|
+
value: encode(record)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function buildAsyncActivityAcknowledgementOperations(pending, outcome) {
|
|
53
|
+
const record = {
|
|
54
|
+
version: 1,
|
|
55
|
+
kind: "resolution",
|
|
56
|
+
token: pending.token,
|
|
57
|
+
workflowId: pending.workflowId,
|
|
58
|
+
outcome
|
|
59
|
+
};
|
|
60
|
+
return [
|
|
61
|
+
{ type: "delete", key: KEYS.asyncActivity(pending.workflowId, pending.token) },
|
|
62
|
+
{
|
|
63
|
+
type: "put",
|
|
64
|
+
key: KEYS.asyncActivityResolution(pending.workflowId, pending.token),
|
|
65
|
+
value: encode(record)
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
export async function registerPendingAsyncActivity(internals, pending) {
|
|
70
|
+
const alreadyRegistered = internals.pendingAsyncActivities.has(pending.token);
|
|
71
|
+
internals.pendingAsyncActivities.set(pending.token, pending);
|
|
72
|
+
await commitFencedEngineWrite(internals, [buildPersistPendingAsyncActivityOperation(pending)], [], () => Error(`Async activity registration for token "${pending.token}" lost its precondition.`));
|
|
73
|
+
if (!alreadyRegistered)
|
|
74
|
+
internals.engine.dispatchEvent(new ActivityAsyncPendingEvent(pending.token, pending.operationId, pending.workflowId, pending.activityName, pending.attempt));
|
|
75
|
+
}
|
|
76
|
+
export async function recoverPendingAsyncActivities(internals) {
|
|
77
|
+
for await (const [, bytes] of internals.storage.scan(ASYNC_ACTIVITY_KEY_PREFIX)) {
|
|
78
|
+
const decoded = decode(bytes);
|
|
79
|
+
if (isPersistedAsyncActivity(decoded)) {
|
|
80
|
+
internals.pendingAsyncActivities.set(decoded.token, {
|
|
81
|
+
token: decoded.token,
|
|
82
|
+
workflowId: decoded.workflowId,
|
|
83
|
+
activityName: decoded.activityName,
|
|
84
|
+
operationId: decoded.operationId,
|
|
85
|
+
step: decoded.step,
|
|
86
|
+
attempt: decoded.attempt,
|
|
87
|
+
createdAt: decoded.createdAt
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (isPersistedAsyncActivityResolution(decoded))
|
|
92
|
+
queuePendingAsyncActivityResolution(internals, decoded.workflowId, {
|
|
93
|
+
token: decoded.token,
|
|
94
|
+
outcome: decoded.outcome,
|
|
95
|
+
timelineStatus: decoded.outcome.status,
|
|
96
|
+
timelineOutput: decoded.outcome.status === "completed" ? decoded.outcome.value : decoded.outcome.error
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function shouldBufferPendingAsyncActivityResolution(internals, workflowId) {
|
|
101
|
+
return internals.inlineStrategy !== null && !internals.inlineStrategy.hasGenerator(workflowId);
|
|
102
|
+
}
|
|
103
|
+
export function queuePendingAsyncActivityResolution(internals, workflowId, resolution) {
|
|
104
|
+
internals.pendingAsyncActivityResolutions ??= new Map;
|
|
105
|
+
const queued = internals.pendingAsyncActivityResolutions.get(workflowId) ?? [];
|
|
106
|
+
queued.push(resolution);
|
|
107
|
+
internals.pendingAsyncActivityResolutions.set(workflowId, queued);
|
|
108
|
+
}
|
|
109
|
+
export function takePendingAsyncActivityResolution(internals, workflowId, token) {
|
|
110
|
+
internals.pendingAsyncActivityResolutions ??= new Map;
|
|
111
|
+
const queued = internals.pendingAsyncActivityResolutions.get(workflowId);
|
|
112
|
+
if (queued === void 0)
|
|
113
|
+
return;
|
|
114
|
+
const index = queued.findIndex((resolution) => resolution.token === token);
|
|
115
|
+
if (index === -1)
|
|
116
|
+
return;
|
|
117
|
+
const resolution = queued[index];
|
|
118
|
+
if (resolution === void 0)
|
|
119
|
+
return;
|
|
120
|
+
queued.splice(index, 1);
|
|
121
|
+
if (queued.length === 0)
|
|
122
|
+
internals.pendingAsyncActivityResolutions.delete(workflowId);
|
|
123
|
+
return resolution;
|
|
124
|
+
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { decode } from "../codec.js";
|
|
9
9
|
import { buildIndexOperations } from "../search-attributes.js";
|
|
10
10
|
import { buildWorkflowTagIndexOperations, normalizeWorkflowTags } from "../workflow-tags.js";
|
|
11
|
-
import { asyncActivityWorkflowPrefix } from "./async-activity-
|
|
11
|
+
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";
|
|
@@ -192,6 +192,7 @@ function buildBaseWorkflowDeleteKeys(state) {
|
|
|
192
192
|
KEYS.workflowHeaders(state.id),
|
|
193
193
|
KEYS.terminalCleanupNeeded(state.id),
|
|
194
194
|
KEYS.workflowConcurrencyHolder(state.id),
|
|
195
|
+
KEYS.scheduleRun(state.id),
|
|
195
196
|
KEYS.workflowHasServices(state.id),
|
|
196
197
|
KEYS.finalizerState(state.id),
|
|
197
198
|
KEYS.teardownOwed(state.id),
|
|
@@ -62,20 +62,13 @@ async function runBulkCancellation(internals, filter, options = {}) {
|
|
|
62
62
|
const workflowIdsToCancel = preparation.workflowIds, bulkConcurrency = resolveBulkOperationConcurrency(options);
|
|
63
63
|
let cancelled = 0;
|
|
64
64
|
const errors = [], cancellationResults = await runBulkWorkflowPool(workflowIdsToCancel, bulkConcurrency, async (workflowId) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
} catch (error) {
|
|
74
|
-
return {
|
|
75
|
-
status: "failed",
|
|
76
|
-
error: toBulkOperationError(internals, workflowId, error)
|
|
77
|
-
};
|
|
78
|
-
}
|
|
65
|
+
await internals.engine.cancel(workflowId);
|
|
66
|
+
if ((await loadWorkflowState(internals, workflowId))?.status === "cancelled")
|
|
67
|
+
return { status: "cancelled" };
|
|
68
|
+
return {
|
|
69
|
+
status: "failed",
|
|
70
|
+
error: { id: workflowId, error: "Workflow no longer cancellable" }
|
|
71
|
+
};
|
|
79
72
|
});
|
|
80
73
|
for (const cancellationResult of cancellationResults) {
|
|
81
74
|
if (cancellationResult.status === "rejected") {
|
|
@@ -107,27 +100,15 @@ async function runBulkFailedWorkflowRetry(internals, filter, options = {}) {
|
|
|
107
100
|
const bulkConcurrency = resolveBulkOperationConcurrency(options);
|
|
108
101
|
let retried = 0;
|
|
109
102
|
const errors = [], retryResults = await runBulkWorkflowPool(preparation.workflowIds, bulkConcurrency, async (workflowId) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return { status: "retried" };
|
|
113
|
-
} catch (error) {
|
|
114
|
-
return {
|
|
115
|
-
status: "failed",
|
|
116
|
-
error: toBulkOperationError(internals, workflowId, error)
|
|
117
|
-
};
|
|
118
|
-
}
|
|
103
|
+
await retryFailedWorkflow(internals, workflowId);
|
|
104
|
+
return { status: "retried" };
|
|
119
105
|
});
|
|
120
106
|
for (const retryResult of retryResults) {
|
|
121
107
|
if (retryResult.status === "rejected") {
|
|
122
108
|
errors.push(toBulkOperationError(internals, retryResult.item, retryResult.reason));
|
|
123
109
|
continue;
|
|
124
110
|
}
|
|
125
|
-
|
|
126
|
-
if (value.status === "retried") {
|
|
127
|
-
retried += 1;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
errors.push(value.error);
|
|
111
|
+
retried += 1;
|
|
131
112
|
}
|
|
132
113
|
const result = { retried, failed: errors.length, errors };
|
|
133
114
|
if (!shouldPersistBulkAudit(options))
|
|
@@ -122,7 +122,7 @@ export function createTimeOperationCallbacks(engine) {
|
|
|
122
122
|
loadWorkflowState: (workflowId) => loadWorkflowState(getInternals(engine), workflowId),
|
|
123
123
|
failWorkflow: (workflowId, error) => failWorkflow(getInternals(engine), workflowId, error, createTerminationCallbacks(engine)),
|
|
124
124
|
runSerializedWorkflowStateWrite: (workflowId, writeOperation) => runSerializedWorkflowStateWrite(getInternals(engine), workflowId, writeOperation),
|
|
125
|
-
beginWorkflowExecution: (workflowId, workflowType, input, checkpoint, executionDeadline, executionStateOwnerId, registration) => beginWorkflowExecution(getInternals(engine), workflowId, workflowType, input, checkpoint, executionDeadline, executionStateOwnerId, registration, createLifecycleCallbacks(engine)),
|
|
125
|
+
beginWorkflowExecution: (workflowId, workflowExecutionToken, workflowType, input, checkpoint, executionDeadline, executionStateOwnerId, registration) => beginWorkflowExecution(getInternals(engine), workflowId, workflowExecutionToken, workflowType, input, checkpoint, executionDeadline, executionStateOwnerId, registration, createLifecycleCallbacks(engine)),
|
|
126
126
|
workflowVersionTupleFromState: (state) => workflowVersionTupleFromState(getInternals(engine), state, createLifecycleCallbacks(engine)),
|
|
127
127
|
setWorkflowStartHeaders: (workflowId, headers) => setWorkflowStartHeaders(getInternals(engine), workflowId, headers, createLifecycleCallbacks(engine)),
|
|
128
128
|
loadWorkflowStartHeaders: (workflowId) => loadWorkflowStartHeaders(getInternals(engine), workflowId, createLifecycleCallbacks(engine)),
|
|
@@ -76,6 +76,7 @@ export function createLifecycleCallbacks(engine) {
|
|
|
76
76
|
swallowPromiseRejection: (promise) => swallowPromiseRejection(promise),
|
|
77
77
|
enforceHistoryCircuitBreaker: (workflowId) => terminateWorkflow(getInternals(engine), workflowId, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON),
|
|
78
78
|
failWorkflowForUnavailableServices: (workflowId, error) => failWorkflow(getInternals(engine), workflowId, error, createTerminationCallbacks(engine), "system"),
|
|
79
|
+
failWorkflowForRecoveryHook: (workflowId, error) => failWorkflow(getInternals(engine), workflowId, error, createTerminationCallbacks(engine), "system"),
|
|
79
80
|
failWorkflowForCheckpointDecodeError: (workflowId, error) => failWorkflow(getInternals(engine), workflowId, error, createTerminationCallbacks(engine), "system")
|
|
80
81
|
};
|
|
81
82
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { AlertManager } from '../../alerting/alert-manager.ts';
|
|
2
1
|
import type { Storage as WeftStorage } from '../../storage/interface.ts';
|
|
3
2
|
import { ActivityWorkerDispatcher } from '../../workers/activity-worker-dispatcher.ts';
|
|
4
3
|
import type { ComposedWorkflowInterceptor, Interceptor } from '../interceptor.ts';
|
|
5
|
-
import { type AnyActivityDefinition, type AnyWorkflowDefinition, type
|
|
4
|
+
import { type AnyActivityDefinition, type AnyWorkflowDefinition, type RegisteredWorkflowDefinition } from '../types.ts';
|
|
6
5
|
import type { WorkflowLogRecord } from '../types/workflow-log.ts';
|
|
7
6
|
import type { EngineConstructorOptions, ExecutionStrategyBundle, RegistrationEntry, ResolvedOptions } from './engine-internal-types.ts';
|
|
8
7
|
export type KnownWorkflowNames<TWorkflows extends object> = Extract<keyof TWorkflows, string>;
|
|
@@ -60,5 +59,4 @@ export declare function createExecutionStrategyBundle(parameters: {
|
|
|
60
59
|
getLogSink?: () => ((record: WorkflowLogRecord) => void) | undefined;
|
|
61
60
|
}): ExecutionStrategyBundle;
|
|
62
61
|
export declare function createActivityWorkerDispatcher(activityExecution: EngineConstructorOptions['activityExecution']): ActivityWorkerDispatcher | null;
|
|
63
|
-
export declare function createAlertManagerForEngine(engine: EventTarget, alerts: EngineOptions['alerts'] | undefined, getNow: () => number): AlertManager | null;
|
|
64
62
|
export {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AlertManager } from "../../alerting/alert-manager.js";
|
|
2
1
|
import { CompressedStorage } from "../../storage/compressed-storage.js";
|
|
3
2
|
import { MemoryStorage } from "../../storage/memory.js";
|
|
4
3
|
import { ActivityWorkerDispatcher } from "../../workers/activity-worker-dispatcher.js";
|
|
@@ -16,7 +15,7 @@ import {
|
|
|
16
15
|
DEFAULT_WORKER_TURN_TIMEOUT_MS,
|
|
17
16
|
MIN_WORKER_PROTOCOL_MESSAGE_BYTES
|
|
18
17
|
} from "../worker-protocol.js";
|
|
19
|
-
import { resolveOwnershipFields } from "./ownership-options.js";
|
|
18
|
+
import { resolveBackgroundTaskMode, resolveOwnershipFields } from "./ownership-options.js";
|
|
20
19
|
import {
|
|
21
20
|
normalizeHistoryPolicy,
|
|
22
21
|
normalizePayloadSizePolicy,
|
|
@@ -122,6 +121,7 @@ export function resolveEngineOptions(storage, options, getNow) {
|
|
|
122
121
|
getNow,
|
|
123
122
|
resolveWorkflowServices: options?.resolveWorkflowServices ?? null,
|
|
124
123
|
onLog: options?.onLog ?? null,
|
|
124
|
+
backgroundTaskMode: resolveBackgroundTaskMode(options),
|
|
125
125
|
...resolveBooleanDefaults(options),
|
|
126
126
|
...resolveNumericDefaults(options),
|
|
127
127
|
...resolveRetentionFields(options),
|
|
@@ -235,6 +235,3 @@ export function createActivityWorkerDispatcher(activityExecution) {
|
|
|
235
235
|
smol: activityExecution.smol ?? !1
|
|
236
236
|
}));
|
|
237
237
|
}
|
|
238
|
-
export function createAlertManagerForEngine(engine, alerts, getNow) {
|
|
239
|
-
return alerts ? new AlertManager(engine, alerts, getNow) : null;
|
|
240
|
-
}
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* nested coordinator surfaces up to its parent.
|
|
26
26
|
*/
|
|
27
27
|
declare const DEFERRED_CONSUME_BRAND: unique symbol;
|
|
28
|
+
declare const KEYED_RACE_RESULT_BRAND: unique symbol;
|
|
28
29
|
/**
|
|
29
30
|
* A branch result whose real value is produced by a single deferred consume that
|
|
30
31
|
* only the winning coordinator performs.
|
|
@@ -34,6 +35,12 @@ export type DeferredConsumeEnvelope = {
|
|
|
34
35
|
/** Perform the single destructive consume and return the consumed payload. */
|
|
35
36
|
readonly finalize: () => Promise<unknown>;
|
|
36
37
|
};
|
|
38
|
+
type KeyedRaceResultEnvelope = {
|
|
39
|
+
readonly [KEYED_RACE_RESULT_BRAND]: true;
|
|
40
|
+
readonly key: string;
|
|
41
|
+
readonly value: unknown;
|
|
42
|
+
};
|
|
43
|
+
export declare function createKeyedRaceResultEnvelope(key: string, value: unknown): KeyedRaceResultEnvelope;
|
|
37
44
|
/** Wrap a deferred consume into a branded envelope. */
|
|
38
45
|
export declare function createDeferredConsumeEnvelope(finalize: () => Promise<unknown>): DeferredConsumeEnvelope;
|
|
39
46
|
/** Detect an envelope by its brand symbol only (never structurally). */
|
|
@@ -43,7 +50,9 @@ export declare function isDeferredConsumeEnvelope(value: unknown): value is Defe
|
|
|
43
50
|
* cache. A winning `wait-signal` branch surfaces a {@link DeferredConsumeEnvelope}
|
|
44
51
|
* whose `finalize()` performs the single consume; a nested `ctx.all` branch
|
|
45
52
|
* surfaces an ARRAY that may hold envelopes at arbitrary positions, so arrays are
|
|
46
|
-
* walked and each element finalized.
|
|
53
|
+
* walked and each element finalized. A nested `ctx.raceKeyed()` winner is walked
|
|
54
|
+
* through its value while retaining its key. Any other value passes through
|
|
55
|
+
* untouched.
|
|
47
56
|
*
|
|
48
57
|
* This runs only on the WINNING path (race winner, or every branch of a settled
|
|
49
58
|
* `ctx.all`), so finalizing here is exactly the linearization point of "this
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
const DEFERRED_CONSUME_BRAND = Symbol("weft.deferredConsume");
|
|
1
|
+
const DEFERRED_CONSUME_BRAND = Symbol("weft.deferredConsume"), KEYED_RACE_RESULT_BRAND = Symbol("weft.keyedRaceResult");
|
|
2
|
+
export function createKeyedRaceResultEnvelope(key, value) {
|
|
3
|
+
return { [KEYED_RACE_RESULT_BRAND]: !0, key, value };
|
|
4
|
+
}
|
|
5
|
+
function isKeyedRaceResultEnvelope(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && value[KEYED_RACE_RESULT_BRAND] === !0;
|
|
7
|
+
}
|
|
2
8
|
export function createDeferredConsumeEnvelope(finalize) {
|
|
3
9
|
return { [DEFERRED_CONSUME_BRAND]: !0, finalize };
|
|
4
10
|
}
|
|
@@ -10,5 +16,7 @@ export async function finalizeAndUnwrap(value) {
|
|
|
10
16
|
return value.finalize();
|
|
11
17
|
if (Array.isArray(value))
|
|
12
18
|
return Promise.all(value.map((element) => finalizeAndUnwrap(element)));
|
|
19
|
+
if (isKeyedRaceResultEnvelope(value))
|
|
20
|
+
return { key: value.key, value: await finalizeAndUnwrap(value.value) };
|
|
13
21
|
return value;
|
|
14
22
|
}
|
|
@@ -46,6 +46,7 @@ export function disposeEngine(internals) {
|
|
|
46
46
|
internals.pendingWebhooks.clear();
|
|
47
47
|
internals.sleepResolvers.clear();
|
|
48
48
|
internals.sleepResolversByWorkflow.clear();
|
|
49
|
+
internals.sleepTimersFiredWithoutResolver.clear();
|
|
49
50
|
internals.checkpoints.clear();
|
|
50
51
|
internals.pendingExecutionStateOwnerId = void 0;
|
|
51
52
|
internals.workflowNestingDepths.clear();
|
|
@@ -24,6 +24,7 @@ export interface RegistrationEntry {
|
|
|
24
24
|
export interface ResolvedOptions {
|
|
25
25
|
storage: WeftStorage;
|
|
26
26
|
development: boolean;
|
|
27
|
+
backgroundTaskMode: 'automatic' | 'manual';
|
|
27
28
|
checkpointHistory: number;
|
|
28
29
|
checkpointSizeWarningThreshold: number;
|
|
29
30
|
maxNestingDepth: number;
|
|
@@ -84,6 +85,7 @@ export type PendingTimelineEntry = {
|
|
|
84
85
|
};
|
|
85
86
|
export type QueuedInlineWorkflowExecutionStart = {
|
|
86
87
|
workflowId: string;
|
|
88
|
+
workflowExecutionToken?: string;
|
|
87
89
|
workflowType: string;
|
|
88
90
|
input: unknown;
|
|
89
91
|
checkpoint: Checkpoint;
|
|
@@ -4,6 +4,13 @@ import type { Engine } from './index.ts';
|
|
|
4
4
|
import { type EngineInternals } from './internals.ts';
|
|
5
5
|
import type { SecondInstanceDetector } from './second-instance-detector.ts';
|
|
6
6
|
export declare function isActivityDefinition(value: unknown): value is AnyActivityDefinition;
|
|
7
|
+
type EngineCreateBackgroundTaskOptions = {
|
|
8
|
+
backgroundTasks?: 'automatic' | 'manual' | undefined;
|
|
9
|
+
recover?: boolean | undefined;
|
|
10
|
+
startScheduler?: boolean | undefined;
|
|
11
|
+
};
|
|
12
|
+
export declare function validateEngineCreateBackgroundTaskOptions(options: EngineCreateBackgroundTaskOptions): void;
|
|
13
|
+
export declare function shouldStartEngineScheduler(options: EngineCreateBackgroundTaskOptions, backgroundTaskMode: 'automatic' | 'manual'): boolean;
|
|
7
14
|
export declare function createQueuedInlineWorkflowStartHandler<TWorkflows extends object, TActivities extends object>(weakEngine: WeakRef<Engine<TWorkflows, TActivities>>, channel: MessageChannel): () => void;
|
|
8
15
|
/**
|
|
9
16
|
* Drain pending inline launches for `engine` before teardown. Built with the
|
|
@@ -23,3 +30,4 @@ export declare function createCleanupIntervalTick<TWorkflows extends object, TAc
|
|
|
23
30
|
*/
|
|
24
31
|
export declare function createSecondInstanceDetectorResolver<TWorkflows extends object, TActivities extends object>(weakEngine: WeakRef<Engine<TWorkflows, TActivities>>): () => SecondInstanceDetector | null;
|
|
25
32
|
export declare function disposeEngineCleanupInterval(internals: EngineInternals): void;
|
|
33
|
+
export {};
|
|
@@ -12,6 +12,15 @@ import { swallowPromiseRejection } from "./strategy-helpers.js";
|
|
|
12
12
|
export function isActivityDefinition(value) {
|
|
13
13
|
return typeof value === "function" && typeof value.name === "string" && "execute" in value && typeof value.execute === "function";
|
|
14
14
|
}
|
|
15
|
+
export function validateEngineCreateBackgroundTaskOptions(options) {
|
|
16
|
+
if (options.backgroundTasks === "manual" && options.startScheduler === !0)
|
|
17
|
+
throw Error('startScheduler cannot be true when backgroundTasks is "manual"');
|
|
18
|
+
}
|
|
19
|
+
export function shouldStartEngineScheduler(options, backgroundTaskMode) {
|
|
20
|
+
if (backgroundTaskMode === "manual")
|
|
21
|
+
return !1;
|
|
22
|
+
return options.startScheduler ?? options.recover !== !1;
|
|
23
|
+
}
|
|
15
24
|
function inlineLaunchQueueCallbacksForEngine(engine) {
|
|
16
25
|
const lifecycleCallbacks = createLifecycleCallbacks(engine);
|
|
17
26
|
return {
|
|
@@ -43,7 +43,7 @@ export class WorkflowTypeNotRegisteredForRecoveryError extends WeftError {
|
|
|
43
43
|
const missingWorkflowCount = parameters.missingWorkflows.length, missingTypes = [
|
|
44
44
|
...new Set(parameters.missingWorkflows.map((workflow) => workflow.type))
|
|
45
45
|
].toSorted(), registeredTypes = [...parameters.registeredTypes].toSorted(), summarizedTypes = summarizeMissingWorkflowTypes(missingTypes);
|
|
46
|
-
super("WorkflowTypeNotRegisteredForRecoveryError", `Cannot recover ${missingWorkflowCount} running workflow(s): workflow type(s) not registered: ${summarizedTypes}. Register the missing workflow types before calling \`recoverAll()\`, or pass ` + "`{ acknowledgeUnknownWorkflowTypes: true }` (dangerous \u2014 see
|
|
46
|
+
super("WorkflowTypeNotRegisteredForRecoveryError", `Cannot recover ${missingWorkflowCount} running workflow(s): workflow type(s) not registered: ${summarizedTypes}. Register the missing workflow types before calling \`recoverAll()\`, or pass ` + "`{ acknowledgeUnknownWorkflowTypes: true }` (dangerous \u2014 see " + "https://github.com/stevekinney/weft/blob/main/documentation/guides/recovery-and-deploys.md#acknowledging-drift-acknowledgeunknownworkflowtypes).");
|
|
47
47
|
this.registeredTypes = registeredTypes;
|
|
48
48
|
this.missingTypes = missingTypes;
|
|
49
49
|
this.missingWorkflowSamples = parameters.missingWorkflows.slice(0, MISSING_WORKFLOW_SAMPLE_LIMIT).map((workflow) => ({ ...workflow }));
|
|
@@ -21,12 +21,12 @@ import { ScheduleHandle } from './schedule-handle.ts';
|
|
|
21
21
|
import { type WorkflowFeedListener, type WorkflowFeedRecord, type WorkflowFeedSelector } from './workflow-feed.ts';
|
|
22
22
|
export { ActivityReconciliationCapabilityError, ActivityReconciliationConflictError, ActivityReconciliationIndeterminateError, } from './activity-reconciliation.ts';
|
|
23
23
|
export { AsyncActivityTokenNotFoundError } from './async-activity-completion.ts';
|
|
24
|
-
export type { PendingAsyncActivity } from './async-activity-
|
|
24
|
+
export type { PendingAsyncActivity } from './async-activity-records.ts';
|
|
25
25
|
export type { PendingTimelineEntry, RegistrationEntry, ResolvedOptions, TrackedWaiterKeys, WorkflowResultWaiter, } from './engine-internal-types.ts';
|
|
26
26
|
export { ActivityResolutionError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, EngineCreateNameMismatchError, EngineDisposedError, IdempotencyKeyPurgedError, PersistedDataIncompatibleError, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './errors.ts';
|
|
27
27
|
export { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
|
|
28
28
|
export { EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, } from './lease-errors.ts';
|
|
29
|
-
export type { RecoverAllOptions } from './lifecycle.ts';
|
|
29
|
+
export type { RecoverAllOptions, RecoveredWorkflowInfo } from './lifecycle.ts';
|
|
30
30
|
export { ScheduleHandle } from './schedule-handle.ts';
|
|
31
31
|
export type { WorkflowFeedListener, WorkflowFeedRecord, WorkflowFeedSelector, } from './workflow-feed.ts';
|
|
32
32
|
export type { EngineCreateOptions } from './engine-create-types.ts';
|
|
@@ -239,6 +239,16 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
239
239
|
list<const TAttributeKeys extends readonly AttributeFilterKey[] = readonly AttributeFilterKey[]>(filter?: TypedListFilter<TAttributeKeys>, options?: ListOptions): Promise<PaginatedResult<WorkflowSummary>>;
|
|
240
240
|
aggregate(filter: ListFilter | undefined, options: AggregateOptions): Promise<AggregateResult>;
|
|
241
241
|
getRetentionOverview(): RetentionOverview;
|
|
242
|
+
/**
|
|
243
|
+
* Run one host-driven maintenance cycle. This fires due durable timers,
|
|
244
|
+
* deletes expired update responses, applies configured retention, and
|
|
245
|
+
* re-evaluates alert rules without relying on process-local intervals.
|
|
246
|
+
*
|
|
247
|
+
* Use with `backgroundTasks: 'manual'` from a serverless alarm, Cron trigger,
|
|
248
|
+
* or another externally scheduled wake-up. Concurrent calls are safe, but a
|
|
249
|
+
* host should await each cycle before scheduling another.
|
|
250
|
+
*/
|
|
251
|
+
runMaintenance(now?: number): Promise<void>;
|
|
242
252
|
purge(filter?: ListFilter): Promise<PurgeResult>;
|
|
243
253
|
cancelAll(filter: ListFilter, options: BulkOperationDryRunOptions): Promise<BulkOperationDryRunResult>;
|
|
244
254
|
cancelAll(filter: ListFilter, options?: BulkOperationCommitOptions): Promise<BulkCancelResult>;
|