@lostgradient/weft 0.16.0 → 0.17.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/alerting/alert-manager.d.ts +5 -5
- package/dist/alerting/alert-manager.js +24 -6
- package/dist/alerting/index.d.ts +1 -1
- package/dist/alerting/types.d.ts +17 -13
- package/dist/alerting/types.js +5 -0
- package/dist/core/engine/disposal.js +7 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +3 -1
- package/dist/core/engine/engine-runtime-helpers.js +2 -2
- package/dist/core/engine/errors.d.ts +20 -0
- package/dist/core/engine/errors.js +8 -0
- package/dist/core/engine/index.d.ts +39 -17
- package/dist/core/engine/index.js +81 -9
- package/dist/core/engine/inline-launch-queue.d.ts +6 -2
- package/dist/core/engine/inline-launch-queue.js +41 -6
- package/dist/core/engine/internals.d.ts +2 -0
- package/dist/core/engine/lease-manager.d.ts +3 -2
- package/dist/core/engine/lease-manager.js +7 -3
- package/dist/core/engine/operations-time.js +6 -0
- package/dist/core/execution-strategy.d.ts +8 -0
- package/dist/core/inline-execution-strategy.d.ts +1 -0
- package/dist/core/inline-execution-strategy.js +33 -20
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +1 -0
- package/dist/core/worker-execution-strategy.d.ts +2 -0
- package/dist/core/worker-execution-strategy.js +7 -2
- package/dist/core/worker-turn-watchdog.d.ts +4 -1
- package/dist/core/worker-turn-watchdog.js +9 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -0
- package/dist/indexeddb.js +1 -1
- package/dist/json-schema.js +1 -1
- package/dist/mcp/tools.js +1 -3
- package/dist/server/dashboard-assets.d.ts +12 -1
- package/dist/server/dashboard-assets.js +145 -31
- package/dist/server/operations/aggregate-workflows.js +0 -7
- package/dist/server/operations/async-activity.js +5 -24
- package/dist/server/operations/bulk-cancel-workflows.js +3 -8
- package/dist/server/operations/bulk-delete-workflows.js +3 -8
- package/dist/server/operations/bulk-mutate-workflow-tags.js +3 -8
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -10
- package/dist/server/operations/bulk-operation-helpers.js +0 -6
- package/dist/server/operations/bulk-retry-failed-workflows.js +3 -8
- package/dist/server/operations/bulk-signal-workflows.js +3 -8
- package/dist/server/operations/cancel-schedule.js +1 -3
- package/dist/server/operations/cancel-workflow.js +1 -3
- package/dist/server/operations/create-schedule.js +2 -3
- package/dist/server/operations/fork-workflow.js +2 -3
- package/dist/server/operations/get-checkpoint-at.js +1 -6
- package/dist/server/operations/get-registry.js +1 -7
- package/dist/server/operations/get-retention-overview.js +2 -15
- package/dist/server/operations/get-review.js +2 -15
- package/dist/server/operations/get-schedule.js +2 -8
- package/dist/server/operations/get-stream-chunks.js +2 -6
- package/dist/server/operations/get-system-lease.js +1 -7
- package/dist/server/operations/get-system-metrics.js +0 -4
- package/dist/server/operations/get-task-diagnostics.js +2 -13
- package/dist/server/operations/get-update-result.js +1 -6
- package/dist/server/operations/get-workflow-attributes.js +2 -15
- package/dist/server/operations/get-workflow-events.js +2 -15
- package/dist/server/operations/get-workflow-observability.js +2 -5
- package/dist/server/operations/get-workflow-result.js +0 -7
- package/dist/server/operations/get-workflow-timeline.js +1 -6
- package/dist/server/operations/get-workflow.d.ts +3 -6
- package/dist/server/operations/get-workflow.js +2 -12
- package/dist/server/operations/list-alerts.d.ts +5 -2
- package/dist/server/operations/list-alerts.js +2 -9
- package/dist/server/operations/list-checkpoints.js +1 -6
- package/dist/server/operations/list-reviews.js +0 -7
- package/dist/server/operations/list-schedules.js +3 -8
- package/dist/server/operations/list-task-queues.js +0 -4
- package/dist/server/operations/list-workers.js +0 -4
- package/dist/server/operations/list-workflows.js +0 -7
- package/dist/server/operations/pause-schedule.js +1 -3
- package/dist/server/operations/purge-workflows.js +2 -5
- package/dist/server/operations/query-workflow.js +4 -15
- package/dist/server/operations/replay-workflow.js +2 -6
- package/dist/server/operations/resume-schedule.js +1 -3
- package/dist/server/operations/resume-workflow.js +1 -3
- package/dist/server/operations/set-workflow-attributes.js +3 -15
- package/dist/server/operations/signal-workflow.js +3 -12
- package/dist/server/operations/single-workflow-tag-mutation.js +0 -7
- package/dist/server/operations/start-or-signal-workflow.js +2 -3
- package/dist/server/operations/start-workflow.js +2 -3
- package/dist/server/operations/storage-capabilities.js +1 -3
- package/dist/server/operations/storage.js +7 -13
- package/dist/server/operations/submit-review-decision.js +3 -12
- package/dist/server/operations/suspend-workflow.js +1 -3
- package/dist/server/operations/timeout-workflow.js +1 -3
- package/dist/server/operations/update-schedule.js +1 -3
- package/dist/server/operations/update-workflow.js +2 -3
- package/dist/server/operations/worker-drain.js +0 -8
- package/dist/server/rest-binding.d.ts +3 -2
- package/dist/server/route-model.d.ts +2 -0
- package/dist/server/route-model.js +1 -1
- package/dist/server/runtime/task-reconciliation.d.ts +10 -1
- package/dist/server/runtime/task-reconciliation.js +26 -2
- package/dist/server/serve-internals.js +12 -6
- package/dist/storage/indexeddb.js +28 -48
- package/dist/storage/testing.d.ts +6 -3
- package/dist/storage/testing.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/protocol-schemas.d.ts +2 -2
- package/dist/worker/protocol-schemas.js +2 -2
- package/dist/worker/protocol.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defineOperation } from "../operation-registry.js";
|
|
3
3
|
import { readRestJsonBody } from "../rest-body.js";
|
|
4
|
-
import { isOperationFault
|
|
4
|
+
import { isOperationFault } from "./operation-helpers.js";
|
|
5
5
|
const setWorkflowAttributesInput = z.object({
|
|
6
6
|
workflowId: z.string().min(1),
|
|
7
7
|
attributes: z.unknown().optional()
|
|
@@ -32,17 +32,7 @@ export const setWorkflowAttributesOperation = defineOperation({
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
})
|
|
36
|
-
function shapeSetWorkflowAttributesSuccess(output) {
|
|
37
|
-
return new Response(JSON.stringify(output), {
|
|
38
|
-
status: 200,
|
|
39
|
-
headers: { "Content-Type": "application/json" }
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function shapeSetWorkflowAttributesFault(fault) {
|
|
43
|
-
return shapeRestFault(fault);
|
|
44
|
-
}
|
|
45
|
-
export const setWorkflowAttributesRestBinding = {
|
|
35
|
+
}), setWorkflowAttributesRestBinding = {
|
|
46
36
|
method: "PATCH",
|
|
47
37
|
path: "/v1/workflows/:id/attributes",
|
|
48
38
|
pathParamNames: ["id"],
|
|
@@ -64,7 +54,5 @@ export const setWorkflowAttributesRestBinding = {
|
|
|
64
54
|
attributes: typeof body === "object" ? body.attributes : void 0
|
|
65
55
|
};
|
|
66
56
|
},
|
|
67
|
-
success: { kind: "json", status: 200 }
|
|
68
|
-
shapeSuccess: (output) => shapeSetWorkflowAttributesSuccess(output),
|
|
69
|
-
shapeFault: shapeSetWorkflowAttributesFault
|
|
57
|
+
success: { kind: "json", status: 200 }
|
|
70
58
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { isSignalIdWithinByteLimit } from "../../core/signal-id.js";
|
|
3
3
|
import { readRestJsonBody } from "../rest-body.js";
|
|
4
|
-
import { isOperationFault
|
|
4
|
+
import { isOperationFault } from "./operation-helpers.js";
|
|
5
5
|
import {
|
|
6
6
|
createSingleWorkflowControlOperation,
|
|
7
7
|
extractWorkflowIdFromPath
|
|
@@ -27,14 +27,7 @@ export const signalWorkflowOperation = createSingleWorkflowControlOperation({
|
|
|
27
27
|
await engine.signal(input.workflowId, input.signalName, input.payload, input.signalId === void 0 ? void 0 : { signalId: input.signalId });
|
|
28
28
|
return { ok: !0 };
|
|
29
29
|
}
|
|
30
|
-
})
|
|
31
|
-
function shapeSignalWorkflowSuccess(output) {
|
|
32
|
-
return new Response(JSON.stringify(output), {
|
|
33
|
-
status: 200,
|
|
34
|
-
headers: { "Content-Type": "application/json" }
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
export const signalWorkflowRestBinding = {
|
|
30
|
+
}), signalWorkflowRestBinding = {
|
|
38
31
|
method: "POST",
|
|
39
32
|
path: "/v1/workflows/:id/signal/:name",
|
|
40
33
|
pathParamNames: ["id", "name"],
|
|
@@ -57,7 +50,5 @@ export const signalWorkflowRestBinding = {
|
|
|
57
50
|
...signalId === void 0 ? {} : { signalId }
|
|
58
51
|
};
|
|
59
52
|
},
|
|
60
|
-
success: { kind: "json", status: 200 }
|
|
61
|
-
shapeSuccess: (output) => shapeSignalWorkflowSuccess(output),
|
|
62
|
-
shapeFault: shapeRestFault
|
|
53
|
+
success: { kind: "json", status: 200 }
|
|
63
54
|
};
|
|
@@ -66,16 +66,9 @@ export function createSingleWorkflowTagMutationRestBinding(configuration) {
|
|
|
66
66
|
};
|
|
67
67
|
},
|
|
68
68
|
success: { kind: "json", status: 200 },
|
|
69
|
-
shapeSuccess: shapeSingleWorkflowTagMutationSuccess,
|
|
70
69
|
shapeFault: shapeSingleWorkflowTagMutationFault
|
|
71
70
|
};
|
|
72
71
|
}
|
|
73
|
-
function shapeSingleWorkflowTagMutationSuccess(output) {
|
|
74
|
-
return new Response(JSON.stringify(output), {
|
|
75
|
-
status: 200,
|
|
76
|
-
headers: { "Content-Type": "application/json" }
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
72
|
function shapeSingleWorkflowTagMutationFault(fault) {
|
|
80
73
|
if (fault.code === "Unprocessable")
|
|
81
74
|
return shapeRestFault(fault, { status: 400 });
|
|
@@ -9,7 +9,7 @@ import { runtimeWorkflowEngine } from "../../core/runtime-workflow-engine.js";
|
|
|
9
9
|
import { isSignalIdWithinByteLimit } from "../../core/signal-id.js";
|
|
10
10
|
import { StartWorkflowValidationError } from "../../core/start-workflow-validation.js";
|
|
11
11
|
import { defineOperation } from "../operation-registry.js";
|
|
12
|
-
import { invalidParamsFault
|
|
12
|
+
import { invalidParamsFault } from "./operation-helpers.js";
|
|
13
13
|
import { buildStartOrSignalWorkflowOptions } from "./start-workflow-options.js";
|
|
14
14
|
import {
|
|
15
15
|
extractSharedStartWorkflowRestFields,
|
|
@@ -136,6 +136,5 @@ export const startOrSignalWorkflowOperation = defineOperation({
|
|
|
136
136
|
onTerminalConflict: record.onTerminalConflict
|
|
137
137
|
};
|
|
138
138
|
},
|
|
139
|
-
success: { kind: "json", status: 201 }
|
|
140
|
-
shapeFault: shapeRestFault
|
|
139
|
+
success: { kind: "json", status: 201 }
|
|
141
140
|
};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { runtimeWorkflowEngine } from "../../core/runtime-workflow-engine.js";
|
|
8
8
|
import { StartWorkflowValidationError } from "../../core/start-workflow-validation.js";
|
|
9
9
|
import { defineOperation } from "../operation-registry.js";
|
|
10
|
-
import { invalidParamsFault
|
|
10
|
+
import { invalidParamsFault } from "./operation-helpers.js";
|
|
11
11
|
import { buildSharedStartWorkflowOptions } from "./start-workflow-options.js";
|
|
12
12
|
import {
|
|
13
13
|
extractSharedStartWorkflowRestFields,
|
|
@@ -99,6 +99,5 @@ export const startWorkflowOperation = defineOperation({
|
|
|
99
99
|
extractInput: async (request, _pathParams, context) => {
|
|
100
100
|
return extractSharedStartWorkflowRestFields(await parseStartWorkflowRequestRecord(request, context));
|
|
101
101
|
},
|
|
102
|
-
success: { kind: "json", status: 201 }
|
|
103
|
-
shapeFault: shapeRestFault
|
|
102
|
+
success: { kind: "json", status: 201 }
|
|
104
103
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defineOperation } from "../operation-registry.js";
|
|
3
|
-
import { shapeRestFault } from "./operation-helpers.js";
|
|
4
3
|
const storageCapabilitiesInput = z.object({}), storageCapabilitiesOutput = z.object({
|
|
5
4
|
persistence: z.enum(["ephemeral", "local", "remote"]),
|
|
6
5
|
readAfterWrite: z.enum(["linearizable", "session", "eventual"]),
|
|
@@ -33,6 +32,5 @@ export const storageCapabilitiesOperation = defineOperation({
|
|
|
33
32
|
inputSources: {},
|
|
34
33
|
extractInput: async () => ({}),
|
|
35
34
|
success: { kind: "json", status: 200 },
|
|
36
|
-
shapeSuccess: (output) => Response.json(output)
|
|
37
|
-
shapeFault: shapeRestFault
|
|
35
|
+
shapeSuccess: (output) => Response.json(output)
|
|
38
36
|
};
|
|
@@ -11,7 +11,7 @@ import { raiseFault } from "../operation-catalog.js";
|
|
|
11
11
|
import { defineOperation } from "../operation-registry.js";
|
|
12
12
|
import { isAuthenticated } from "../principal.js";
|
|
13
13
|
import { readRestBodyBounded, readRestJsonBody } from "../rest-body.js";
|
|
14
|
-
import { invalidParamsFault, isOperationFault
|
|
14
|
+
import { invalidParamsFault, isOperationFault } from "./operation-helpers.js";
|
|
15
15
|
const rawStorageAccess = {
|
|
16
16
|
kind: "scoped",
|
|
17
17
|
scopes: { kind: "anyOf", scopes: ["storage:admin"] }
|
|
@@ -283,8 +283,7 @@ export const storageGetOperation = defineOperation({
|
|
|
283
283
|
},
|
|
284
284
|
extractInput: async (_request, pathParams) => ({ key: storageKeyFromPath(pathParams) }),
|
|
285
285
|
success: { kind: "streaming", mediaType: "application/octet-stream" },
|
|
286
|
-
shapeSuccess: (output) => createBinaryResponse(output)
|
|
287
|
-
shapeFault: shapeRestFault
|
|
286
|
+
shapeSuccess: (output) => createBinaryResponse(output)
|
|
288
287
|
}, storagePutRestBinding = {
|
|
289
288
|
method: "PUT",
|
|
290
289
|
path: "/v1/storage/:key",
|
|
@@ -299,8 +298,7 @@ export const storageGetOperation = defineOperation({
|
|
|
299
298
|
value: await readRestBodyBounded(request, context)
|
|
300
299
|
}),
|
|
301
300
|
success: { kind: "empty", status: 204 },
|
|
302
|
-
shapeSuccess: createNoContentResponse
|
|
303
|
-
shapeFault: shapeRestFault
|
|
301
|
+
shapeSuccess: createNoContentResponse
|
|
304
302
|
}, storageDeleteRestBinding = {
|
|
305
303
|
method: "DELETE",
|
|
306
304
|
path: "/v1/storage/:key",
|
|
@@ -311,8 +309,7 @@ export const storageGetOperation = defineOperation({
|
|
|
311
309
|
},
|
|
312
310
|
extractInput: async (_request, pathParams) => ({ key: storageKeyFromPath(pathParams) }),
|
|
313
311
|
success: { kind: "empty", status: 204 },
|
|
314
|
-
shapeSuccess: createNoContentResponse
|
|
315
|
-
shapeFault: shapeRestFault
|
|
312
|
+
shapeSuccess: createNoContentResponse
|
|
316
313
|
}, storageScanRestBinding = {
|
|
317
314
|
method: "GET",
|
|
318
315
|
path: "/v1/storage",
|
|
@@ -329,8 +326,7 @@ export const storageGetOperation = defineOperation({
|
|
|
329
326
|
},
|
|
330
327
|
extractInput: async (request) => extractStorageScanInput(request),
|
|
331
328
|
success: { kind: "streaming", mediaType: "application/x-ndjson" },
|
|
332
|
-
shapeSuccess: (output) => createNdjsonResponse(output)
|
|
333
|
-
shapeFault: shapeRestFault
|
|
329
|
+
shapeSuccess: (output) => createNdjsonResponse(output)
|
|
334
330
|
}, storageBatchRestBinding = {
|
|
335
331
|
method: "POST",
|
|
336
332
|
path: "/v1/storage/-/batch",
|
|
@@ -341,8 +337,7 @@ export const storageGetOperation = defineOperation({
|
|
|
341
337
|
},
|
|
342
338
|
extractInput: async (request, _pathParams, context) => readJsonRequestBody(request, context),
|
|
343
339
|
success: { kind: "empty", status: 204 },
|
|
344
|
-
shapeSuccess: createNoContentResponse
|
|
345
|
-
shapeFault: shapeRestFault
|
|
340
|
+
shapeSuccess: createNoContentResponse
|
|
346
341
|
}, storageConditionalBatchRestBinding = {
|
|
347
342
|
method: "POST",
|
|
348
343
|
path: "/v1/storage/-/conditional-batch",
|
|
@@ -354,6 +349,5 @@ export const storageGetOperation = defineOperation({
|
|
|
354
349
|
},
|
|
355
350
|
extractInput: async (request, _pathParams, context) => readJsonRequestBody(request, context),
|
|
356
351
|
success: { kind: "json", status: 200 },
|
|
357
|
-
shapeSuccess: (output) => Response.json(output)
|
|
358
|
-
shapeFault: shapeRestFault
|
|
352
|
+
shapeSuccess: (output) => Response.json(output)
|
|
359
353
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defineOperation } from "../operation-registry.js";
|
|
3
3
|
import { readRestJsonBody } from "../rest-body.js";
|
|
4
|
-
import { isOperationFault
|
|
4
|
+
import { isOperationFault } from "./operation-helpers.js";
|
|
5
5
|
const VALID_DECISIONS = [
|
|
6
6
|
"approved",
|
|
7
7
|
"rejected",
|
|
@@ -92,14 +92,7 @@ export const submitReviewDecisionOperation = defineOperation({
|
|
|
92
92
|
mapReviewDecisionError(error, input.reviewId);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
})
|
|
96
|
-
function shapeSubmitReviewDecisionSuccess(output) {
|
|
97
|
-
return new Response(JSON.stringify(output), {
|
|
98
|
-
status: 200,
|
|
99
|
-
headers: { "Content-Type": "application/json" }
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
export const submitReviewDecisionRestBinding = {
|
|
95
|
+
}), submitReviewDecisionRestBinding = {
|
|
103
96
|
method: "POST",
|
|
104
97
|
path: "/v1/reviews/:reviewId/decision",
|
|
105
98
|
pathParamNames: ["reviewId"],
|
|
@@ -127,7 +120,5 @@ export const submitReviewDecisionRestBinding = {
|
|
|
127
120
|
workflowId: record.workflowId
|
|
128
121
|
};
|
|
129
122
|
},
|
|
130
|
-
success: { kind: "json", status: 200 }
|
|
131
|
-
shapeSuccess: (output) => shapeSubmitReviewDecisionSuccess(output),
|
|
132
|
-
shapeFault: shapeRestFault
|
|
123
|
+
success: { kind: "json", status: 200 }
|
|
133
124
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { WorkflowSuspendNotSupportedError } from "../../core/engine/errors.js";
|
|
3
|
-
import { shapeRestFault } from "./operation-helpers.js";
|
|
4
3
|
import {
|
|
5
4
|
createSingleWorkflowControlOperation,
|
|
6
5
|
extractWorkflowIdFromPath
|
|
@@ -31,6 +30,5 @@ export const suspendWorkflowOperation = createSingleWorkflowControlOperation({
|
|
|
31
30
|
workflowId: { kind: "path", pathParam: "id" }
|
|
32
31
|
},
|
|
33
32
|
extractInput: async (_request, pathParams) => extractWorkflowIdFromPath(pathParams),
|
|
34
|
-
success: { kind: "empty", status: 204 }
|
|
35
|
-
shapeFault: shapeRestFault
|
|
33
|
+
success: { kind: "empty", status: 204 }
|
|
36
34
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { shapeRestFault } from "./operation-helpers.js";
|
|
3
2
|
import {
|
|
4
3
|
createSingleWorkflowControlOperation,
|
|
5
4
|
extractWorkflowIdFromPath
|
|
@@ -29,6 +28,5 @@ export const timeoutWorkflowOperation = createSingleWorkflowControlOperation({
|
|
|
29
28
|
workflowId: { kind: "path", pathParam: "id" }
|
|
30
29
|
},
|
|
31
30
|
extractInput: async (_request, pathParams) => extractWorkflowIdFromPath(pathParams),
|
|
32
|
-
success: { kind: "empty", status: 204 }
|
|
33
|
-
shapeFault: shapeRestFault
|
|
31
|
+
success: { kind: "empty", status: 204 }
|
|
34
32
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defineOperation } from "../operation-registry.js";
|
|
3
|
-
import { shapeRestFault } from "./operation-helpers.js";
|
|
4
3
|
import {
|
|
5
4
|
mapScheduleErrorToFault,
|
|
6
5
|
validateScheduleInputCadence,
|
|
@@ -62,6 +61,5 @@ export const updateScheduleOperation = defineOperation({
|
|
|
62
61
|
...extractSharedScheduleRestFields(record)
|
|
63
62
|
};
|
|
64
63
|
},
|
|
65
|
-
success: { kind: "empty", status: 204 }
|
|
66
|
-
shapeFault: shapeRestFault
|
|
64
|
+
success: { kind: "empty", status: 204 }
|
|
67
65
|
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../../core/updates.js";
|
|
7
7
|
import { defineOperation } from "../operation-registry.js";
|
|
8
8
|
import { readRestJsonBody } from "../rest-body.js";
|
|
9
|
-
import { isOperationFault
|
|
9
|
+
import { isOperationFault } from "./operation-helpers.js";
|
|
10
10
|
const DEFAULT_UPDATE_TIMEOUT_MS = 30000, updateWorkflowInput = z.object({
|
|
11
11
|
workflowId: z.string().min(1),
|
|
12
12
|
updateName: z.string().min(1),
|
|
@@ -108,6 +108,5 @@ export const updateWorkflowOperation = defineOperation({
|
|
|
108
108
|
...idempotencyKey !== void 0 ? { idempotencyKey } : {}
|
|
109
109
|
};
|
|
110
110
|
},
|
|
111
|
-
success: { kind: "json", status: 200 }
|
|
112
|
-
shapeFault: shapeRestFault
|
|
111
|
+
success: { kind: "json", status: 200 }
|
|
113
112
|
};
|
|
@@ -159,7 +159,6 @@ function createWorkerDrainRestBinding(method, operationName) {
|
|
|
159
159
|
...method === "POST" ? await readDrainBody(request, context) : {}
|
|
160
160
|
}),
|
|
161
161
|
success: { kind: "json", status: 200 },
|
|
162
|
-
shapeSuccess: shapeDrainSuccess,
|
|
163
162
|
shapeFault: shapeOperationFaultAsJson
|
|
164
163
|
};
|
|
165
164
|
}
|
|
@@ -178,16 +177,9 @@ function createDeploymentDrainRestBinding(method, operationName) {
|
|
|
178
177
|
...method === "POST" ? await readDrainBody(request, context) : {}
|
|
179
178
|
}),
|
|
180
179
|
success: { kind: "json", status: 200 },
|
|
181
|
-
shapeSuccess: shapeDrainSuccess,
|
|
182
180
|
shapeFault: shapeOperationFaultAsJson
|
|
183
181
|
};
|
|
184
182
|
}
|
|
185
|
-
function shapeDrainSuccess(output) {
|
|
186
|
-
return new Response(JSON.stringify(output), {
|
|
187
|
-
status: 200,
|
|
188
|
-
headers: { "Content-Type": "application/json" }
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
183
|
async function readDrainBody(request, context) {
|
|
192
184
|
const text = await readRestTextBody(request, context);
|
|
193
185
|
if (text.trim().length === 0)
|
|
@@ -98,8 +98,9 @@ export type RestBinding<Input, Output> = {
|
|
|
98
98
|
readonly success: ResponseShape;
|
|
99
99
|
/**
|
|
100
100
|
* Optional override for response construction. When absent, transport
|
|
101
|
-
* adapters default to `
|
|
102
|
-
*
|
|
101
|
+
* adapters default to `jsonResponse(output, success.status)`, which emits
|
|
102
|
+
* `JSON.stringify(output)` with `Content-Type: application/json` (or
|
|
103
|
+
* `new Response(null, { status })` for `empty`). Provide this
|
|
103
104
|
* when the wire representation differs from `output` verbatim.
|
|
104
105
|
*
|
|
105
106
|
* Receives the original `Request` so REST-only response shaping —
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
* RFC 9264 / discovery convention.
|
|
35
35
|
*/
|
|
36
36
|
export declare const API_PREFIX = "/api";
|
|
37
|
+
/** Root-relative namespace for the functional REST and WebSocket API. */
|
|
38
|
+
export declare const ROOT_API_PREFIX = "/v1";
|
|
37
39
|
/**
|
|
38
40
|
* Map a canonical, root-relative server path to its external (`/api`-prefixed)
|
|
39
41
|
* form for emission in specs and discovery documents.
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { ServeOptions } from '../index.ts';
|
|
2
2
|
import type { InflightRecord, TaskRequeueReason } from '../task-state.ts';
|
|
3
3
|
import type { ServerContext } from './context.ts';
|
|
4
|
+
interface ManualTaskReconciliationForTesting {
|
|
5
|
+
readonly options: ServeOptions;
|
|
6
|
+
scanAt(operationId: string, trackedDeadline: number, now: number): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
/** @internal Restricts manual reconciliation to explicitly marked test options. */
|
|
9
|
+
export declare function useManualTaskReconciliationForTesting(options: ServeOptions): ManualTaskReconciliationForTesting;
|
|
10
|
+
/** @internal Installs the narrow one-shot test controller before a server starts. */
|
|
11
|
+
export declare function consumeManualTaskReconciliationForTesting(options: ServeOptions, context: ServerContext, cleanupWorkflowIndex: (operationId: string) => void): boolean;
|
|
4
12
|
/**
|
|
5
13
|
* Given a persisted inflight record, either permanently fail the task (if
|
|
6
14
|
* retry attempts are exhausted) or transition it back to queued and
|
|
@@ -13,5 +21,6 @@ export declare function reassignOrExpireTask(context: ServerContext, options: Se
|
|
|
13
21
|
* their tasks. Only touches storage for the specific operations whose
|
|
14
22
|
* deadlines have actually passed — no full `op:inflight:*` scan.
|
|
15
23
|
*/
|
|
16
|
-
export declare function scanExpiredTasks(context: ServerContext, options: ServeOptions, cleanupWorkflowIndex: (operationId: string) => void): Promise<void>;
|
|
24
|
+
export declare function scanExpiredTasks(context: ServerContext, options: ServeOptions, cleanupWorkflowIndex: (operationId: string) => void, now?: number): Promise<void>;
|
|
17
25
|
export declare function reconcileOrphanedRecords(context: ServerContext, options: ServeOptions, cleanupWorkflowIndex: (operationId: string) => void): Promise<void>;
|
|
26
|
+
export {};
|
|
@@ -17,6 +17,30 @@ import {
|
|
|
17
17
|
recordWorkerCapacitySaturationMetric
|
|
18
18
|
} from "./task-metrics.js";
|
|
19
19
|
import { isInflightRecord } from "./websocket-worker.js";
|
|
20
|
+
const manualTaskReconciliationRegistrations = new WeakMap;
|
|
21
|
+
export function useManualTaskReconciliationForTesting(options) {
|
|
22
|
+
const registration = {};
|
|
23
|
+
manualTaskReconciliationRegistrations.set(options, registration);
|
|
24
|
+
return {
|
|
25
|
+
options,
|
|
26
|
+
scanAt(operationId, trackedDeadline, now) {
|
|
27
|
+
if (registration.scanAt === void 0)
|
|
28
|
+
throw Error("Manual task reconciliation requires a running test server");
|
|
29
|
+
return registration.scanAt(operationId, trackedDeadline, now);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function consumeManualTaskReconciliationForTesting(options, context, cleanupWorkflowIndex) {
|
|
34
|
+
const registration = manualTaskReconciliationRegistrations.get(options);
|
|
35
|
+
manualTaskReconciliationRegistrations.delete(options);
|
|
36
|
+
if (registration === void 0)
|
|
37
|
+
return !1;
|
|
38
|
+
registration.scanAt = async (operationId, trackedDeadline, now) => {
|
|
39
|
+
context.deadlineTracker.add({ operationId, deadline: trackedDeadline });
|
|
40
|
+
await scanExpiredTasks(context, options, cleanupWorkflowIndex, now);
|
|
41
|
+
};
|
|
42
|
+
return !0;
|
|
43
|
+
}
|
|
20
44
|
export async function reassignOrExpireTask(context, options, operationId, record, reason = "visibility-timeout") {
|
|
21
45
|
const nextAttempt = (record.attempt ?? 1) + 1, policy = record.retryPolicy, nextRetryCount = Math.max(record.retryCount ?? 0, nextAttempt - 1);
|
|
22
46
|
if (hasExceededMaxAttempts(policy, nextAttempt)) {
|
|
@@ -82,12 +106,12 @@ function scheduleTaskRedispatch(context, options, taskDispatch, policy) {
|
|
|
82
106
|
} else
|
|
83
107
|
dispatchTaskImpl(context, options, taskDispatch).catch((err) => console.error(`[weft] Redispatch failed for "${taskDispatch.operationId}":`, err));
|
|
84
108
|
}
|
|
85
|
-
export async function scanExpiredTasks(context, options, cleanupWorkflowIndex) {
|
|
109
|
+
export async function scanExpiredTasks(context, options, cleanupWorkflowIndex, now = Date.now()) {
|
|
86
110
|
if (context.scanRunning)
|
|
87
111
|
return;
|
|
88
112
|
context.scanRunning = !0;
|
|
89
113
|
try {
|
|
90
|
-
const
|
|
114
|
+
const expired = context.deadlineTracker.drainExpired(now);
|
|
91
115
|
for (const { operationId, deadline } of expired) {
|
|
92
116
|
if (context.processingOperations.has(operationId)) {
|
|
93
117
|
context.deadlineTracker.add({ operationId, deadline });
|
|
@@ -25,7 +25,11 @@ import {
|
|
|
25
25
|
registerWorkflowEventLifecycle
|
|
26
26
|
} from "./runtime/event-broadcasting.js";
|
|
27
27
|
import { shutdownAllWorkers } from "./runtime/shutdown.js";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
consumeManualTaskReconciliationForTesting as consumeManual,
|
|
30
|
+
reconcileOrphanedRecords,
|
|
31
|
+
scanExpiredTasks
|
|
32
|
+
} from "./runtime/task-reconciliation.js";
|
|
29
33
|
import { DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW } from "./runtime/websocket-stream.js";
|
|
30
34
|
import { isInflightRecord, withRetry } from "./runtime/websocket-worker.js";
|
|
31
35
|
import { TaskQueue } from "./task-queue.js";
|
|
@@ -166,14 +170,16 @@ export function registerStackDisposers(stack, context, options, broadcastingHand
|
|
|
166
170
|
stack.defer(() => context.mcpSessionManager[Symbol.asyncDispose]());
|
|
167
171
|
stack.defer(registerWorkflowEventLifecycle(options.engine, context, broadcastingHandle));
|
|
168
172
|
stack.defer(() => shutdownAllWorkers(context, options.workerShutdownTimeoutMs === void 0 ? void 0 : { timeoutMs: options.workerShutdownTimeoutMs, stopWaitingWhenIdle: !0 }));
|
|
169
|
-
const visibilityPollHandle = setInterval(() => {
|
|
173
|
+
const schedulesTaskReconciliation = !consumeManual(options, context, onOperationCleanup), visibilityPollHandle = schedulesTaskReconciliation ? setInterval(() => {
|
|
170
174
|
scanExpiredTasks(context, options, onOperationCleanup);
|
|
171
|
-
}, context.visibilityPollMs), reconciliationIntervalMs = context.visibilityPollMs * RECONCILIATION_MULTIPLIER, reconciliationHandle = setInterval(() => {
|
|
175
|
+
}, context.visibilityPollMs) : void 0, reconciliationIntervalMs = context.visibilityPollMs * RECONCILIATION_MULTIPLIER, reconciliationHandle = schedulesTaskReconciliation ? setInterval(() => {
|
|
172
176
|
reconcileOrphanedRecords(context, options, onOperationCleanup);
|
|
173
|
-
}, reconciliationIntervalMs);
|
|
177
|
+
}, reconciliationIntervalMs) : void 0;
|
|
174
178
|
stack.defer(() => {
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
if (visibilityPollHandle !== void 0)
|
|
180
|
+
clearInterval(visibilityPollHandle);
|
|
181
|
+
if (reconciliationHandle !== void 0)
|
|
182
|
+
clearInterval(reconciliationHandle);
|
|
177
183
|
context.deadlineTracker.clear();
|
|
178
184
|
for (const timer of context.pendingTimers)
|
|
179
185
|
clearTimeout(timer);
|
|
@@ -74,6 +74,30 @@ function createCursorRequestAwaiter(request, transaction) {
|
|
|
74
74
|
});
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
async function* iterateCursor(database, keyRangeFactory, prefix, options, openCursor, project) {
|
|
78
|
+
const { limit, reverse } = options, prefixEnd = resolvePrefixRangeEnd(prefix), range = keyRangeFactory.bound(prefix, prefixEnd, !1, !0), direction = reverse ? "prev" : "next", transaction = database.transaction(STORE_NAME, "readonly"), store = transaction.objectStore(STORE_NAME), request = openCursor(store, range, direction), nextCursor = createCursorRequestAwaiter(request, transaction);
|
|
79
|
+
let count = 0, completed = !1;
|
|
80
|
+
try {
|
|
81
|
+
let cursor = await nextCursor();
|
|
82
|
+
while (cursor) {
|
|
83
|
+
if (limit !== void 0 && count >= limit)
|
|
84
|
+
break;
|
|
85
|
+
const key = cursor.key;
|
|
86
|
+
if (matchesScanOptions(key, options)) {
|
|
87
|
+
yield project(cursor);
|
|
88
|
+
count++;
|
|
89
|
+
}
|
|
90
|
+
cursor.continue();
|
|
91
|
+
cursor = await nextCursor();
|
|
92
|
+
}
|
|
93
|
+
completed = !0;
|
|
94
|
+
} finally {
|
|
95
|
+
if (!completed)
|
|
96
|
+
try {
|
|
97
|
+
transaction.abort();
|
|
98
|
+
} catch {}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
77
101
|
|
|
78
102
|
export class IndexedDBStorage {
|
|
79
103
|
#databaseName;
|
|
@@ -168,30 +192,8 @@ export class IndexedDBStorage {
|
|
|
168
192
|
});
|
|
169
193
|
}
|
|
170
194
|
async* scan(prefix, options = {}) {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
const nextCursor = createCursorRequestAwaiter(request, transaction);
|
|
174
|
-
let completed = !1;
|
|
175
|
-
try {
|
|
176
|
-
let cursor = await nextCursor();
|
|
177
|
-
while (cursor) {
|
|
178
|
-
if (limit !== void 0 && count >= limit)
|
|
179
|
-
break;
|
|
180
|
-
const key = cursor.key;
|
|
181
|
-
if (matchesScanOptions(key, options)) {
|
|
182
|
-
yield [key, new Uint8Array(cursor.value)];
|
|
183
|
-
count++;
|
|
184
|
-
}
|
|
185
|
-
cursor.continue();
|
|
186
|
-
cursor = await nextCursor();
|
|
187
|
-
}
|
|
188
|
-
completed = !0;
|
|
189
|
-
} finally {
|
|
190
|
-
if (!completed)
|
|
191
|
-
try {
|
|
192
|
-
transaction.abort();
|
|
193
|
-
} catch {}
|
|
194
|
-
}
|
|
195
|
+
const database = await this.#databasePromise;
|
|
196
|
+
yield* iterateCursor(database, this.#runtime.IDBKeyRange, prefix, options, (store, range, direction) => store.openCursor(range, direction), (cursor) => [cursor.key, new Uint8Array(cursor.value)]);
|
|
195
197
|
}
|
|
196
198
|
async batch(operations) {
|
|
197
199
|
assertStorageBatchOperationCount("batch operations", operations.length);
|
|
@@ -270,30 +272,8 @@ export class IndexedDBStorage {
|
|
|
270
272
|
});
|
|
271
273
|
}
|
|
272
274
|
async* keys(prefix, options = {}) {
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
const nextCursor = createCursorRequestAwaiter(request, transaction);
|
|
276
|
-
let completed = !1;
|
|
277
|
-
try {
|
|
278
|
-
let cursor = await nextCursor();
|
|
279
|
-
while (cursor) {
|
|
280
|
-
if (limit !== void 0 && count >= limit)
|
|
281
|
-
break;
|
|
282
|
-
const key = cursor.key;
|
|
283
|
-
if (matchesScanOptions(key, options)) {
|
|
284
|
-
yield key;
|
|
285
|
-
count++;
|
|
286
|
-
}
|
|
287
|
-
cursor.continue();
|
|
288
|
-
cursor = await nextCursor();
|
|
289
|
-
}
|
|
290
|
-
completed = !0;
|
|
291
|
-
} finally {
|
|
292
|
-
if (!completed)
|
|
293
|
-
try {
|
|
294
|
-
transaction.abort();
|
|
295
|
-
} catch {}
|
|
296
|
-
}
|
|
275
|
+
const database = await this.#databasePromise;
|
|
276
|
+
yield* iterateCursor(database, this.#runtime.IDBKeyRange, prefix, options, (store, range, direction) => store.openKeyCursor(range, direction), (cursor) => cursor.key);
|
|
297
277
|
}
|
|
298
278
|
async count(prefix) {
|
|
299
279
|
const database = await this.#databasePromise, prefixEnd = resolvePrefixRangeEnd(prefix), store = database.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME);
|
|
@@ -70,6 +70,8 @@ export type ConcurrentConditionalBatchConformanceOptions = {
|
|
|
70
70
|
export type BinaryAndLargeScanConformanceOptions = {
|
|
71
71
|
/** Construct a fresh, empty adapter for each conformance case. */
|
|
72
72
|
readonly create: () => Storage | Promise<Storage>;
|
|
73
|
+
/** Optional timeout for adapters whose local large-scan test needs more time. */
|
|
74
|
+
readonly largeScanTimeoutMs?: number;
|
|
73
75
|
};
|
|
74
76
|
/**
|
|
75
77
|
* Construct a fresh, empty adapter for each basic-contract case.
|
|
@@ -151,9 +153,10 @@ export declare function runStorageCapabilityConformance(name: string, options: C
|
|
|
151
153
|
*/
|
|
152
154
|
export declare function runConcurrentConditionalBatchConformance(name: string, options: ConcurrentConditionalBatchConformanceOptions): void;
|
|
153
155
|
/**
|
|
154
|
-
* Register the basic key/value and scan contract that every storage
|
|
155
|
-
* must satisfy: get, put, overwrite, delete
|
|
156
|
-
*
|
|
156
|
+
* Register the complete basic key/value and scan contract that every storage
|
|
157
|
+
* adapter must satisfy: get, put, overwrite, delete (including missing keys),
|
|
158
|
+
* prefix scans, limits, reverse ordering, exclusive and inclusive range
|
|
159
|
+
* bounds, no-match scans, empty-prefix scans, and put/delete batches.
|
|
157
160
|
*
|
|
158
161
|
* @example
|
|
159
162
|
* ```ts
|