@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveConnection } from "../connection.js";
|
|
2
|
-
import { failureCategoryForFaultCode
|
|
2
|
+
import { failureCategoryForFaultCode } from "../core/fault-code.js";
|
|
3
3
|
import { isWeftErrorCode, WeftError } from "../core/weft-error.js";
|
|
4
4
|
export function resolveHttpClientConnection(options) {
|
|
5
5
|
const connection = resolveConnection({
|
|
@@ -41,19 +41,13 @@ function buildRequestHeaders(baseHeaders, options) {
|
|
|
41
41
|
function isFlatErrorBody(value) {
|
|
42
42
|
return value !== null && typeof value === "object" && typeof value.error === "string";
|
|
43
43
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
function weftCodeFromData(data) {
|
|
53
|
-
if (data === null || typeof data !== "object")
|
|
54
|
-
return;
|
|
55
|
-
const candidate = data.weftCode;
|
|
56
|
-
return isWeftErrorCode(candidate) ? candidate : void 0;
|
|
44
|
+
function parseFlatErrorBody(body) {
|
|
45
|
+
const weftCode = isWeftErrorCode(body.weftCode) ? body.weftCode : void 0, data = isRecord(body.data) ? body.data : void 0;
|
|
46
|
+
return {
|
|
47
|
+
message: body.error,
|
|
48
|
+
...weftCode === void 0 ? {} : { weftCode },
|
|
49
|
+
...data === void 0 ? {} : { data }
|
|
50
|
+
};
|
|
57
51
|
}
|
|
58
52
|
function isRecord(value) {
|
|
59
53
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -61,32 +55,28 @@ function isRecord(value) {
|
|
|
61
55
|
async function parseErrorBody(response) {
|
|
62
56
|
try {
|
|
63
57
|
const body = await response.json();
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
if (weftCode !== void 0)
|
|
67
|
-
base.weftCode = weftCode;
|
|
68
|
-
if (isRecord(data))
|
|
69
|
-
base.data = data;
|
|
70
|
-
return isFaultCode(code) ? { ...base, faultCode: code } : base;
|
|
71
|
-
}
|
|
72
|
-
if (isFlatErrorBody(body) && body.error) {
|
|
73
|
-
const weftCode = isWeftErrorCode(body.weftCode) ? body.weftCode : void 0;
|
|
74
|
-
return weftCode === void 0 ? { message: body.error } : { message: body.error, weftCode };
|
|
75
|
-
}
|
|
58
|
+
if (isFlatErrorBody(body) && body.error)
|
|
59
|
+
return parseFlatErrorBody(body);
|
|
76
60
|
return { message: response.statusText };
|
|
77
61
|
} catch {
|
|
78
62
|
return { message: response.statusText };
|
|
79
63
|
}
|
|
80
64
|
}
|
|
81
65
|
export async function request(baseUrl, path, baseHeaders, options) {
|
|
66
|
+
const response = await requestResponse(baseUrl, path, baseHeaders, options);
|
|
67
|
+
if (response === null)
|
|
68
|
+
return null;
|
|
69
|
+
if (response.status === 204)
|
|
70
|
+
return;
|
|
71
|
+
return response.json();
|
|
72
|
+
}
|
|
73
|
+
export async function requestResponse(baseUrl, path, baseHeaders, options) {
|
|
82
74
|
const headers = buildRequestHeaders(baseHeaders, options), response = await fetch(`${baseUrl}/v1${path}`, { ...options, headers });
|
|
83
75
|
if (response.status === 404 && (!options?.method || options.method === "GET"))
|
|
84
76
|
return null;
|
|
85
77
|
if (!response.ok) {
|
|
86
|
-
const { message,
|
|
87
|
-
throw new HttpClientError(response.status, message, {
|
|
78
|
+
const { message, weftCode, data } = await parseErrorBody(response);
|
|
79
|
+
throw new HttpClientError(response.status, message, { weftCode, data });
|
|
88
80
|
}
|
|
89
|
-
|
|
90
|
-
return;
|
|
91
|
-
return response.json();
|
|
81
|
+
return response;
|
|
92
82
|
}
|
|
@@ -22,9 +22,9 @@ import type { Engine } from '../core/engine.ts';
|
|
|
22
22
|
*
|
|
23
23
|
* The registry and trusted principal are constructed once and reused across
|
|
24
24
|
* calls. Operations run with `transport: 'jsonRpcHttp'` so input/output
|
|
25
|
-
* validation and unknown-key handling match the remote
|
|
25
|
+
* validation and unknown-key handling match the selected remote transport.
|
|
26
26
|
* A failed dispatch throws with the fault message, mirroring the HTTP
|
|
27
27
|
* transport's `throw new Error(result.error.message)` contract so both clients
|
|
28
28
|
* surface operation faults the same way.
|
|
29
29
|
*/
|
|
30
|
-
export declare function inProcessCatalogTransport(engine: Engine): CatalogTransport;
|
|
30
|
+
export declare function inProcessCatalogTransport(engine: Engine, restOperationNames?: ReadonlySet<string>): CatalogTransport;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { executeOperation } from "../server/operation-catalog.js";
|
|
2
2
|
import { principalFromStdioLocal } from "../server/principal.js";
|
|
3
3
|
import { createLiveOperationRegistry } from "../server/rest-bindings.js";
|
|
4
|
-
export function inProcessCatalogTransport(engine) {
|
|
4
|
+
export function inProcessCatalogTransport(engine, restOperationNames = new Set) {
|
|
5
5
|
const registry = createLiveOperationRegistry(), principal = principalFromStdioLocal();
|
|
6
6
|
return async (operationName, input) => {
|
|
7
7
|
const result = await executeOperation(operationName, input, {
|
|
8
8
|
principal,
|
|
9
9
|
engine,
|
|
10
|
-
transport: "jsonRpcHttp",
|
|
10
|
+
transport: restOperationNames.has(operationName) ? "http-rest" : "jsonRpcHttp",
|
|
11
11
|
registry
|
|
12
12
|
});
|
|
13
13
|
if (!result.ok)
|
package/dist/client/index.d.ts
CHANGED
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module client/index
|
|
9
9
|
*/
|
|
10
|
-
export {
|
|
10
|
+
export { WorkflowCancelledEvent, WorkflowCompletedEvent, WorkflowFailedEvent, WorkflowResumedEvent, WorkflowStartedEvent, WorkflowSuspendedEvent, WorkflowTeardownEvent, WorkflowTimedOutEvent, } from '../core/events/workflow-events.ts';
|
|
11
|
+
export { isFaultCode, type FaultCode } from '../core/fault-code.ts';
|
|
12
|
+
export type { PendingAsyncActivityInfo, PendingAsyncActivityListOptions, PendingAsyncActivityPage, } from '../core/types.ts';
|
|
13
|
+
export { WeftError, isWeftError, isWeftErrorCode, isWeftErrorLike, isWeftFault, } from '../core/weft-error.ts';
|
|
11
14
|
export type { WeftErrorCode } from '../core/weft-error.ts';
|
|
15
|
+
export type { WeftClientStorage } from './client-storage.ts';
|
|
12
16
|
export type { WorkflowEventStreamOptions, WorkflowEventTransport } from './event-stream-options.ts';
|
|
13
17
|
export type { WorkflowEventTail } from './event-tail.ts';
|
|
14
18
|
export { HttpClient } from './http-client.ts';
|
package/dist/client/index.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
export {
|
|
2
|
+
WorkflowCancelledEvent,
|
|
3
|
+
WorkflowCompletedEvent,
|
|
4
|
+
WorkflowFailedEvent,
|
|
5
|
+
WorkflowResumedEvent,
|
|
6
|
+
WorkflowStartedEvent,
|
|
7
|
+
WorkflowSuspendedEvent,
|
|
8
|
+
WorkflowTeardownEvent,
|
|
9
|
+
WorkflowTimedOutEvent
|
|
10
|
+
} from "../core/events/workflow-events.js";
|
|
11
|
+
export { isFaultCode } from "../core/fault-code.js";
|
|
12
|
+
export {
|
|
13
|
+
WeftError,
|
|
2
14
|
isWeftError,
|
|
3
15
|
isWeftErrorCode,
|
|
4
16
|
isWeftErrorLike,
|
|
5
|
-
isWeftFault
|
|
6
|
-
WeftError
|
|
17
|
+
isWeftFault
|
|
7
18
|
} from "../core/weft-error.js";
|
|
8
19
|
export { HttpClient } from "./http-client.js";
|
|
9
20
|
export { HttpClientError } from "./http-request.js";
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module client/interface
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
8
|
+
import type { ClientOperationName, ClientOperationTypes, ClientOperations } from '../cli/generated/operation-client.generated.ts';
|
|
9
9
|
import type { StoredStreamChunk } from '../core/context.ts';
|
|
10
10
|
import type { StartOrSignalOutcome as EngineStartOrSignalOutcome } from '../core/engine/handles.ts';
|
|
11
11
|
import type { TypedEventTarget, WeftEventMap } from '../core/events.ts';
|
|
12
|
-
import type { AttributeFilterKey, BulkCancelResult, BulkDeleteResult, BulkRetryFailedResult, BulkSignalResult, BulkTagResult, CoordinatedUpdateResult, ForkOptions, ListFilter, PaginatedResult, PurgeResult, QueryDefinition, RetentionOverview, ReviewListEntry, ReviewListFilter, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleSummary, SearchAttributeValue, SignalDefinition, SignalDeliveryOptions, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TypedListFilter, UpdateDefinition, WorkflowEvent, WorkflowInput, WorkflowOutput, WorkflowRegistry, WorkflowReplay, WorkflowState, WorkflowSummary, WorkflowTimelineEntry } from '../core/types.ts';
|
|
12
|
+
import type { AttributeFilterKey, BulkCancelResult, BulkDeleteResult, BulkRetryFailedResult, BulkSignalResult, BulkTagResult, CoordinatedUpdateResult, ForkOptions, ListFilter, PaginatedResult, PendingAsyncActivityListOptions, PendingAsyncActivityPage, PurgeResult, QueryDefinition, RetentionOverview, ReviewListEntry, ReviewListFilter, ScheduleUpdateOptions as ScheduleEdit, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleSummary, SearchAttributeValue, SignalDefinition, SignalDeliveryOptions, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TypedListFilter, UpdateDefinition, WorkflowEvent, WorkflowInput, WorkflowOutput, WorkflowRegistry, WorkflowReplay, WorkflowState, WorkflowSummary, WorkflowTimelineEntry } from '../core/types.ts';
|
|
13
|
+
import type { WeftClientStorage } from './client-storage.ts';
|
|
13
14
|
import type { WorkflowEventTail } from './event-tail.ts';
|
|
14
15
|
import type { KnownWorkflowName, UnknownNameWhenRegistryEmpty } from './workflow-name-typing.ts';
|
|
15
16
|
/**
|
|
@@ -197,8 +198,8 @@ export interface ClientScheduleHandle extends Disposable {
|
|
|
197
198
|
resume(): Promise<void>;
|
|
198
199
|
/** Cancel this schedule. */
|
|
199
200
|
cancel(): Promise<void>;
|
|
200
|
-
/** Update the schedule
|
|
201
|
-
update(newSpec: string | ScheduleSpec): Promise<void>;
|
|
201
|
+
/** Update the schedule cadence and optional mutable schedule settings. */
|
|
202
|
+
update(newSpec: string | ScheduleSpec, options?: ScheduleEdit): Promise<void>;
|
|
202
203
|
/** Read the latest persisted summary for this schedule. */
|
|
203
204
|
describe(): Promise<ScheduleSummary | null>;
|
|
204
205
|
}
|
|
@@ -212,24 +213,21 @@ export type UpdateResult = {
|
|
|
212
213
|
* Out-of-band ("async") activity completion surface, shared by every client.
|
|
213
214
|
*
|
|
214
215
|
* An activity that called `ActivityContext.completeAsync()` parks its workflow
|
|
215
|
-
* until an external system resolves it by
|
|
216
|
-
* the
|
|
217
|
-
* directly; server mode
|
|
218
|
-
*
|
|
219
|
-
* consumes the single-use token before re-adoption and strands the workflow. The
|
|
220
|
-
* token is a deterministic identifier, not a secret (see `completeAsync`).
|
|
216
|
+
* until an external system resolves it by durable task token. `listPending()`
|
|
217
|
+
* queries the durable record after a missed live event or process restart.
|
|
218
|
+
* Library mode calls the engine directly; server mode uses the matching REST
|
|
219
|
+
* operations. The token is a deterministic identifier, not a secret.
|
|
221
220
|
*
|
|
222
221
|
* @example
|
|
223
222
|
* ```ts
|
|
224
|
-
* import {
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* // `token` comes from the engine's `activity:async-pending` event:
|
|
228
|
-
* // await activity.complete(token, { approved: true });
|
|
229
|
-
* void activity;
|
|
223
|
+
* import type { WeftClientActivity } from '@lostgradient/weft/client';
|
|
224
|
+
* declare const activity: WeftClientActivity;
|
|
225
|
+
* void activity.listPending('order-1');
|
|
230
226
|
* ```
|
|
231
227
|
*/
|
|
232
228
|
export interface WeftClientActivity {
|
|
229
|
+
/** List a bounded page of durable activities awaiting completion for one workflow. */
|
|
230
|
+
listPending(workflowId: string, options?: PendingAsyncActivityListOptions): Promise<PendingAsyncActivityPage>;
|
|
233
231
|
/** Complete a deferred activity by token, resuming its workflow with `result` (optional; omitted/`undefined` resumes with `undefined`). */
|
|
234
232
|
complete(token: string, result?: unknown): Promise<void>;
|
|
235
233
|
/** Fail a deferred activity by token; the error is thrown into its workflow. */
|
|
@@ -259,7 +257,6 @@ export interface WeftClient {
|
|
|
259
257
|
* returned handle's `result()` to its output type. Without augmentation the
|
|
260
258
|
* permissive string-name overload applies, so the client stays usable with
|
|
261
259
|
* plain string names and no hard dependency on codegen.
|
|
262
|
-
*
|
|
263
260
|
* Pass `options.idempotencyKey` for at-most-once starts: a repeated key returns
|
|
264
261
|
* a handle to the existing run rather than starting a second. Conflicts (a
|
|
265
262
|
* duplicate `id`, or a key whose run was purged) are transport-dependent:
|
|
@@ -339,8 +336,8 @@ export interface WeftClient {
|
|
|
339
336
|
resumeSchedule(id: string): Promise<void>;
|
|
340
337
|
/** Cancel a recurring schedule. */
|
|
341
338
|
cancelSchedule(id: string): Promise<void>;
|
|
342
|
-
/** Update a recurring schedule's
|
|
343
|
-
updateSchedule(id: string, newSpec: string | ScheduleSpec): Promise<void>;
|
|
339
|
+
/** Update a recurring schedule's cadence and optional mutable schedule settings. */
|
|
340
|
+
updateSchedule(id: string, newSpec: string | ScheduleSpec, options?: ScheduleEdit): Promise<void>;
|
|
344
341
|
/** Send a named signal to a workflow. */
|
|
345
342
|
signal(id: string, name: SignalDefinition): Promise<void>;
|
|
346
343
|
signal<TInput>(id: string, name: SignalDefinition<TInput>, payload: TInput, options?: SignalDeliveryOptions): Promise<void>;
|
|
@@ -433,11 +430,12 @@ export interface WeftClient {
|
|
|
433
430
|
/**
|
|
434
431
|
* Typed low-level accessor for the full operation catalog.
|
|
435
432
|
*
|
|
436
|
-
* Every
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
433
|
+
* Every unary JSON-RPC operation and ordinary schema-shaped REST-only
|
|
434
|
+
* operation is reachable as `client.operations['weft.<op>']`, including
|
|
435
|
+
* server operations the ergonomic surface does not curate (workers, task
|
|
436
|
+
* queues, task diagnostics, system lease/metrics/registry, checkpoints). Binary
|
|
437
|
+
* and streaming raw-storage routes use {@link storage} instead. New compatible
|
|
438
|
+
* operations appear here when the snapshot regenerates.
|
|
441
439
|
*
|
|
442
440
|
* @example
|
|
443
441
|
* ```ts
|
|
@@ -450,11 +448,13 @@ export interface WeftClient {
|
|
|
450
448
|
* void metrics;
|
|
451
449
|
* ```
|
|
452
450
|
*/
|
|
453
|
-
readonly operations:
|
|
451
|
+
readonly operations: ClientOperations;
|
|
452
|
+
/** Raw storage administration with byte values and streaming scans. */
|
|
453
|
+
readonly storage: WeftClientStorage;
|
|
454
454
|
/**
|
|
455
455
|
* Invoke a single catalog operation by name, with its input and output typed
|
|
456
456
|
* from the generated catalog. Equivalent to `client.operations[name](input)`
|
|
457
457
|
* but ergonomic when the operation name is known dynamically.
|
|
458
458
|
*/
|
|
459
|
-
call<Name extends
|
|
459
|
+
call<Name extends ClientOperationName>(name: Name, input: ClientOperationTypes[Name]['input']): Promise<ClientOperationTypes[Name]['output']>;
|
|
460
460
|
}
|
package/dist/client/local.d.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module client/local
|
|
9
9
|
*/
|
|
10
|
-
import { type
|
|
10
|
+
import { type ClientOperationName, type ClientOperationTypes, type ClientOperations } from '../cli/generated/operation-client.generated.ts';
|
|
11
11
|
import type { Engine } from '../core/engine.ts';
|
|
12
|
-
import type { AttributeFilterKey, BulkCancelResult, BulkDeleteResult, BulkRetryFailedResult, BulkSignalResult, BulkTagResult, CoordinatedUpdateResult, DefaultActivityTypes, DefaultWorkflowRegistry, ForkOptions, ListFilter, PaginatedResult, PurgeResult, QueryDefinition, RetentionOverview, ReviewListEntry, ReviewListFilter, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleSummary, SearchAttributeValue, SignalDefinition, SignalDeliveryOptions, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TypedListFilter, UpdateDefinition, WorkflowEvent, WorkflowInput, WorkflowOutput, WorkflowRegistry, WorkflowReplay, WorkflowState, WorkflowSummary, WorkflowTimelineEntry } from '../core/types.ts';
|
|
12
|
+
import type { AttributeFilterKey, BulkCancelResult, BulkDeleteResult, BulkRetryFailedResult, BulkSignalResult, BulkTagResult, CoordinatedUpdateResult, DefaultActivityTypes, DefaultWorkflowRegistry, ForkOptions, ListFilter, PaginatedResult, PurgeResult, QueryDefinition, RetentionOverview, ReviewListEntry, ReviewListFilter, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleSummary, ScheduleUpdateOptions, SearchAttributeValue, SignalDefinition, SignalDeliveryOptions, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TypedListFilter, UpdateDefinition, WorkflowEvent, WorkflowInput, WorkflowOutput, WorkflowRegistry, WorkflowReplay, WorkflowState, WorkflowSummary, WorkflowTimelineEntry } from '../core/types.ts';
|
|
13
|
+
import { type WeftClientStorage } from './client-storage.ts';
|
|
13
14
|
import type { WorkflowEventTail } from './event-tail.ts';
|
|
14
15
|
import type { ClientHandle, ClientScheduleHandle, UpdateResult, WeftClient, WeftClientActivity } from './interface.ts';
|
|
15
16
|
import type { KnownWorkflowName, UnknownNameWhenRegistryEmpty } from './workflow-name-typing.ts';
|
|
@@ -34,8 +35,10 @@ import type { KnownWorkflowName, UnknownNameWhenRegistryEmpty } from './workflow
|
|
|
34
35
|
*/
|
|
35
36
|
export declare class LocalClient<TWorkflows extends object = DefaultWorkflowRegistry, TActivities extends object = DefaultActivityTypes> implements WeftClient {
|
|
36
37
|
#private;
|
|
37
|
-
/** Typed low-level accessor for every
|
|
38
|
-
readonly operations:
|
|
38
|
+
/** Typed low-level accessor for every client-callable operation, routed in-process. */
|
|
39
|
+
readonly operations: ClientOperations;
|
|
40
|
+
/** Raw storage administration against the engine-owned backend. */
|
|
41
|
+
readonly storage: WeftClientStorage;
|
|
39
42
|
/**
|
|
40
43
|
* Out-of-band ("async") activity completion. An activity that called
|
|
41
44
|
* `ActivityContext.completeAsync()` parks its workflow until an external
|
|
@@ -54,7 +57,7 @@ export declare class LocalClient<TWorkflows extends object = DefaultWorkflowRegi
|
|
|
54
57
|
*/
|
|
55
58
|
readonly activity: WeftClientActivity;
|
|
56
59
|
constructor(engine: Engine<TWorkflows, TActivities> | Engine);
|
|
57
|
-
call<Name extends
|
|
60
|
+
call<Name extends ClientOperationName>(name: Name, input: ClientOperationTypes[Name]['input']): Promise<ClientOperationTypes[Name]['output']>;
|
|
58
61
|
start<TName extends KnownWorkflowName>(type: TName, input: WorkflowInput<WorkflowRegistry, TName>, options?: StartOptions): Promise<ClientHandle<WorkflowOutput<WorkflowRegistry, TName>>>;
|
|
59
62
|
start<TName extends string>(type: UnknownNameWhenRegistryEmpty<TName>, input: unknown, options?: StartOptions): Promise<ClientHandle>;
|
|
60
63
|
startOrSignal<TName extends KnownWorkflowName>(type: TName, input: WorkflowInput<WorkflowRegistry, TName>, signal: StartOrSignalSignal, options?: StartOrSignalOptions): Promise<ClientHandle<WorkflowOutput<WorkflowRegistry, TName>>>;
|
|
@@ -72,7 +75,7 @@ export declare class LocalClient<TWorkflows extends object = DefaultWorkflowRegi
|
|
|
72
75
|
pauseSchedule(id: string): Promise<void>;
|
|
73
76
|
resumeSchedule(id: string): Promise<void>;
|
|
74
77
|
cancelSchedule(id: string): Promise<void>;
|
|
75
|
-
updateSchedule(id: string, newSpec: string | ScheduleSpec): Promise<void>;
|
|
78
|
+
updateSchedule(id: string, newSpec: string | ScheduleSpec, options?: ScheduleUpdateOptions): Promise<void>;
|
|
76
79
|
signal(id: string, name: SignalDefinition): Promise<void>;
|
|
77
80
|
signal<TInput>(id: string, name: SignalDefinition<TInput>, payload: TInput, options?: SignalDeliveryOptions): Promise<void>;
|
|
78
81
|
signal(id: string, name: string, payload?: unknown, options?: SignalDeliveryOptions): Promise<void>;
|
package/dist/client/local.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
CLIENT_OPERATION_NAMES,
|
|
3
|
+
CLIENT_REST_OPERATION_BINDINGS
|
|
3
4
|
} from "../cli/generated/operation-client.generated.js";
|
|
4
5
|
import { createCatalogWeftClient } from "../cli/operation-client-runtime.js";
|
|
5
6
|
import {
|
|
6
7
|
runtimeWorkflowEngine
|
|
7
8
|
} from "../core/runtime-workflow-engine.js";
|
|
8
9
|
import { messageName } from "../core/types.js";
|
|
10
|
+
import { createLocalClientStorage } from "./client-storage.js";
|
|
9
11
|
import { inProcessCatalogTransport } from "./in-process-operations.js";
|
|
10
12
|
import { createLocalWorkflowEventTail } from "./local-event-tail.js";
|
|
11
13
|
import { LocalHandle, LocalScheduleHandle } from "./local-handles.js";
|
|
@@ -14,15 +16,18 @@ export class LocalClient {
|
|
|
14
16
|
#engine;
|
|
15
17
|
#rawEngine;
|
|
16
18
|
operations;
|
|
19
|
+
storage;
|
|
17
20
|
activity;
|
|
18
21
|
constructor(engine) {
|
|
19
22
|
this.#engine = runtimeWorkflowEngine(engine);
|
|
20
23
|
this.#rawEngine = engine;
|
|
24
|
+
this.storage = createLocalClientStorage(this.#rawEngine.storage);
|
|
21
25
|
this.activity = {
|
|
26
|
+
listPending: (workflowId, options) => this.#engine.listPendingAsyncActivities(workflowId, options),
|
|
22
27
|
complete: (token, result) => this.#engine.completeAsyncActivity(token, result),
|
|
23
28
|
completeExceptionally: (token, error) => this.#engine.failAsyncActivity(token, error)
|
|
24
29
|
};
|
|
25
|
-
this.operations = createCatalogWeftClient(
|
|
30
|
+
this.operations = createCatalogWeftClient(CLIENT_OPERATION_NAMES, inProcessCatalogTransport(this.#rawEngine, new Set(Object.keys(CLIENT_REST_OPERATION_BINDINGS))));
|
|
26
31
|
}
|
|
27
32
|
call(name, input) {
|
|
28
33
|
return this.operations[name](input);
|
|
@@ -71,8 +76,8 @@ export class LocalClient {
|
|
|
71
76
|
async cancelSchedule(id) {
|
|
72
77
|
return this.#engine.cancelSchedule(id);
|
|
73
78
|
}
|
|
74
|
-
async updateSchedule(id, newSpec) {
|
|
75
|
-
return this.#engine.updateSchedule(id, newSpec);
|
|
79
|
+
async updateSchedule(id, newSpec, options) {
|
|
80
|
+
return this.#engine.updateSchedule(id, newSpec, options);
|
|
76
81
|
}
|
|
77
82
|
async signal(id, nameOrDefinition, payload, options) {
|
|
78
83
|
if (options === void 0)
|
|
@@ -29,16 +29,20 @@ function appendAttributeFilters(params, attributes) {
|
|
|
29
29
|
params.set(`attr.${key}.lte`, String(attribute.lte));
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
+
function appendOptionalSearchParameter(params, key, value) {
|
|
33
|
+
if (value !== void 0)
|
|
34
|
+
params.set(key, String(value));
|
|
35
|
+
}
|
|
32
36
|
export function buildWorkflowListSearchParams(filter) {
|
|
33
37
|
const params = new URLSearchParams;
|
|
34
38
|
appendStatusFilters(params, filter?.status);
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
appendOptionalSearchParameter(params, "type", filter?.type);
|
|
40
|
+
appendOptionalSearchParameter(params, "schedule_id", filter?.scheduleId);
|
|
41
|
+
appendOptionalSearchParameter(params, "parent_workflow_id", filter?.parentWorkflowId);
|
|
42
|
+
appendOptionalSearchParameter(params, "parent_workflow_execution_token", filter?.parentWorkflowExecutionToken);
|
|
37
43
|
appendTagFilters(params, filter?.tags);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (filter?.offset !== void 0)
|
|
41
|
-
params.set("offset", String(filter.offset));
|
|
44
|
+
appendOptionalSearchParameter(params, "limit", filter?.limit);
|
|
45
|
+
appendOptionalSearchParameter(params, "offset", filter?.offset);
|
|
42
46
|
appendAttributeFilters(params, filter?.attributes);
|
|
43
47
|
return params;
|
|
44
48
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScheduleSpec, StartOrSignalSignal } from '../core/types.ts';
|
|
1
|
+
import type { ScheduleOptions, ScheduleSpec, StartOrSignalSignal } from '../core/types.ts';
|
|
2
2
|
import type { ClientStartOptions, ClientStartOrSignalOptions } from './interface.ts';
|
|
3
3
|
export declare function setIfDefined(body: Record<string, unknown>, key: string, value: unknown): void;
|
|
4
4
|
/**
|
|
@@ -7,6 +7,8 @@ export declare function setIfDefined(body: Record<string, unknown>, key: string,
|
|
|
7
7
|
* `cronExpression`; an interval spec is sent as `every`.
|
|
8
8
|
*/
|
|
9
9
|
export declare function scheduleSpecToWireFields(spec: string | ScheduleSpec): Record<string, unknown>;
|
|
10
|
+
/** Build a schedule-create wire body from the explicitly supported option fields. */
|
|
11
|
+
export declare function buildScheduleBody(type: string, input: unknown, spec: string | ScheduleSpec, options?: ScheduleOptions): Record<string, unknown>;
|
|
10
12
|
export declare function buildStartBody(type: string, input: unknown, options?: ClientStartOptions): Record<string, unknown>;
|
|
11
13
|
/**
|
|
12
14
|
* Build the wire body for `weft.workflows.startorsignal`. Flattens the signal
|
|
@@ -9,6 +9,15 @@ export function scheduleSpecToWireFields(spec) {
|
|
|
9
9
|
return { every: spec.every };
|
|
10
10
|
return { cronExpression: spec.cron };
|
|
11
11
|
}
|
|
12
|
+
export function buildScheduleBody(type, input, spec, options) {
|
|
13
|
+
const body = { type, input, ...scheduleSpecToWireFields(spec) };
|
|
14
|
+
setIfDefined(body, "id", options?.id);
|
|
15
|
+
setIfDefined(body, "description", options?.description);
|
|
16
|
+
setIfDefined(body, "overlap", options?.overlap);
|
|
17
|
+
setIfDefined(body, "backfill", options?.backfill);
|
|
18
|
+
setIfDefined(body, "jitter", options?.jitter);
|
|
19
|
+
return body;
|
|
20
|
+
}
|
|
12
21
|
function applyStartOptionsToBody(body, options) {
|
|
13
22
|
setIfDefined(body, "id", options?.id);
|
|
14
23
|
setIfDefined(body, "executionTimeout", options?.executionTimeout);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ListFilter } from './types.ts';
|
|
2
|
-
export declare const BULK_WORKFLOW_FILTER_ERROR_MESSAGE = "Field \"filter\" must include at least one of status, type, tags, attributes, idPrefix (\u22653 chars), or failureCategory paired with status";
|
|
2
|
+
export declare const BULK_WORKFLOW_FILTER_ERROR_MESSAGE = "Field \"filter\" must include at least one of status, type, scheduleId, tags, attributes, idPrefix (\u22653 chars), or failureCategory paired with status";
|
|
3
3
|
/**
|
|
4
4
|
* Returns `true` when the filter narrows destructive bulk operations
|
|
5
5
|
* to a scoped subset rather than every workflow on the engine.
|
|
@@ -7,6 +7,7 @@ export declare const BULK_WORKFLOW_FILTER_ERROR_MESSAGE = "Field \"filter\" must
|
|
|
7
7
|
* Valid scopes:
|
|
8
8
|
* - `status` (non-empty after normalization).
|
|
9
9
|
* - `type` (non-empty after trim).
|
|
10
|
+
* - `scheduleId` (non-empty after trim).
|
|
10
11
|
* - `tags` (at least one tag after normalization).
|
|
11
12
|
* - `attributes` (at least one attribute predicate with a non-empty key).
|
|
12
13
|
* - `idPrefix` (length ≥ 3 — short prefixes match too much to be a safe scope).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { searchAttributeName } from "./search-attributes.js";
|
|
2
2
|
import { normalizeWorkflowTags } from "./workflow-tags.js";
|
|
3
3
|
const ID_PREFIX_MIN_LENGTH = 3;
|
|
4
|
-
export const BULK_WORKFLOW_FILTER_ERROR_MESSAGE = 'Field "filter" must include at least one of status, type, tags, attributes, idPrefix (\u22653 chars), or failureCategory paired with status';
|
|
4
|
+
export const BULK_WORKFLOW_FILTER_ERROR_MESSAGE = 'Field "filter" must include at least one of status, type, scheduleId, tags, attributes, idPrefix (\u22653 chars), or failureCategory paired with status';
|
|
5
5
|
function hasScopedStatusFilter(filter) {
|
|
6
6
|
if (filter.status === void 0)
|
|
7
7
|
return !1;
|
|
@@ -12,6 +12,9 @@ function hasScopedStatusFilter(filter) {
|
|
|
12
12
|
function hasScopedTypeFilter(filter) {
|
|
13
13
|
return filter.type !== void 0 && filter.type.trim().length > 0;
|
|
14
14
|
}
|
|
15
|
+
function hasScopedScheduleFilter(filter) {
|
|
16
|
+
return filter.scheduleId !== void 0 && filter.scheduleId.trim().length > 0;
|
|
17
|
+
}
|
|
15
18
|
function hasScopedTagsFilter(filter) {
|
|
16
19
|
return (normalizeWorkflowTags(filter.tags)?.length ?? 0) > 0;
|
|
17
20
|
}
|
|
@@ -24,6 +27,7 @@ function hasScopedIdPrefix(filter) {
|
|
|
24
27
|
const BULK_FILTER_DIMENSION_CHECKS = {
|
|
25
28
|
status: hasScopedStatusFilter,
|
|
26
29
|
type: hasScopedTypeFilter,
|
|
30
|
+
scheduleId: hasScopedScheduleFilter,
|
|
27
31
|
tags: hasScopedTagsFilter,
|
|
28
32
|
attributes: hasScopedAttributesFilter,
|
|
29
33
|
idPrefix: hasScopedIdPrefix
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { Context } from './index.ts';
|
|
2
2
|
import type { ContextInternals } from './internals.ts';
|
|
3
3
|
import type { ContextOperationRequest } from './operation-request.ts';
|
|
4
|
-
import { assertValidParallelOperationCacheEntry, BranchTopologyChangedError, createParallelOperationCacheEntry, isParallelOperationCacheEntry, type ParallelBranchSlot, type ParallelOperationCacheEntry } from './parallel-cache-entry.ts';
|
|
5
|
-
export { assertValidParallelOperationCacheEntry, BranchTopologyChangedError, createParallelOperationCacheEntry, isParallelOperationCacheEntry, type ParallelBranchSlot, type ParallelOperationCacheEntry, };
|
|
6
4
|
export declare function all(context: Context, internals: ContextInternals, operations: Generator<ContextOperationRequest, unknown, unknown>[]): Generator<ContextOperationRequest, unknown[], unknown>;
|
|
7
5
|
export declare function race(context: Context, internals: ContextInternals, operations: Generator<ContextOperationRequest, unknown, unknown>[], branchNames?: string[]): Generator<ContextOperationRequest, unknown, unknown>;
|
|
8
6
|
export declare function memo<T>(context: Context, internals: ContextInternals, key: string, fn: () => T | Promise<T>): Generator<ContextOperationRequest, T, unknown>;
|
|
@@ -6,13 +6,6 @@ import {
|
|
|
6
6
|
isParallelOperationCacheEntry
|
|
7
7
|
} from "./parallel-cache-entry.js";
|
|
8
8
|
import { captureCallerStack } from "./validation.js";
|
|
9
|
-
|
|
10
|
-
export {
|
|
11
|
-
assertValidParallelOperationCacheEntry,
|
|
12
|
-
BranchTopologyChangedError,
|
|
13
|
-
createParallelOperationCacheEntry,
|
|
14
|
-
isParallelOperationCacheEntry
|
|
15
|
-
};
|
|
16
9
|
function reconstructAllResult(entry) {
|
|
17
10
|
return entry.branches.map((slot) => {
|
|
18
11
|
if (slot.status !== "fulfilled")
|
|
@@ -16,8 +16,11 @@
|
|
|
16
16
|
* key derivations, and the in-memory resolution queue that recovery drains.
|
|
17
17
|
*/
|
|
18
18
|
import { type BatchOperation } from '../../storage/interface.ts';
|
|
19
|
-
import type { OperationOutcome } from '../types.ts';
|
|
19
|
+
import type { OperationOutcome, PendingAsyncActivityListOptions, PendingAsyncActivityPage } from '../types.ts';
|
|
20
20
|
import type { EngineInternals } from './internals.ts';
|
|
21
|
+
export declare const DEFAULT_PENDING_ASYNC_ACTIVITY_LIMIT = 50;
|
|
22
|
+
export declare const MAX_PENDING_ASYNC_ACTIVITY_LIMIT = 200;
|
|
23
|
+
export declare const MAX_PENDING_ASYNC_ACTIVITY_CURSOR_LENGTH = 8192;
|
|
21
24
|
/**
|
|
22
25
|
* Storage-key prefix for durable async-activity records. Matches the base of
|
|
23
26
|
* {@link KEYS.asyncActivity}; the full key appends `<workflowId>:<token>` (and
|
|
@@ -60,6 +63,14 @@ export type PendingAsyncActivityResolution = {
|
|
|
60
63
|
readonly timelineStatus: 'completed' | 'failed';
|
|
61
64
|
readonly timelineOutput: unknown;
|
|
62
65
|
};
|
|
66
|
+
export declare function isPendingAsyncActivityCursor(cursor: string): boolean;
|
|
67
|
+
export declare function isPendingAsyncActivityCursorForWorkflow(cursor: string, workflowId: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Read a bounded page directly from the durable per-workflow async-activity
|
|
70
|
+
* namespace. Pagination advances over raw storage keys, so corrupt or resolved
|
|
71
|
+
* records cannot stall a caller or expand one request beyond `limit + 1` reads.
|
|
72
|
+
*/
|
|
73
|
+
export declare function listPendingAsyncActivities(internals: EngineInternals, workflowId: string, options?: PendingAsyncActivityListOptions): Promise<PendingAsyncActivityPage>;
|
|
63
74
|
/**
|
|
64
75
|
* Derive the durable, deterministic task token for an async activity.
|
|
65
76
|
*
|
|
@@ -2,8 +2,8 @@ import { KEYS, encodeStorageKeyComponent } from "../../storage/interface.js";
|
|
|
2
2
|
import { decode, encode } from "../codec.js";
|
|
3
3
|
import { ActivityAsyncPendingEvent } from "../events.js";
|
|
4
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:";
|
|
5
|
+
const ASYNC_ACTIVITY_TOKEN_PREFIX = "async-act:v1", PENDING_ASYNC_ACTIVITY_CURSOR_PREFIX = "pending-async:v1:";
|
|
6
|
+
export const DEFAULT_PENDING_ASYNC_ACTIVITY_LIMIT = 50, MAX_PENDING_ASYNC_ACTIVITY_LIMIT = 200, MAX_PENDING_ASYNC_ACTIVITY_CURSOR_LENGTH = 8192, ASYNC_ACTIVITY_KEY_PREFIX = "async-act:v1:";
|
|
7
7
|
export function asyncActivityWorkflowPrefix(workflowId) {
|
|
8
8
|
return `${ASYNC_ACTIVITY_KEY_PREFIX}${encodeStorageKeyComponent(workflowId)}:`;
|
|
9
9
|
}
|
|
@@ -13,6 +13,85 @@ function isPersistedAsyncActivity(value) {
|
|
|
13
13
|
const record = value;
|
|
14
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
15
|
}
|
|
16
|
+
function decodePendingAsyncActivityCursor(cursor) {
|
|
17
|
+
if (cursor.length > MAX_PENDING_ASYNC_ACTIVITY_CURSOR_LENGTH || !cursor.startsWith(PENDING_ASYNC_ACTIVITY_CURSOR_PREFIX))
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const suffix = decodeURIComponent(cursor.slice(PENDING_ASYNC_ACTIVITY_CURSOR_PREFIX.length));
|
|
21
|
+
return suffix.length > 0 ? suffix : null;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function isPendingAsyncActivityCursor(cursor) {
|
|
27
|
+
return decodePendingAsyncActivityCursor(cursor) !== null;
|
|
28
|
+
}
|
|
29
|
+
export function isPendingAsyncActivityCursorForWorkflow(cursor, workflowId) {
|
|
30
|
+
const key = decodePendingAsyncActivityCursor(cursor), prefix = asyncActivityWorkflowPrefix(workflowId);
|
|
31
|
+
return key !== null && key.startsWith(prefix) && key.length > prefix.length;
|
|
32
|
+
}
|
|
33
|
+
function encodePendingAsyncActivityCursor(key) {
|
|
34
|
+
return `${PENDING_ASYNC_ACTIVITY_CURSOR_PREFIX}${encodeURIComponent(key)}`;
|
|
35
|
+
}
|
|
36
|
+
function resolvePendingAsyncActivityLimit(limit) {
|
|
37
|
+
const resolved = limit ?? DEFAULT_PENDING_ASYNC_ACTIVITY_LIMIT;
|
|
38
|
+
if (!Number.isSafeInteger(resolved) || resolved < 1 || resolved > MAX_PENDING_ASYNC_ACTIVITY_LIMIT)
|
|
39
|
+
throw RangeError(`Pending async activity limit must be an integer between 1 and ${MAX_PENDING_ASYNC_ACTIVITY_LIMIT}.`);
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
function toPendingAsyncActivityInfo(value, key, workflowId) {
|
|
43
|
+
if (!isPersistedAsyncActivity(value))
|
|
44
|
+
return null;
|
|
45
|
+
if (value.workflowId !== workflowId || key !== KEYS.asyncActivity(workflowId, value.token))
|
|
46
|
+
return null;
|
|
47
|
+
if (!Number.isSafeInteger(value.step) || value.step < 0 || !Number.isSafeInteger(value.attempt) || value.attempt < 1 || !Number.isFinite(value.createdAt))
|
|
48
|
+
return null;
|
|
49
|
+
return {
|
|
50
|
+
token: value.token,
|
|
51
|
+
operationId: value.operationId,
|
|
52
|
+
activityName: value.activityName,
|
|
53
|
+
step: value.step,
|
|
54
|
+
attempt: value.attempt,
|
|
55
|
+
createdAt: value.createdAt
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function resolvePendingAsyncActivityAfterKey(cursor, workflowId) {
|
|
59
|
+
if (cursor === void 0)
|
|
60
|
+
return;
|
|
61
|
+
const key = decodePendingAsyncActivityCursor(cursor);
|
|
62
|
+
if (key === null || !isPendingAsyncActivityCursorForWorkflow(cursor, workflowId))
|
|
63
|
+
throw TypeError("Invalid pending async activity cursor.");
|
|
64
|
+
return key;
|
|
65
|
+
}
|
|
66
|
+
function decodePendingAsyncActivityInfo(bytes, key, workflowId) {
|
|
67
|
+
try {
|
|
68
|
+
return toPendingAsyncActivityInfo(decode(bytes), key, workflowId);
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function pendingAsyncActivityPage(scanned, limit, workflowId) {
|
|
74
|
+
const pageEntries = scanned.slice(0, limit), items = pageEntries.flatMap(([key, bytes]) => {
|
|
75
|
+
const item = decodePendingAsyncActivityInfo(bytes, key, workflowId);
|
|
76
|
+
return item === null ? [] : [item];
|
|
77
|
+
}), cursorKey = pageEntries.at(-1)?.[0];
|
|
78
|
+
return {
|
|
79
|
+
items,
|
|
80
|
+
...scanned.length > limit && cursorKey !== void 0 ? { nextCursor: encodePendingAsyncActivityCursor(cursorKey) } : {}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export async function listPendingAsyncActivities(internals, workflowId, options = {}) {
|
|
84
|
+
const limit = resolvePendingAsyncActivityLimit(options.limit), prefix = asyncActivityWorkflowPrefix(workflowId), afterKey = resolvePendingAsyncActivityAfterKey(options.cursor, workflowId), scanned = [];
|
|
85
|
+
for await (const entry of internals.storage.scan(prefix, {
|
|
86
|
+
limit: limit + 1,
|
|
87
|
+
...afterKey === void 0 ? {} : { gt: afterKey }
|
|
88
|
+
})) {
|
|
89
|
+
scanned.push(entry);
|
|
90
|
+
if (scanned.length >= limit + 1)
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
return pendingAsyncActivityPage(scanned, limit, workflowId);
|
|
94
|
+
}
|
|
16
95
|
function isPersistedOperationOutcome(value) {
|
|
17
96
|
if (typeof value !== "object" || value === null)
|
|
18
97
|
return !1;
|