@lostgradient/weft 0.23.1 → 0.24.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 +72 -4
- package/dist/cli/codegen-emit-dedup.d.ts +81 -0
- package/dist/cli/codegen-emit-dedup.js +45 -0
- package/dist/cli/codegen-emit-registry.d.ts +90 -0
- package/dist/cli/codegen-emit-registry.js +50 -0
- package/dist/cli/codegen-emit.d.ts +26 -39
- package/dist/cli/codegen-emit.js +4 -27
- package/dist/cli/codegen-validate.d.ts +49 -0
- package/dist/cli/codegen-validate.js +186 -0
- package/dist/cli/codegen.js +6 -87
- package/dist/cli/generated/operation-catalog.snapshot.json +287 -3
- package/dist/cli/generated/operation-client.generated.d.ts +324 -10
- package/dist/cli/generated/operation-client.generated.js +12 -0
- package/dist/cli/output.js +1 -1
- package/dist/cli/storage-factory.js +2 -0
- package/dist/cli/workflow-commands.js +2 -0
- package/dist/cli-main.js +1 -1
- package/dist/core/application-payload-digest.d.ts +42 -0
- package/dist/core/application-payload-digest.js +76 -0
- package/dist/core/application-primitive-abort.d.ts +50 -0
- package/dist/core/application-primitive-abort.js +40 -0
- package/dist/core/application-primitive-attempt-registry.d.ts +74 -0
- package/dist/core/application-primitive-attempt-registry.js +73 -0
- package/dist/core/application-primitive-codec.d.ts +36 -0
- package/dist/core/application-primitive-codec.js +56 -0
- package/dist/core/application-primitive-commit.d.ts +67 -0
- package/dist/core/application-primitive-commit.js +66 -0
- package/dist/core/application-primitive-guards.d.ts +62 -0
- package/dist/core/application-primitive-guards.js +89 -0
- package/dist/core/application-primitive-payload.d.ts +29 -0
- package/dist/core/application-primitive-payload.js +65 -0
- package/dist/core/application-primitive-timing.d.ts +18 -0
- package/dist/core/application-primitive-timing.js +22 -0
- package/dist/core/atomic-state.js +2 -0
- package/dist/core/catalog/codec.d.ts +40 -0
- package/dist/core/catalog/codec.js +45 -0
- package/dist/core/catalog/errors.d.ts +104 -0
- package/dist/core/catalog/errors.js +41 -0
- package/dist/core/catalog/index.d.ts +25 -0
- package/dist/core/catalog/index.js +15 -0
- package/dist/core/catalog/reference-counts.d.ts +105 -0
- package/dist/core/catalog/reference-counts.js +28 -0
- package/dist/core/catalog/removal.d.ts +52 -0
- package/dist/core/catalog/removal.js +14 -0
- package/dist/core/catalog/storage-io.d.ts +78 -0
- package/dist/core/catalog/storage-io.js +106 -0
- package/dist/core/catalog/types.d.ts +108 -0
- package/dist/core/catalog/types.js +0 -0
- package/dist/core/catalog/workflow-catalog.d.ts +165 -0
- package/dist/core/catalog/workflow-catalog.js +198 -0
- package/dist/core/compare-codepoint.d.ts +13 -0
- package/dist/core/compare-codepoint.js +7 -0
- package/dist/core/compression.js +2 -0
- package/dist/core/context/attributes.d.ts +1 -1
- package/dist/core/context/durable-operations.d.ts +2 -2
- package/dist/core/context/index.js +5 -3
- package/dist/core/context/state-namespace.d.ts +1 -1
- package/dist/core/contract/build.d.ts +64 -0
- package/dist/core/contract/build.js +99 -0
- package/dist/core/contract/compatibility.d.ts +187 -0
- package/dist/core/contract/compatibility.js +37 -0
- package/dist/core/contract/failure.d.ts +64 -0
- package/dist/core/contract/failure.js +4 -0
- package/dist/core/contract/hash.d.ts +92 -0
- package/dist/core/contract/hash.js +34 -0
- package/dist/core/contract/index.d.ts +21 -0
- package/dist/core/contract/index.js +22 -0
- package/dist/core/contract/limits.d.ts +74 -0
- package/dist/core/contract/limits.js +1 -0
- package/dist/core/contract/manifest-parse-schema.d.ts +37 -0
- package/dist/core/contract/manifest-parse-schema.js +106 -0
- package/dist/core/contract/manifest-parse.d.ts +76 -0
- package/dist/core/contract/manifest-parse.js +189 -0
- package/dist/core/contract/manifest.d.ts +56 -0
- package/dist/core/contract/manifest.js +31 -0
- package/dist/core/contract/normalize.d.ts +97 -0
- package/dist/core/contract/normalize.js +127 -0
- package/dist/core/contract/revision.d.ts +29 -0
- package/dist/core/contract/revision.js +5 -0
- package/dist/core/contract/types.d.ts +274 -0
- package/dist/core/contract/types.js +1 -0
- package/dist/core/engine/catalog-activation.d.ts +40 -0
- package/dist/core/engine/catalog-activation.js +17 -0
- package/dist/core/engine/catalog-events.d.ts +36 -0
- package/dist/core/engine/catalog-events.js +15 -0
- package/dist/core/engine/catalog-readiness.d.ts +49 -0
- package/dist/core/engine/catalog-readiness.js +59 -0
- package/dist/core/engine/catalog-removal.d.ts +132 -0
- package/dist/core/engine/catalog-removal.js +70 -0
- package/dist/core/engine/construction.d.ts +1 -1
- package/dist/core/engine/construction.js +4 -2
- package/dist/core/engine/disposal.js +9 -0
- package/dist/core/engine/engine-workflows-namespace.d.ts +130 -0
- package/dist/core/engine/engine-workflows-namespace.js +49 -0
- package/dist/core/engine/finalizer-metadata.d.ts +22 -0
- package/dist/core/engine/finalizer-metadata.js +12 -0
- package/dist/core/engine/handle-result.js +2 -0
- package/dist/core/engine/index.d.ts +83 -0
- package/dist/core/engine/index.js +61 -0
- package/dist/core/engine/internals.d.ts +44 -1
- package/dist/core/engine/internals.js +6 -0
- package/dist/core/engine/lifecycle/start.js +3 -0
- package/dist/core/engine/registration.d.ts +76 -0
- package/dist/core/engine/registration.js +12 -6
- package/dist/core/engine/source-registration.d.ts +42 -0
- package/dist/core/engine/source-registration.js +36 -0
- package/dist/core/engine/source-resolution.d.ts +85 -0
- package/dist/core/engine/source-resolution.js +119 -0
- package/dist/core/engine/validation.js +2 -2
- package/dist/core/events/catalog-events.d.ts +117 -0
- package/dist/core/events/catalog-events.js +62 -0
- package/dist/core/events/event-map.d.ts +6 -0
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/mailbox-admission.d.ts +26 -0
- package/dist/core/mailbox-admission.js +130 -0
- package/dist/core/mailbox-claims.d.ts +251 -0
- package/dist/core/mailbox-claims.js +0 -0
- package/dist/core/mailbox-codec.d.ts +32 -0
- package/dist/core/mailbox-codec.js +221 -0
- package/dist/core/mailbox-contract.d.ts +290 -0
- package/dist/core/mailbox-contract.js +0 -0
- package/dist/core/mailbox-delivery.d.ts +37 -0
- package/dist/core/mailbox-delivery.js +193 -0
- package/dist/core/mailbox-guards.d.ts +78 -0
- package/dist/core/mailbox-guards.js +58 -0
- package/dist/core/mailbox-index-codec.d.ts +41 -0
- package/dist/core/mailbox-index-codec.js +71 -0
- package/dist/core/mailbox-internals.d.ts +156 -0
- package/dist/core/mailbox-internals.js +154 -0
- package/dist/core/mailbox-maintenance.d.ts +29 -0
- package/dist/core/mailbox-maintenance.js +196 -0
- package/dist/core/mailbox-settlement.d.ts +69 -0
- package/dist/core/mailbox-settlement.js +206 -0
- package/dist/core/mailbox-storage.d.ts +117 -0
- package/dist/core/mailbox-storage.js +115 -0
- package/dist/core/mailbox-transition-helpers.d.ts +70 -0
- package/dist/core/mailbox-transition-helpers.js +43 -0
- package/dist/core/mailbox-transitions-recovery.d.ts +28 -0
- package/dist/core/mailbox-transitions-recovery.js +64 -0
- package/dist/core/mailbox-transitions.d.ts +138 -0
- package/dist/core/mailbox-transitions.js +180 -0
- package/dist/core/mailbox-types.d.ts +406 -0
- package/dist/core/mailbox-types.js +16 -0
- package/dist/core/mailbox-validation.d.ts +65 -0
- package/dist/core/mailbox-validation.js +73 -0
- package/dist/core/mailbox-waits.d.ts +50 -0
- package/dist/core/mailbox-waits.js +97 -0
- package/dist/core/mailbox.d.ts +163 -0
- package/dist/core/mailbox.js +211 -0
- package/dist/core/outbox-claims.d.ts +307 -0
- package/dist/core/outbox-claims.js +0 -0
- package/dist/core/outbox-codec.d.ts +24 -0
- package/dist/core/outbox-codec.js +257 -0
- package/dist/core/outbox-contract.d.ts +346 -0
- package/dist/core/outbox-contract.js +0 -0
- package/dist/core/outbox-delivery.d.ts +34 -0
- package/dist/core/outbox-delivery.js +149 -0
- package/dist/core/outbox-drain.d.ts +29 -0
- package/dist/core/outbox-drain.js +158 -0
- package/dist/core/outbox-enqueue.d.ts +24 -0
- package/dist/core/outbox-enqueue.js +115 -0
- package/dist/core/outbox-guards.d.ts +76 -0
- package/dist/core/outbox-guards.js +60 -0
- package/dist/core/outbox-index-codec.d.ts +33 -0
- package/dist/core/outbox-index-codec.js +71 -0
- package/dist/core/outbox-internals.d.ts +99 -0
- package/dist/core/outbox-internals.js +159 -0
- package/dist/core/outbox-listing.d.ts +12 -0
- package/dist/core/outbox-listing.js +38 -0
- package/dist/core/outbox-maintenance.d.ts +28 -0
- package/dist/core/outbox-maintenance.js +191 -0
- package/dist/core/outbox-operations.d.ts +18 -0
- package/dist/core/outbox-operations.js +46 -0
- package/dist/core/outbox-runner.d.ts +30 -0
- package/dist/core/outbox-runner.js +217 -0
- package/dist/core/outbox-settlement.d.ts +57 -0
- package/dist/core/outbox-settlement.js +183 -0
- package/dist/core/outbox-storage.d.ts +107 -0
- package/dist/core/outbox-storage.js +127 -0
- package/dist/core/outbox-transition-helpers.d.ts +83 -0
- package/dist/core/outbox-transition-helpers.js +63 -0
- package/dist/core/outbox-transitions-recovery.d.ts +30 -0
- package/dist/core/outbox-transitions-recovery.js +42 -0
- package/dist/core/outbox-transitions.d.ts +145 -0
- package/dist/core/outbox-transitions.js +236 -0
- package/dist/core/outbox-types.d.ts +400 -0
- package/dist/core/outbox-types.js +20 -0
- package/dist/core/outbox-validation.d.ts +101 -0
- package/dist/core/outbox-validation.js +127 -0
- package/dist/core/outbox-waits.d.ts +39 -0
- package/dist/core/outbox-waits.js +88 -0
- package/dist/core/outbox.d.ts +156 -0
- package/dist/core/outbox.js +234 -0
- package/dist/core/registry-limits.d.ts +49 -0
- package/dist/core/registry-limits.js +10 -0
- package/dist/core/registry-schema-conversion.d.ts +20 -0
- package/dist/core/registry-schema-conversion.js +22 -0
- package/dist/core/registry-snapshot.d.ts +91 -42
- package/dist/core/registry-snapshot.js +39 -77
- package/dist/core/registry-workflow-contract-draft.d.ts +32 -0
- package/dist/core/registry-workflow-contract-draft.js +28 -0
- package/dist/core/registry-workflow-manifest.d.ts +122 -0
- package/dist/core/registry-workflow-manifest.js +92 -0
- package/dist/core/source/errors.d.ts +55 -0
- package/dist/core/source/errors.js +13 -0
- package/dist/core/source/index.d.ts +19 -0
- package/dist/core/source/index.js +4 -0
- package/dist/core/source/resolvers.d.ts +45 -0
- package/dist/core/source/resolvers.js +9 -0
- package/dist/core/source/types.d.ts +211 -0
- package/dist/core/source/types.js +0 -0
- package/dist/core/source/validate.d.ts +91 -0
- package/dist/core/source/validate.js +62 -0
- package/dist/core/source/workflow-source.d.ts +43 -0
- package/dist/core/source/workflow-source.js +16 -0
- package/dist/core/types/workflow-registries.d.ts +7 -0
- package/dist/core/types/workflow-registry.d.ts +12 -0
- package/dist/core/versioning.js +2 -0
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +9 -1
- package/dist/http.js +2 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +50 -0
- package/dist/indexeddb.js +1 -1
- package/dist/json-schema.js +3 -3
- package/dist/mcp/resources.js +2 -0
- package/dist/runtime/portable.d.ts +9 -1
- package/dist/server/fault-to-json-rpc.js +3 -1
- package/dist/server/handler/auth-context-principal.js +4 -0
- package/dist/server/json-rpc-http.js +2 -0
- package/dist/server/json-rpc-websocket.js +6 -4
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +2 -0
- package/dist/server/operation-catalog/types.d.ts +17 -0
- package/dist/server/operation-fault.d.ts +3 -0
- package/dist/server/operation-fault.js +3 -1
- package/dist/server/operations/activate-workflow-revision.d.ts +30 -0
- package/dist/server/operations/activate-workflow-revision.js +69 -0
- package/dist/server/operations/fleet-events-subscription.js +1 -1
- package/dist/server/operations/fork-workflow.js +1 -1
- package/dist/server/operations/get-active-workflow-revision.d.ts +32 -0
- package/dist/server/operations/get-active-workflow-revision.js +46 -0
- package/dist/server/operations/get-catalog-diagnostics.d.ts +85 -0
- package/dist/server/operations/get-catalog-diagnostics.js +57 -0
- package/dist/server/operations/get-registry.js +17 -4
- package/dist/server/operations/get-workflow-revision.d.ts +25 -0
- package/dist/server/operations/get-workflow-revision.js +50 -0
- package/dist/server/operations/install-workflow-revision.d.ts +27 -0
- package/dist/server/operations/install-workflow-revision.js +46 -0
- package/dist/server/operations/list-workflow-revisions.d.ts +20 -0
- package/dist/server/operations/list-workflow-revisions.js +40 -0
- package/dist/server/operations/start-or-signal-workflow.js +1 -1
- package/dist/server/operations/start-workflow.js +1 -1
- package/dist/server/operations/static-registrations.js +36 -0
- package/dist/server/operations/storage.js +2 -2
- package/dist/server/operations/submit-review-decision.js +1 -1
- package/dist/server/operations/workflow-catalog-operation-helpers.d.ts +59 -0
- package/dist/server/operations/workflow-catalog-operation-helpers.js +135 -0
- package/dist/server/runtime/websocket-upgrade.js +2 -0
- package/dist/storage/bun-sql.js +49 -6
- package/dist/storage/catalog-keys.d.ts +45 -0
- package/dist/storage/catalog-keys.js +6 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/derived-operations.js +1 -1
- package/dist/storage/index.d.ts +26 -1
- package/dist/storage/interface.d.ts +26 -1
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-encoding.d.ts +15 -0
- package/dist/storage/key-encoding.js +3 -0
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +15 -0
- package/dist/storage/lmdb.d.ts +26 -1
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/mailbox-keys.d.ts +80 -0
- package/dist/storage/mailbox-keys.js +14 -0
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +2 -2
- package/dist/storage/node-sqlite-loader.d.ts +1 -1
- package/dist/storage/node-sqlite.js +49 -6
- package/dist/storage/outbox-keys.d.ts +77 -0
- package/dist/storage/outbox-keys.js +14 -0
- package/dist/storage/postgres.js +2 -2
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/storage-configuration.d.ts +6 -0
- 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/dist/worker/manifest/registry-contract-builder.d.ts +21 -3
- package/dist/worker/manifest/registry-contract-builder.js +40 -31
- package/package.json +1 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attemptControllerRegistry,
|
|
3
|
+
releaseAttemptControllerRegistry
|
|
4
|
+
} from "./application-primitive-attempt-registry.js";
|
|
5
|
+
import { claimNextDelivery } from "./outbox-delivery.js";
|
|
6
|
+
import { drainOutbox } from "./outbox-drain.js";
|
|
7
|
+
import { capacityOf, enqueueDelivery } from "./outbox-enqueue.js";
|
|
8
|
+
import {
|
|
9
|
+
ApplicationDeliveryValidationError,
|
|
10
|
+
requireClockInstant,
|
|
11
|
+
requireMaintenanceInstant,
|
|
12
|
+
validateCancellationReason,
|
|
13
|
+
validateDeliveryIdentifier,
|
|
14
|
+
validateDurableJSONValue
|
|
15
|
+
} from "./outbox-guards.js";
|
|
16
|
+
import {
|
|
17
|
+
OUTBOX_PRIMITIVE,
|
|
18
|
+
toApplicationDeliveryReceipt
|
|
19
|
+
} from "./outbox-internals.js";
|
|
20
|
+
import { listDeliveries } from "./outbox-listing.js";
|
|
21
|
+
import { runOutboxMaintenance } from "./outbox-maintenance.js";
|
|
22
|
+
import { deadLetterDelivery, retryDelivery } from "./outbox-operations.js";
|
|
23
|
+
import { deliverNext } from "./outbox-runner.js";
|
|
24
|
+
import {
|
|
25
|
+
beginAttempt,
|
|
26
|
+
heartbeatAttempt,
|
|
27
|
+
readCleanupState,
|
|
28
|
+
requestCancellation,
|
|
29
|
+
settleAttempt
|
|
30
|
+
} from "./outbox-settlement.js";
|
|
31
|
+
import { createOutboxKeys, loadDelivery, loadOutboxHeader } from "./outbox-storage.js";
|
|
32
|
+
import { resolveOutboxPolicy, validateOutcome } from "./outbox-validation.js";
|
|
33
|
+
import { waitForCleanup, waitForDueWork } from "./outbox-waits.js";
|
|
34
|
+
function requireOutboxStorage(storage) {
|
|
35
|
+
const capabilities = storage.capabilities();
|
|
36
|
+
if (!capabilities.conditionalBatch)
|
|
37
|
+
throw new ApplicationDeliveryValidationError("Application outboxes require storage with conditional batch support: every transition is a compare-and-swap.");
|
|
38
|
+
if (capabilities.scanConsistency !== "snapshot")
|
|
39
|
+
throw new ApplicationDeliveryValidationError("Application outboxes require storage with snapshot scan consistency: claims read the earliest due entry, and a best-effort scan can miss one.");
|
|
40
|
+
if (capabilities.readAfterWrite !== "linearizable")
|
|
41
|
+
throw new ApplicationDeliveryValidationError("Application outboxes require storage with linearizable read-after-write: maintenance reconciles live attempts against what it reads, and a stale read could abort a current one.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class Outbox {
|
|
45
|
+
#runtime;
|
|
46
|
+
#disposal = new AbortController;
|
|
47
|
+
#ownAttempts = new Set;
|
|
48
|
+
#maintenanceCursor;
|
|
49
|
+
#maintenanceTimer = null;
|
|
50
|
+
#disposed = !1;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
const policy = resolveOutboxPolicy(options);
|
|
53
|
+
requireOutboxStorage(options.storage);
|
|
54
|
+
if (options.adapter !== void 0 && typeof options.adapter.send !== "function")
|
|
55
|
+
throw new ApplicationDeliveryValidationError("adapter must expose a send() function.");
|
|
56
|
+
if (options.onMaintenanceError !== void 0 && typeof options.onMaintenanceError !== "function")
|
|
57
|
+
throw new ApplicationDeliveryValidationError("onMaintenanceError must be a function.");
|
|
58
|
+
this.#runtime = {
|
|
59
|
+
storage: options.storage,
|
|
60
|
+
events: options.events,
|
|
61
|
+
adapter: options.adapter,
|
|
62
|
+
policy,
|
|
63
|
+
keys: createOutboxKeys(policy.namespace, policy.ownerId),
|
|
64
|
+
now: () => requireClockInstant((options.now ?? Date.now)()),
|
|
65
|
+
generateId: options.generateId ?? (() => crypto.randomUUID()),
|
|
66
|
+
disposal: this.#disposal.signal,
|
|
67
|
+
attemptControllers: attemptControllerRegistry(options.storage, OUTBOX_PRIMITIVE, policy.namespace, policy.ownerId),
|
|
68
|
+
adoptAttempt: (attemptToken) => {
|
|
69
|
+
if (this.#disposed)
|
|
70
|
+
return null;
|
|
71
|
+
this.#ownAttempts.add(attemptToken);
|
|
72
|
+
return () => {
|
|
73
|
+
this.#ownAttempts.delete(attemptToken);
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
readMaintenanceCursor: () => this.#maintenanceCursor,
|
|
77
|
+
writeMaintenanceCursor: (cursor) => {
|
|
78
|
+
this.#maintenanceCursor = cursor;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
if (policy.backgroundTasks === "automatic")
|
|
82
|
+
this.#scheduleMaintenance(options.onMaintenanceError ?? defaultMaintenanceErrorSink);
|
|
83
|
+
}
|
|
84
|
+
#scheduleMaintenance(onError) {
|
|
85
|
+
const tick = async () => {
|
|
86
|
+
this.#maintenanceTimer = null;
|
|
87
|
+
if (this.#disposed)
|
|
88
|
+
return;
|
|
89
|
+
try {
|
|
90
|
+
await runOutboxMaintenance(this.#runtime, this.#runtime.now());
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (this.#disposed)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
onError(error);
|
|
96
|
+
} catch {}
|
|
97
|
+
}
|
|
98
|
+
if (!this.#disposed)
|
|
99
|
+
arm();
|
|
100
|
+
}, arm = () => {
|
|
101
|
+
this.#maintenanceTimer = setTimeout(() => {
|
|
102
|
+
tick();
|
|
103
|
+
}, this.#runtime.policy.maintenanceIntervalMs);
|
|
104
|
+
this.#maintenanceTimer.unref?.();
|
|
105
|
+
};
|
|
106
|
+
arm();
|
|
107
|
+
}
|
|
108
|
+
get namespace() {
|
|
109
|
+
return this.#runtime.policy.namespace;
|
|
110
|
+
}
|
|
111
|
+
get ownerId() {
|
|
112
|
+
return this.#runtime.policy.ownerId;
|
|
113
|
+
}
|
|
114
|
+
get storage() {
|
|
115
|
+
return this.#runtime.storage;
|
|
116
|
+
}
|
|
117
|
+
#assertLive() {
|
|
118
|
+
if (this.#disposed)
|
|
119
|
+
throw new ApplicationDeliveryValidationError("This application outbox has been disposed.");
|
|
120
|
+
}
|
|
121
|
+
async enqueue(delivery) {
|
|
122
|
+
this.#assertLive();
|
|
123
|
+
return enqueueDelivery(this.#runtime, delivery);
|
|
124
|
+
}
|
|
125
|
+
async receipt(deliveryId) {
|
|
126
|
+
this.#assertLive();
|
|
127
|
+
const loaded = await loadDelivery(this.#runtime.storage, this.#runtime.keys, validateDeliveryIdentifier(deliveryId));
|
|
128
|
+
return loaded === null ? null : toApplicationDeliveryReceipt(loaded.record);
|
|
129
|
+
}
|
|
130
|
+
async list(options) {
|
|
131
|
+
this.#assertLive();
|
|
132
|
+
return listDeliveries(this.#runtime, options);
|
|
133
|
+
}
|
|
134
|
+
async capacity() {
|
|
135
|
+
this.#assertLive();
|
|
136
|
+
const header = await loadOutboxHeader(this.#runtime.storage, this.#runtime.keys, this.#runtime.policy.namespace, this.#runtime.policy.ownerId);
|
|
137
|
+
return capacityOf(this.#runtime, header.record.openCount, header.record.enqueuedCount);
|
|
138
|
+
}
|
|
139
|
+
async claim(options) {
|
|
140
|
+
this.#assertLive();
|
|
141
|
+
return claimNextDelivery(this.#runtime, options);
|
|
142
|
+
}
|
|
143
|
+
async beginAttempt(options) {
|
|
144
|
+
this.#assertLive();
|
|
145
|
+
return beginAttempt(this.#runtime, {
|
|
146
|
+
deliveryId: validateDeliveryIdentifier(options.deliveryId),
|
|
147
|
+
attemptToken: options.attemptToken
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async heartbeat(options) {
|
|
151
|
+
this.#assertLive();
|
|
152
|
+
return heartbeatAttempt(this.#runtime, {
|
|
153
|
+
deliveryId: validateDeliveryIdentifier(options.deliveryId),
|
|
154
|
+
attemptToken: options.attemptToken,
|
|
155
|
+
transportActivity: validateDurableJSONValue(options.transportActivity, "transportActivity")
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async settle(options) {
|
|
159
|
+
this.#assertLive();
|
|
160
|
+
return settleAttempt(this.#runtime, {
|
|
161
|
+
deliveryId: validateDeliveryIdentifier(options.deliveryId),
|
|
162
|
+
attemptToken: options.attemptToken,
|
|
163
|
+
outcome: validateOutcome(options.outcome)
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
async deliverNext(options) {
|
|
167
|
+
this.#assertLive();
|
|
168
|
+
return deliverNext(this.#runtime, options);
|
|
169
|
+
}
|
|
170
|
+
async drain(options) {
|
|
171
|
+
this.#assertLive();
|
|
172
|
+
return drainOutbox(this.#runtime, options);
|
|
173
|
+
}
|
|
174
|
+
async requestCancellation(options) {
|
|
175
|
+
this.#assertLive();
|
|
176
|
+
return requestCancellation(this.#runtime, {
|
|
177
|
+
deliveryId: validateDeliveryIdentifier(options.deliveryId),
|
|
178
|
+
reason: validateCancellationReason(options.reason)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async cleanupState(deliveryId) {
|
|
182
|
+
this.#assertLive();
|
|
183
|
+
return readCleanupState(this.#runtime, validateDeliveryIdentifier(deliveryId));
|
|
184
|
+
}
|
|
185
|
+
async awaitCleanup(options) {
|
|
186
|
+
this.#assertLive();
|
|
187
|
+
return waitForCleanup(this.#runtime, {
|
|
188
|
+
...options,
|
|
189
|
+
deliveryId: validateDeliveryIdentifier(options.deliveryId)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
async retry(options) {
|
|
193
|
+
this.#assertLive();
|
|
194
|
+
return retryDelivery(this.#runtime, validateDeliveryIdentifier(options.deliveryId));
|
|
195
|
+
}
|
|
196
|
+
async deadLetter(options) {
|
|
197
|
+
this.#assertLive();
|
|
198
|
+
return deadLetterDelivery(this.#runtime, validateDeliveryIdentifier(options.deliveryId), validateCancellationReason(options.reason));
|
|
199
|
+
}
|
|
200
|
+
async waitForDue(options) {
|
|
201
|
+
this.#assertLive();
|
|
202
|
+
return waitForDueWork(this.#runtime, options);
|
|
203
|
+
}
|
|
204
|
+
async runMaintenance(now = this.#runtime.now()) {
|
|
205
|
+
this.#assertLive();
|
|
206
|
+
return runOutboxMaintenance(this.#runtime, requireMaintenanceInstant(now));
|
|
207
|
+
}
|
|
208
|
+
dispose() {
|
|
209
|
+
if (this.#disposed)
|
|
210
|
+
return;
|
|
211
|
+
this.#disposed = !0;
|
|
212
|
+
if (this.#maintenanceTimer !== null) {
|
|
213
|
+
clearTimeout(this.#maintenanceTimer);
|
|
214
|
+
this.#maintenanceTimer = null;
|
|
215
|
+
}
|
|
216
|
+
for (const attemptToken of this.#ownAttempts) {
|
|
217
|
+
const registration = this.#runtime.attemptControllers.get(attemptToken);
|
|
218
|
+
if (registration === void 0)
|
|
219
|
+
continue;
|
|
220
|
+
this.#runtime.attemptControllers.delete(attemptToken);
|
|
221
|
+
if (!registration.controller.signal.aborted)
|
|
222
|
+
registration.controller.abort(Error("The application outbox was disposed while this attempt was open."));
|
|
223
|
+
}
|
|
224
|
+
this.#ownAttempts.clear();
|
|
225
|
+
this.#disposal.abort(Error("The application outbox was disposed."));
|
|
226
|
+
releaseAttemptControllerRegistry(this.#runtime.storage, OUTBOX_PRIMITIVE, this.#runtime.policy.namespace, this.#runtime.policy.ownerId);
|
|
227
|
+
}
|
|
228
|
+
[Symbol.dispose]() {
|
|
229
|
+
this.dispose();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function defaultMaintenanceErrorSink(error) {
|
|
233
|
+
console.error("Application outbox maintenance failed:", error);
|
|
234
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate registry-snapshot limits shared between the producer
|
|
3
|
+
* (`buildRegistrySnapshot`) and the codegen consumer
|
|
4
|
+
* (`cli/codegen-validate.ts`). Split into its own leaf module — rather than
|
|
5
|
+
* living in `registry-snapshot.ts` — so `codegen-validate.ts` can import the
|
|
6
|
+
* constant and error type without pulling in the rest of the (non-public)
|
|
7
|
+
* snapshot-building surface, and so `registry-snapshot.ts` stays under the
|
|
8
|
+
* repository's implementation-file-size ceiling.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately not re-exported from `core/contract/limits.ts` or any other
|
|
11
|
+
* public-surface module: `registry-snapshot.ts` and this module are internal
|
|
12
|
+
* to the package (never re-exported from the package root), so this constant
|
|
13
|
+
* and error class are not part of the public API and carry no `@example`/
|
|
14
|
+
* jsdoc-audit obligations.
|
|
15
|
+
*
|
|
16
|
+
* @module core/registry-limits
|
|
17
|
+
*/
|
|
18
|
+
import { WeftError } from './weft-error.ts';
|
|
19
|
+
/**
|
|
20
|
+
* Ceiling on the number of workflows one registry snapshot may report,
|
|
21
|
+
* enforced at snapshot-build time in `buildRegistrySnapshot` (the producer)
|
|
22
|
+
* and, independently, on the raw wire payload in `codegen-validate.ts` (the
|
|
23
|
+
* consumer) before that payload is parsed. The two call sites deliberately
|
|
24
|
+
* share this one constant rather than each defining its own: a consumer
|
|
25
|
+
* ceiling looser than the producer's would be dead code, and a consumer
|
|
26
|
+
* ceiling tighter than the producer's would make `weft codegen --server`
|
|
27
|
+
* reject a legitimately-generated snapshot from a same-release server.
|
|
28
|
+
*
|
|
29
|
+
* 512 matches `worker/manifest/limits.ts`'s `MAX_MANIFEST_WORKFLOW_COUNT` —
|
|
30
|
+
* the analogous ceiling an advertised worker manifest's `workflows` array is
|
|
31
|
+
* held to — without importing across the `core`/`worker` boundary; the two
|
|
32
|
+
* numbers are intentionally kept in sync by convention, not by a shared
|
|
33
|
+
* import, since `core/` does not depend on `worker/`.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MAX_REGISTRY_WORKFLOW_COUNT = 512;
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when `buildRegistrySnapshot` would otherwise publish more than
|
|
38
|
+
* {@link MAX_REGISTRY_WORKFLOW_COUNT} workflows in one snapshot. Unlike
|
|
39
|
+
* {@link RegistryManifestLimitError}, this is an aggregate violation with no
|
|
40
|
+
* single offending workflow to name. Mirrors
|
|
41
|
+
* `RegistrySchemaConversionError`/`RegistryManifestLimitError`'s masked-500
|
|
42
|
+
* handling in `server/operations/get-registry.ts`: the wire response stays a
|
|
43
|
+
* generic `500 / Internal server error`, and the actual count reaches
|
|
44
|
+
* server-side logs only.
|
|
45
|
+
*/
|
|
46
|
+
export declare class RegistryWorkflowCountLimitError extends WeftError<'RegistryWorkflowCountLimitError'> {
|
|
47
|
+
readonly count: number;
|
|
48
|
+
constructor(count: number);
|
|
49
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WeftError } from "./weft-error.js";
|
|
2
|
+
export const MAX_REGISTRY_WORKFLOW_COUNT = 512;
|
|
3
|
+
|
|
4
|
+
export class RegistryWorkflowCountLimitError extends WeftError {
|
|
5
|
+
count;
|
|
6
|
+
constructor(count) {
|
|
7
|
+
super("RegistryWorkflowCountLimitError", `Registry snapshot would report ${count} workflows, exceeding the maximum of ${MAX_REGISTRY_WORKFLOW_COUNT}`);
|
|
8
|
+
this.count = count;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DefinitionSchema } from './types/definition-schema.ts';
|
|
2
|
+
import { WeftError } from './weft-error.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Thrown when a registered workflow or activity schema cannot be converted
|
|
5
|
+
* to JSON Schema. Carries the offending entity name and direction so
|
|
6
|
+
* server-side observability (logs and telemetry) and non-HTTP callers
|
|
7
|
+
* (the in-process MCP builder, programmatic users of `buildRegistrySnapshot`)
|
|
8
|
+
* can identify which registration is broken. The HTTP REST binding
|
|
9
|
+
* deliberately masks this on the wire as a generic `500 / Internal server
|
|
10
|
+
* error` so a misbehaving registration cannot leak schema layout to clients
|
|
11
|
+
* that only have `system:read`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class RegistrySchemaConversionError extends WeftError<'RegistrySchemaConversionError'> {
|
|
14
|
+
readonly entityKind: 'workflow' | 'activity';
|
|
15
|
+
readonly entityName: string;
|
|
16
|
+
readonly direction: 'inputSchema' | 'outputSchema';
|
|
17
|
+
constructor(entityKind: 'workflow' | 'activity', entityName: string, direction: 'inputSchema' | 'outputSchema', cause: unknown);
|
|
18
|
+
}
|
|
19
|
+
/** Convert one `DefinitionSchema` fragment to JSON Schema, wrapping a conversion failure as {@link RegistrySchemaConversionError}. */
|
|
20
|
+
export declare function convertSchema(entityKind: 'workflow' | 'activity', entityName: string, field: 'inputSchema' | 'outputSchema', schema: DefinitionSchema): Record<string, unknown>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { definitionSchemaToJsonSchema } from "./types/definition-schema-to-json.js";
|
|
2
|
+
import { WeftError } from "./weft-error.js";
|
|
3
|
+
|
|
4
|
+
export class RegistrySchemaConversionError extends WeftError {
|
|
5
|
+
entityKind;
|
|
6
|
+
entityName;
|
|
7
|
+
direction;
|
|
8
|
+
constructor(entityKind, entityName, direction, cause) {
|
|
9
|
+
const causeMessage = cause instanceof Error ? cause.message : String(cause);
|
|
10
|
+
super("RegistrySchemaConversionError", `Failed to convert ${direction} for ${entityKind} "${entityName}": ${causeMessage}`, { cause });
|
|
11
|
+
this.entityKind = entityKind;
|
|
12
|
+
this.entityName = entityName;
|
|
13
|
+
this.direction = direction;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function convertSchema(entityKind, entityName, field, schema) {
|
|
17
|
+
try {
|
|
18
|
+
return definitionSchemaToJsonSchema(schema, field === "inputSchema" ? "input" : "output");
|
|
19
|
+
} catch (cause) {
|
|
20
|
+
throw new RegistrySchemaConversionError(entityKind, entityName, field, cause);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -8,41 +8,45 @@
|
|
|
8
8
|
* exceptions surface as a typed {@link RegistrySchemaConversionError} (see
|
|
9
9
|
* its JSDoc for what reaches the wire vs server logs).
|
|
10
10
|
*
|
|
11
|
-
* **
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
11
|
+
* **v2.** Each registered workflow's schema/description/tags/message
|
|
12
|
+
* metadata is packaged as a {@link WorkflowRevisionManifest} (`core/contract`,
|
|
13
|
+
* WFT-5) rather than a flat `Record<name, entry>` — `workflows` is a sorted
|
|
14
|
+
* array and `activeRevisions` is the `name -> revision` pointer map a
|
|
15
|
+
* consumer resolves the "currently active" manifest through. Building a
|
|
16
|
+
* manifest hashes the normalized contract (`crypto.subtle`), so this module
|
|
17
|
+
* is async where v1 was not.
|
|
18
|
+
*
|
|
19
|
+
* **Ordering guarantee.** `workflows` is sorted by `(name, revision)` via
|
|
20
|
+
* {@link compareWorkflowManifests} — see that export's JSDoc for why the
|
|
21
|
+
* revision tiebreak can never actually fire through this builder.
|
|
22
|
+
* `activities` keys are inserted in alphabetical (codepoint) order, and
|
|
23
|
+
* signal/update/query keys inside each manifest's `contract` the same way.
|
|
24
|
+
* Workflow and activity names cannot be integer-like (the name grammar
|
|
25
|
+
* requires a leading letter or underscore), but signal/update/query names
|
|
26
|
+
* accept any string, so integer-like message names could theoretically be
|
|
27
|
+
* reordered by JS engines despite the explicit sort. Clients that want to
|
|
28
|
+
* protect themselves from future registry sources should still sort
|
|
29
|
+
* `Object.keys(...)` before presenting or diffing snapshot entries.
|
|
30
|
+
*
|
|
31
|
+
* The per-workflow entry/message/scoped-activity conversion this module
|
|
32
|
+
* folds into each manifest lives in `registry-workflow-manifest.ts` — see
|
|
33
|
+
* that module's doc for why it is a separate file.
|
|
19
34
|
*
|
|
20
35
|
* @module core/registry-snapshot
|
|
21
36
|
*/
|
|
22
37
|
import type { ActivityMetadata } from './activity-registry.ts';
|
|
38
|
+
import type { WorkflowRevisionManifest } from './contract/index.ts';
|
|
23
39
|
import type { Engine } from './engine.ts';
|
|
24
|
-
import {
|
|
40
|
+
import { RegistryWorkflowCountLimitError } from './registry-limits.ts';
|
|
41
|
+
import { RegistrySchemaConversionError } from './registry-schema-conversion.ts';
|
|
42
|
+
export { buildWorkflowManifestForType, RegistryManifestLimitError, type RegistryMessageEntry, type RegistryWorkflowEntry, } from './registry-workflow-manifest.ts';
|
|
43
|
+
export { RegistrySchemaConversionError, RegistryWorkflowCountLimitError };
|
|
25
44
|
/**
|
|
26
45
|
* Current registry contract version. Future incompatible changes to the
|
|
27
46
|
* snapshot shape must bump this number; the codegen CLI rejects unknown
|
|
28
47
|
* versions with a clear upgrade message.
|
|
29
48
|
*/
|
|
30
|
-
export declare const REGISTRY_VERSION =
|
|
31
|
-
/** Schema metadata reported for a statically registered workflow message. */
|
|
32
|
-
export type RegistryMessageEntry = {
|
|
33
|
-
inputSchema?: Record<string, unknown>;
|
|
34
|
-
outputSchema?: Record<string, unknown>;
|
|
35
|
-
};
|
|
36
|
-
/** Metadata reported per workflow in a registry snapshot. */
|
|
37
|
-
export type RegistryWorkflowEntry = {
|
|
38
|
-
inputSchema?: Record<string, unknown>;
|
|
39
|
-
outputSchema?: Record<string, unknown>;
|
|
40
|
-
description?: string;
|
|
41
|
-
tags?: ReadonlyArray<string>;
|
|
42
|
-
signals?: Record<string, RegistryMessageEntry>;
|
|
43
|
-
updates?: Record<string, RegistryMessageEntry>;
|
|
44
|
-
queries?: Record<string, RegistryMessageEntry>;
|
|
45
|
-
};
|
|
49
|
+
export declare const REGISTRY_VERSION = 2;
|
|
46
50
|
/**
|
|
47
51
|
* Metadata reported per activity in a registry snapshot.
|
|
48
52
|
*
|
|
@@ -67,27 +71,46 @@ export type RegistryActivityEntry = {
|
|
|
67
71
|
/**
|
|
68
72
|
* Snapshot of every locally-registered workflow and activity, suitable for
|
|
69
73
|
* serialization as the `GET /v1/registry` response body.
|
|
74
|
+
*
|
|
75
|
+
* `workflows` carries one {@link WorkflowRevisionManifest} per registered
|
|
76
|
+
* workflow, sorted by {@link compareWorkflowManifests}. `activeRevisions`
|
|
77
|
+
* points each workflow name at the `revision` of its currently active
|
|
78
|
+
* manifest in `workflows` — today that is always the manifest a consumer
|
|
79
|
+
* resolves, since the engine registers exactly one implementation per name;
|
|
80
|
+
* the pointer exists so a future multi-revision registry source does not
|
|
81
|
+
* require another wire-shape bump. `activities` is unchanged from v1: a
|
|
82
|
+
* flat `Record<name, entry>`, since activities are not versioned contracts.
|
|
70
83
|
*/
|
|
71
84
|
export type RegistrySnapshot = {
|
|
72
|
-
registryVersion:
|
|
73
|
-
|
|
85
|
+
registryVersion: typeof REGISTRY_VERSION;
|
|
86
|
+
/** ISO-8601 generation timestamp. Informational only — excluded from codegen input validation and any determinism/drift comparison. */
|
|
87
|
+
generatedAt: string;
|
|
88
|
+
workflows: readonly WorkflowRevisionManifest[];
|
|
89
|
+
activeRevisions: Readonly<Record<string, string>>;
|
|
74
90
|
activities: Record<string, RegistryActivityEntry>;
|
|
75
91
|
};
|
|
76
92
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
93
|
+
* Order two workflow revision manifests by `(name, revision)`. `workflows`
|
|
94
|
+
* is sorted with this comparator so registry output is deterministic
|
|
95
|
+
* regardless of registration order.
|
|
96
|
+
*
|
|
97
|
+
* The `revision` tiebreak can never actually fire through
|
|
98
|
+
* {@link buildRegistrySnapshot}: the engine registers at most one
|
|
99
|
+
* implementation per workflow name, so `name` alone is already unique
|
|
100
|
+
* within one snapshot. It exists, and is exported, so a future
|
|
101
|
+
* multi-revision registry source (or this function in isolation) has a
|
|
102
|
+
* total order to rely on, and so the tiebreak itself has direct unit-test
|
|
103
|
+
* coverage independent of engine registration uniqueness.
|
|
85
104
|
*/
|
|
86
|
-
export declare
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
export declare function compareWorkflowManifests(a: Pick<WorkflowRevisionManifest, 'name' | 'revision'>, b: Pick<WorkflowRevisionManifest, 'name' | 'revision'>): number;
|
|
106
|
+
/** Options accepted by {@link buildRegistrySnapshot}. */
|
|
107
|
+
export interface BuildRegistrySnapshotOptions {
|
|
108
|
+
/**
|
|
109
|
+
* Clock used for `generatedAt`. Defaults to `Date.now`; exists solely so
|
|
110
|
+
* tests can pin `generatedAt` for exact-equality assertions. Production
|
|
111
|
+
* call sites never pass this.
|
|
112
|
+
*/
|
|
113
|
+
now?: () => number;
|
|
91
114
|
}
|
|
92
115
|
/**
|
|
93
116
|
* Build a registry snapshot from an engine's locally-registered workflows
|
|
@@ -95,7 +118,33 @@ export declare class RegistrySchemaConversionError extends WeftError<'RegistrySc
|
|
|
95
118
|
* worker but never registered with the local engine) are excluded by
|
|
96
119
|
* construction — `engine.listActivityDefinitions()` is the only source.
|
|
97
120
|
*
|
|
121
|
+
* `engine.listWorkflowDefinitions()`/`listActivityDefinitions()` are read
|
|
122
|
+
* synchronously in one eager pass before any `await`, so a workflow
|
|
123
|
+
* registered concurrently mid-build simply does not appear in that call's
|
|
124
|
+
* snapshot — the same eventual-consistency behavior v1's fully-synchronous
|
|
125
|
+
* builder had. No torn or partial manifest is possible.
|
|
126
|
+
*
|
|
98
127
|
* Throws {@link RegistrySchemaConversionError} if any registered schema
|
|
99
|
-
* fails JSON Schema conversion
|
|
128
|
+
* fails JSON Schema conversion, {@link RegistryManifestLimitError} if a
|
|
129
|
+
* registered workflow's contract exceeds a WFT-5 hostile-input limit, or
|
|
130
|
+
* {@link RegistryWorkflowCountLimitError} if the engine has more than
|
|
131
|
+
* {@link MAX_REGISTRY_WORKFLOW_COUNT} workflows registered in total —
|
|
132
|
+
* checked here, at the producer, so `weft codegen --server`'s matching
|
|
133
|
+
* consumer-side ceiling in `cli/codegen-validate.ts` can never reject a
|
|
134
|
+
* `GET /v1/registry` response this function actually emits. A caller that
|
|
135
|
+
* wants only one or a few workflows' manifests — never the full snapshot,
|
|
136
|
+
* so neither limit above is the right contract — should use
|
|
137
|
+
* `buildWorkflowManifestForType` (`registry-workflow-manifest.ts`) instead;
|
|
138
|
+
* it is what this function itself calls per workflow.
|
|
139
|
+
*/
|
|
140
|
+
export declare function buildRegistrySnapshot(engine: Engine, options?: BuildRegistrySnapshotOptions): Promise<RegistrySnapshot>;
|
|
141
|
+
/**
|
|
142
|
+
* Convert one activity's catalog metadata to its `RegistryActivityEntry`
|
|
143
|
+
* projection (schema pair plus queue/description/retry/timeout). Exported
|
|
144
|
+
* so build tooling that resolves a single activity outside a full
|
|
145
|
+
* {@link buildRegistrySnapshot} pass — see
|
|
146
|
+
* `worker/manifest/registry-contract-builder.ts`'s workflow-scoped-first
|
|
147
|
+
* activity resolution — can reuse the same conversion rather than
|
|
148
|
+
* reimplementing it.
|
|
100
149
|
*/
|
|
101
|
-
export declare function
|
|
150
|
+
export declare function buildActivityEntry(metadata: ActivityMetadata): RegistryActivityEntry;
|
|
@@ -1,81 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { compareCodepoint } from "./compare-codepoint.js";
|
|
2
|
+
import { ensureWorkflowCatalogReady, getWorkflowCatalog } from "./engine/catalog-readiness.js";
|
|
3
|
+
import { MAX_REGISTRY_WORKFLOW_COUNT, RegistryWorkflowCountLimitError } from "./registry-limits.js";
|
|
4
|
+
import { convertSchema, RegistrySchemaConversionError } from "./registry-schema-conversion.js";
|
|
5
|
+
import { buildOneWorkflowManifest } from "./registry-workflow-manifest.js";
|
|
6
|
+
export {
|
|
7
|
+
buildWorkflowManifestForType,
|
|
8
|
+
RegistryManifestLimitError
|
|
9
|
+
} from "./registry-workflow-manifest.js";
|
|
10
|
+
export { RegistrySchemaConversionError, RegistryWorkflowCountLimitError };
|
|
11
|
+
export const REGISTRY_VERSION = 2;
|
|
12
|
+
export function compareWorkflowManifests(a, b) {
|
|
13
|
+
if (a.name < b.name)
|
|
14
|
+
return -1;
|
|
15
|
+
if (a.name > b.name)
|
|
16
|
+
return 1;
|
|
17
|
+
if (a.revision < b.revision)
|
|
18
|
+
return -1;
|
|
19
|
+
if (a.revision > b.revision)
|
|
20
|
+
return 1;
|
|
21
|
+
return 0;
|
|
16
22
|
}
|
|
17
|
-
export function buildRegistrySnapshot(engine) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}), workflows = Object.create(null);
|
|
31
|
-
for (const definition of sortedWorkflows)
|
|
32
|
-
workflows[definition.type] = buildWorkflowEntry(definition);
|
|
33
|
-
const activities = Object.create(null);
|
|
23
|
+
export async function buildRegistrySnapshot(engine, options) {
|
|
24
|
+
await ensureWorkflowCatalogReady(engine);
|
|
25
|
+
const workflowDefinitions = engine.listWorkflowDefinitions();
|
|
26
|
+
if (workflowDefinitions.length > MAX_REGISTRY_WORKFLOW_COUNT)
|
|
27
|
+
throw new RegistryWorkflowCountLimitError(workflowDefinitions.length);
|
|
28
|
+
const activityDefinitions = engine.listActivityDefinitions(), sortedWorkflows = workflowDefinitions.toSorted((a, b) => compareCodepoint(a.type, b.type)), sortedActivities = activityDefinitions.toSorted((a, b) => compareCodepoint(a.name, b.name)), manifests = await Promise.all(sortedWorkflows.map((definition) => buildOneWorkflowManifest(engine, definition))), catalog = getWorkflowCatalog(engine), activeRevisions = Object.create(null);
|
|
29
|
+
for (const manifest of manifests) {
|
|
30
|
+
const activePointer = catalog.resolveActive(manifest.name);
|
|
31
|
+
if (activePointer === void 0)
|
|
32
|
+
throw Error(`Registry snapshot invariant violated: workflow "${manifest.name}" has no active workflow ` + "catalog pointer. This is a Weft bug \u2014 engine.register() always installs and activates on " + "registration, and ensureWorkflowCatalogReady() is awaited before this point.");
|
|
33
|
+
activeRevisions[manifest.name] = activePointer.revision;
|
|
34
|
+
}
|
|
35
|
+
const sortedManifests = manifests.toSorted(compareWorkflowManifests), activities = Object.create(null);
|
|
34
36
|
for (const metadata of sortedActivities)
|
|
35
37
|
activities[metadata.name] = buildActivityEntry(metadata);
|
|
38
|
+
const now = options?.now ?? Date.now;
|
|
36
39
|
return {
|
|
37
40
|
registryVersion: REGISTRY_VERSION,
|
|
38
|
-
|
|
41
|
+
generatedAt: new Date(now()).toISOString(),
|
|
42
|
+
workflows: sortedManifests,
|
|
43
|
+
activeRevisions,
|
|
39
44
|
activities
|
|
40
45
|
};
|
|
41
46
|
}
|
|
42
|
-
function
|
|
43
|
-
const entry = {};
|
|
44
|
-
if (definition.inputSchema !== void 0)
|
|
45
|
-
entry.inputSchema = convertSchema("workflow", definition.type, "inputSchema", definition.inputSchema);
|
|
46
|
-
if (definition.outputSchema !== void 0)
|
|
47
|
-
entry.outputSchema = convertSchema("workflow", definition.type, "outputSchema", definition.outputSchema);
|
|
48
|
-
if (definition.description !== void 0)
|
|
49
|
-
entry.description = definition.description;
|
|
50
|
-
if (definition.tags.length > 0)
|
|
51
|
-
entry.tags = [...definition.tags];
|
|
52
|
-
addWorkflowMessageEntries(entry, definition);
|
|
53
|
-
return entry;
|
|
54
|
-
}
|
|
55
|
-
function addWorkflowMessageEntries(entry, definition) {
|
|
56
|
-
if (definition.signals !== void 0 && Object.keys(definition.signals).length > 0)
|
|
57
|
-
entry.signals = buildMessageEntries(definition.type, "signal", definition.signals);
|
|
58
|
-
if (definition.updates !== void 0 && Object.keys(definition.updates).length > 0)
|
|
59
|
-
entry.updates = buildMessageEntries(definition.type, "update", definition.updates);
|
|
60
|
-
if (definition.queries !== void 0 && Object.keys(definition.queries).length > 0)
|
|
61
|
-
entry.queries = buildMessageEntries(definition.type, "query", definition.queries);
|
|
62
|
-
}
|
|
63
|
-
function buildMessageEntries(workflowType, messageKind, definitions) {
|
|
64
|
-
const entries = Object.create(null);
|
|
65
|
-
for (const name of Object.keys(definitions).toSorted()) {
|
|
66
|
-
const definition = definitions[name];
|
|
67
|
-
if (definition === void 0)
|
|
68
|
-
continue;
|
|
69
|
-
const entry = {}, entityName = `${workflowType}.${messageKind}.${name}`;
|
|
70
|
-
if (definition.inputSchema !== void 0)
|
|
71
|
-
entry.inputSchema = convertSchema("workflow", entityName, "inputSchema", definition.inputSchema);
|
|
72
|
-
if (definition.outputSchema !== void 0)
|
|
73
|
-
entry.outputSchema = convertSchema("workflow", entityName, "outputSchema", definition.outputSchema);
|
|
74
|
-
entries[name] = entry;
|
|
75
|
-
}
|
|
76
|
-
return entries;
|
|
77
|
-
}
|
|
78
|
-
function buildActivityEntry(metadata) {
|
|
47
|
+
export function buildActivityEntry(metadata) {
|
|
79
48
|
const entry = { queue: metadata.queue };
|
|
80
49
|
if (metadata.inputSchema !== void 0)
|
|
81
50
|
entry.inputSchema = convertSchema("activity", metadata.name, "inputSchema", metadata.inputSchema);
|
|
@@ -89,10 +58,3 @@ function buildActivityEntry(metadata) {
|
|
|
89
58
|
entry.timeout = metadata.timeout;
|
|
90
59
|
return entry;
|
|
91
60
|
}
|
|
92
|
-
function convertSchema(entityKind, entityName, field, schema) {
|
|
93
|
-
try {
|
|
94
|
-
return definitionSchemaToJsonSchema(schema, field === "inputSchema" ? "input" : "output");
|
|
95
|
-
} catch (cause) {
|
|
96
|
-
throw new RegistrySchemaConversionError(entityKind, entityName, field, cause);
|
|
97
|
-
}
|
|
98
|
-
}
|