@ewhauser/world-celld 0.8.0 → 0.9.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/CHANGELOG.md +17 -0
- package/README.md +17 -5
- package/dist/index.d.ts +6 -40
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -38
- package/dist/index.js.map +1 -1
- package/dist/queue-consumer.d.ts +1 -1
- package/dist/queue-consumer.js +1 -1
- package/dist/{queue-delivery-BdeNUbRN.d.ts → queue-delivery-wvPp6_Hh.d.ts} +2 -1
- package/dist/{queue-delivery-BdeNUbRN.d.ts.map → queue-delivery-wvPp6_Hh.d.ts.map} +1 -1
- package/dist/queue-protocol-8iiZ8o_1.d.ts +42 -0
- package/dist/queue-protocol-8iiZ8o_1.d.ts.map +1 -0
- package/dist/{queue-protocol-DKYt8qZJ.js → queue-protocol-C1zbXwa_.js} +5 -2
- package/dist/queue-protocol-C1zbXwa_.js.map +1 -0
- package/dist/{run-list-C987PkJ2.js → run-list-C4B4SBYW.js} +6 -2
- package/dist/{run-list-C987PkJ2.js.map → run-list-C4B4SBYW.js.map} +1 -1
- package/dist/testing.d.ts +17 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +707 -183
- package/dist/testing.js.map +1 -1
- package/dist/worker.d.ts +33 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +408 -183
- package/dist/worker.js.map +1 -1
- package/package.json +4 -4
- package/dist/queue-protocol-DKYt8qZJ.js.map +0 -1
package/dist/queue-consumer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as NativeQueueEnvelope, t as QueueDeliveryResult } from "./queue-delivery-
|
|
1
|
+
import { n as NativeQueueEnvelope, t as QueueDeliveryResult } from "./queue-delivery-wvPp6_Hh.js";
|
|
2
2
|
//#region src/worker/queue-consumer.d.ts
|
|
3
3
|
interface NativeQueueMessage {
|
|
4
4
|
readonly body: unknown;
|
package/dist/queue-consumer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as QUEUE_CLAIM_STALE_MS, d as validateNativeQueueEnvelope, o as nativeQueueDelaySeconds, x as queueDelayDeadline } from "./queue-protocol-C1zbXwa_.js";
|
|
2
2
|
//#region src/worker/queue-consumer.ts
|
|
3
3
|
function backoffSeconds(attempt) {
|
|
4
4
|
return Math.min(60, 2 ** Math.min(attempt, 30));
|
|
@@ -59,6 +59,7 @@ type RunQueueReservation = {
|
|
|
59
59
|
scope: 'run';
|
|
60
60
|
admitted: boolean;
|
|
61
61
|
messageId: string;
|
|
62
|
+
publicationPending?: true;
|
|
62
63
|
};
|
|
63
64
|
//#endregion
|
|
64
65
|
//#region src/worker/queue-delivery.d.ts
|
|
@@ -72,4 +73,4 @@ type QueueDeliveryResult = {
|
|
|
72
73
|
};
|
|
73
74
|
//#endregion
|
|
74
75
|
export { RunQueueReservation as a, QueuePayloadRegistration as i, NativeQueueEnvelope as n, QueuePayloadOrphan as r, QueueDeliveryResult as t };
|
|
75
|
-
//# sourceMappingURL=queue-delivery-
|
|
76
|
+
//# sourceMappingURL=queue-delivery-wvPp6_Hh.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue-delivery-
|
|
1
|
+
{"version":3,"file":"queue-delivery-wvPp6_Hh.d.ts","names":[],"sources":["../src/queue-protocol.ts","../src/worker/queue-delivery.ts"],"mappings":";UAmCiB;EACf;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA;;;;;;;;;UAUe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA;;EAEA;;;;;EAKA;;EAEA;EACA;;;;;;;KAQU;EACN;EAAW;;EACX;EAAU;;EACV;EAAU;EAAc;EAAmB;EAAmB;;;;KC/ExD;EACN;;EACA;EAAiB;;EACjB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/queue-protocol.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Small broker message carried by celld's native Queue.
|
|
4
|
+
*
|
|
5
|
+
* Run-bearing payload bytes live in object storage so the broker's 128 kB limit does not
|
|
6
|
+
* narrow the Workflow World contract and run retention can delete those bytes
|
|
7
|
+
* without waiting for the Queue's fixed four-day retention window.
|
|
8
|
+
*/
|
|
9
|
+
interface NativeQueueEnvelope {
|
|
10
|
+
version: 1;
|
|
11
|
+
messageId: string;
|
|
12
|
+
queueName: string;
|
|
13
|
+
targetBaseUrl: string;
|
|
14
|
+
runId?: string;
|
|
15
|
+
idempotencyKey?: string;
|
|
16
|
+
payloadKey?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Inline body. Health checks always travel inline; a run-bearing body may
|
|
19
|
+
* travel inline when it is small and carries no user data, in which case
|
|
20
|
+
* delivery checks the run's expiry instead of reading a payload object.
|
|
21
|
+
*/
|
|
22
|
+
body?: string;
|
|
23
|
+
/** Absolute workflow redelivery deadline; long waits are chained by the consumer. */
|
|
24
|
+
notBefore?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Where the idempotency claim lives. Absent: the claim cell named by queue
|
|
27
|
+
* and key. `run`: an entry in the run's own cell (requires `runId`).
|
|
28
|
+
*/
|
|
29
|
+
claimScope?: 'run';
|
|
30
|
+
/** Failed deliveries carried across suspension re-publishes. */
|
|
31
|
+
deliveryFailures?: number;
|
|
32
|
+
suspensionCount?: number;
|
|
33
|
+
}
|
|
34
|
+
interface NativeQueueSendOptions {
|
|
35
|
+
delaySeconds?: number;
|
|
36
|
+
}
|
|
37
|
+
interface NativeQueueSendResult {
|
|
38
|
+
messageId: string;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { NativeQueueSendOptions as n, NativeQueueSendResult as r, NativeQueueEnvelope as t };
|
|
42
|
+
//# sourceMappingURL=queue-protocol-8iiZ8o_1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-protocol-8iiZ8o_1.d.ts","names":[],"sources":["../src/queue-protocol.ts"],"mappings":";;;;;;;;UAwDiB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA;;EAEA;;;;;EAKA;;EAEA;EACA;;UAae;EACf;;UAGe;EACf"}
|
|
@@ -51,6 +51,9 @@ const LIFECYCLE_COMPACTION_RETRY_MS = 1e3;
|
|
|
51
51
|
/** celld v0.6.0 follows this native Queue producer-delay ceiling. */
|
|
52
52
|
const NATIVE_QUEUE_MAX_DELAY_SECONDS = 86400;
|
|
53
53
|
const NATIVE_QUEUE_MAX_MESSAGE_BYTES = 128e3;
|
|
54
|
+
/** Unconfirmed producer reservations must become recoverable after an interrupted send. */
|
|
55
|
+
const QUEUE_PUBLICATION_LEASE_MS = 3e5;
|
|
56
|
+
const QUEUE_RESERVATION_GRACE_MS = 432e6;
|
|
54
57
|
const QUEUE_PAYLOAD_REGISTRY_PREFIX = "queue-payload:";
|
|
55
58
|
/** Workflow payload fields that carry user data, which run retention must be able to delete. */
|
|
56
59
|
const USER_DATA_FIELDS = [
|
|
@@ -122,6 +125,6 @@ function validateNativeQueueSendOptions(value) {
|
|
|
122
125
|
return delaySeconds === void 0 ? {} : { delaySeconds };
|
|
123
126
|
}
|
|
124
127
|
//#endregion
|
|
125
|
-
export {
|
|
128
|
+
export { strictIntegerSetting as S, QUEUE_CLAIM_STALE_MS as _, isInlineRunBody as a, isRecord as b, queueOrphanName as c, validateNativeQueueEnvelope as d, validateNativeQueueSendOptions as f, MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS as g, LIFECYCLE_COMPACTION_RETRY_MS as h, QUEUE_RESERVATION_GRACE_MS as i, queuePayloadObjectKey as l, HOOK_CLAIM_LEASE_MS as m, QUEUE_PAYLOAD_REGISTRY_PREFIX as n, nativeQueueDelaySeconds as o, CATALOG_FENCE_GRACE_MS as p, QUEUE_PUBLICATION_LEASE_MS as r, queueClaimName as s, NATIVE_QUEUE_MAX_MESSAGE_BYTES as t, queuePayloadRegistryKey as u, isNonNegativeSafeInteger as v, queueDelayDeadline as x, isPositiveSafeInteger as y };
|
|
126
129
|
|
|
127
|
-
//# sourceMappingURL=queue-protocol-
|
|
130
|
+
//# sourceMappingURL=queue-protocol-C1zbXwa_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-protocol-C1zbXwa_.js","names":[],"sources":["../src/validation.ts","../src/lifecycle.ts","../src/queue-protocol.ts"],"sourcesContent":["/** Largest epoch-ms deadline that fits the queue's fixed-width 13-digit keys. */\nexport const MAX_QUEUE_TIMESTAMP_MS = 9_999_999_999_999;\nexport const MAX_QUEUE_DELAY_SECONDS = Math.floor(MAX_QUEUE_TIMESTAMP_MS / 1000);\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function isNonNegativeSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0;\n}\n\nexport function isPositiveSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) > 0;\n}\n\nexport function boundedIntegerOption(\n name: string,\n value: unknown,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (value === undefined) return fallback;\n if (!Number.isSafeInteger(value) || (value as number) < minimum || (value as number) > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value as number;\n}\n\n/**\n * Parse a deployment/runtime integer setting without accepting whitespace,\n * exponents, fractions, or numeric prefixes such as `5junk`.\n */\nexport function strictIntegerSetting(\n name: string,\n raw: string | number | undefined,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (raw === undefined) return fallback;\n const value = typeof raw === 'number' ? raw : /^\\d+$/.test(raw) ? Number(raw) : Number.NaN;\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value;\n}\n\nexport function isValidQueueDelaySeconds(value: unknown, minimum: 0 | 1 = 0): value is number {\n return (\n Number.isSafeInteger(value) &&\n (value as number) >= minimum &&\n (value as number) <= MAX_QUEUE_DELAY_SECONDS\n );\n}\n\nexport function queueDelayDeadline(\n now: number,\n delaySeconds: unknown,\n minimum: 0 | 1 = 0,\n requiredHeadroomMs = 0,\n): number | null {\n if (!isNonNegativeSafeInteger(now) || !isValidQueueDelaySeconds(delaySeconds, minimum)) {\n return null;\n }\n return checkedQueueTimestampAdd(now, delaySeconds * 1000, requiredHeadroomMs);\n}\n\n/**\n * Add an offset to a queue timestamp while preserving its 13-digit key order.\n * Optional headroom reserves space for a later persisted derivative deadline.\n */\nexport function checkedQueueTimestampAdd(\n timestampMs: unknown,\n offsetMs: unknown,\n requiredHeadroomMs = 0,\n): number | null {\n if (\n !isNonNegativeSafeInteger(timestampMs) ||\n !isNonNegativeSafeInteger(offsetMs) ||\n !isNonNegativeSafeInteger(requiredHeadroomMs)\n ) {\n return null;\n }\n const timestamp = timestampMs;\n const offset = offsetMs;\n if (timestamp > MAX_QUEUE_TIMESTAMP_MS || offset > MAX_QUEUE_TIMESTAMP_MS - timestamp) {\n return null;\n }\n const result = timestamp + offset;\n return requiredHeadroomMs <= MAX_QUEUE_TIMESTAMP_MS - result ? result : null;\n}\n","import { MAX_QUEUE_TIMESTAMP_MS } from './validation.js';\n\n/**\n * Hard protocol bounds used by lifecycle leases and derivative-fence cleanup.\n *\n * These are not retention TTLs. They bound how long a request which was\n * admitted before expiry may still mutate a derivative Durable Object:\n *\n * - fleet calls have at most three 5-minute attempts plus bounded retry delay;\n * - one native Queue idempotency claim stays live for at most 15 minutes\n * without a successful delivery or explicit workflow suspension;\n * - hook admission spans reserve retries, one authoritative apply, and\n * finalize retries before the exact claim must be reacquired.\n */\nexport const MAX_FLEET_RPC_TIMEOUT_MS = 5 * 60 * 1000;\nexport const FLEET_IDEMPOTENT_ATTEMPTS = 3;\nexport const FLEET_RETRY_BACKOFF_MAX_MS = 900;\n\nexport const MAX_IDEMPOTENT_RPC_LIFETIME_MS =\n FLEET_IDEMPOTENT_ATTEMPTS * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS;\nexport const MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS =\n MAX_FLEET_RPC_TIMEOUT_MS + MAX_IDEMPOTENT_RPC_LIFETIME_MS;\n\nexport const MAX_QUEUE_DELIVERY_TIMEOUT_MS = 5 * 60 * 1000;\nexport const QUEUE_CLAIM_STALE_MS = 15 * 60 * 1000;\n/** A fresh delivery edge may advance an immediately-due message by one millisecond. */\nexport const QUEUE_ALARM_EDGE_MS = 1;\nexport const MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS = QUEUE_CLAIM_STALE_MS + QUEUE_ALARM_EDGE_MS;\n/** Latest admissible due time with room for a fresh queue claim. */\nexport const MAX_QUEUE_SCHEDULE_TIMESTAMP_MS =\n MAX_QUEUE_TIMESTAMP_MS - MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS;\n\nexport const CATALOG_FENCE_GRACE_MS = MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS;\n\nexport const HOOK_CLAIM_LEASE_MS =\n (FLEET_IDEMPOTENT_ATTEMPTS * 2 + 1) * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS * 2;\n\nexport const LIFECYCLE_COMPACTION_BATCH = 128;\nexport const LIFECYCLE_COMPACTION_RETRY_MS = 1000;\n","import { isNonNegativeSafeInteger, isRecord } from './validation.js';\nimport { MAX_QUEUE_SCHEDULE_TIMESTAMP_MS } from './lifecycle.js';\n\nexport { QUEUE_CLAIM_STALE_MS } from './lifecycle.js';\n\n/** celld v0.6.0 follows this native Queue producer-delay ceiling. */\nexport const NATIVE_QUEUE_MAX_DELAY_SECONDS = 86_400;\nexport const NATIVE_QUEUE_MAX_MESSAGE_BYTES = 128_000;\nexport const MAX_QUEUE_SUSPENSIONS = 256;\n/** Unconfirmed producer reservations must become recoverable after an interrupted send. */\nexport const QUEUE_PUBLICATION_LEASE_MS = 5 * 60 * 1000;\nexport const QUEUE_RESERVATION_GRACE_MS = 5 * 24 * 60 * 60 * 1000;\nexport const QUEUE_PAYLOAD_REGISTRY_PREFIX = 'queue-payload:';\n/** Largest run-bearing body that may travel inline in the broker envelope. */\nexport const MAX_INLINE_RUN_BODY_BYTES = 8 * 1024;\n/** Workflow payload fields that carry user data, which run retention must be able to delete. */\nconst USER_DATA_FIELDS = ['runInput', 'hookInput', 'stepInput'] as const;\n\n/**\n * A run-bearing body may stay inline when it is small and carries no user\n * data: then it holds only IDs, trace context, and metadata, and nothing in it\n * needs run retention to delete it from object storage.\n */\nexport function isInlineRunBody(body: string): boolean {\n if (body.length > MAX_INLINE_RUN_BODY_BYTES) return false;\n if (new TextEncoder().encode(body).byteLength > MAX_INLINE_RUN_BODY_BYTES) return false;\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return false;\n }\n return isRecord(parsed) && USER_DATA_FIELDS.every((field) => parsed[field] === undefined);\n}\n\nexport interface QueuePayloadRegistration {\n messageId: string;\n key: string;\n /** Delete an orphaned resilient-start payload after this deadline. */\n orphanExpiresAt: number;\n}\n\nexport interface QueuePayloadOrphan {\n messageId: string;\n runId: string;\n key: string;\n expiresAt: number;\n}\n\n/**\n * Small broker message carried by celld's native Queue.\n *\n * Run-bearing payload bytes live in object storage so the broker's 128 kB limit does not\n * narrow the Workflow World contract and run retention can delete those bytes\n * without waiting for the Queue's fixed four-day retention window.\n */\nexport interface NativeQueueEnvelope {\n version: 1;\n messageId: string;\n queueName: string;\n targetBaseUrl: string;\n runId?: string;\n idempotencyKey?: string;\n payloadKey?: string;\n /**\n * Inline body. Health checks always travel inline; a run-bearing body may\n * travel inline when it is small and carries no user data, in which case\n * delivery checks the run's expiry instead of reading a payload object.\n */\n body?: string;\n /** Absolute workflow redelivery deadline; long waits are chained by the consumer. */\n notBefore?: number;\n /**\n * Where the idempotency claim lives. Absent: the claim cell named by queue\n * and key. `run`: an entry in the run's own cell (requires `runId`).\n */\n claimScope?: 'run';\n /** Failed deliveries carried across suspension re-publishes. */\n deliveryFailures?: number;\n suspensionCount?: number;\n}\n\n/**\n * Enqueue-side answer from a run cell. `cell`: the run predates run-scoped\n * claims, so its idempotency claims stay in claim cells. `run`: the\n * reservation was made in the run's own cell.\n */\nexport type RunQueueReservation =\n | { ok: false; message: string }\n | { ok: true; scope: 'cell' }\n | { ok: true; scope: 'run'; admitted: boolean; messageId: string; publicationPending?: true };\n\nexport interface NativeQueueSendOptions {\n delaySeconds?: number;\n}\n\nexport interface NativeQueueSendResult {\n messageId: string;\n}\n\nexport function queuePayloadRegistryKey(messageId: string): string {\n return `${QUEUE_PAYLOAD_REGISTRY_PREFIX}${messageId}`;\n}\n\nexport function queuePayloadObjectKey(runId: string, messageId: string): string {\n return `workflow-queue/${encodeURIComponent(runId)}/${encodeURIComponent(messageId)}`;\n}\n\nexport function queueClaimName(queueName: string, idempotencyKey: string): string {\n return `claim:${queueName.length}:${queueName}:${idempotencyKey}`;\n}\n\nexport function queueOrphanName(messageId: string): string {\n return `queue-orphan:${messageId}`;\n}\n\nexport function nativeQueueDelaySeconds(notBefore: number | undefined, now: number): number {\n if (notBefore === undefined || notBefore <= now) return 0;\n return Math.min(NATIVE_QUEUE_MAX_DELAY_SECONDS, Math.ceil((notBefore - now) / 1000));\n}\n\nexport function validateNativeQueueEnvelope(value: unknown): NativeQueueEnvelope {\n if (!isRecord(value)) throw new TypeError('world-celld native queue envelope must be an object');\n if (value.version !== 1)\n throw new TypeError('world-celld native queue envelope version must be 1');\n for (const field of ['messageId', 'queueName', 'targetBaseUrl'] as const) {\n if (typeof value[field] !== 'string' || value[field].length === 0) {\n throw new TypeError(`world-celld native queue envelope ${field} must be a non-empty string`);\n }\n }\n for (const field of ['runId', 'idempotencyKey', 'payloadKey', 'body'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string') {\n throw new TypeError(`world-celld native queue envelope ${field} must be a string`);\n }\n }\n if (value.claimScope !== undefined && (value.claimScope !== 'run' || value.runId === undefined)) {\n throw new TypeError(\"world-celld native queue envelope claimScope must be 'run' with a runId\");\n }\n if ((value.payloadKey === undefined) === (value.body === undefined)) {\n throw new TypeError(\n 'world-celld native queue envelope must contain exactly one payload source',\n );\n }\n for (const field of ['notBefore', 'deliveryFailures', 'suspensionCount'] as const) {\n if (value[field] !== undefined && !isNonNegativeSafeInteger(value[field])) {\n throw new TypeError(\n `world-celld native queue envelope ${field} must be a non-negative safe integer`,\n );\n }\n }\n if (\n value.notBefore !== undefined &&\n (value.notBefore as number) > MAX_QUEUE_SCHEDULE_TIMESTAMP_MS\n ) {\n throw new TypeError(\n `world-celld native queue envelope notBefore must not exceed ${MAX_QUEUE_SCHEDULE_TIMESTAMP_MS}`,\n );\n }\n return value as unknown as NativeQueueEnvelope;\n}\n\nexport function validateNativeQueueSendOptions(value: unknown): NativeQueueSendOptions {\n if (value === undefined) return {};\n if (!isRecord(value)) throw new TypeError('world-celld native queue options must be an object');\n const delaySeconds = value.delaySeconds;\n if (\n delaySeconds !== undefined &&\n (!Number.isSafeInteger(delaySeconds) ||\n (delaySeconds as number) < 0 ||\n (delaySeconds as number) > NATIVE_QUEUE_MAX_DELAY_SECONDS)\n ) {\n throw new TypeError(\n `world-celld native queue delaySeconds must be an integer between 0 and ${NATIVE_QUEUE_MAX_DELAY_SECONDS}`,\n );\n }\n return delaySeconds === undefined ? {} : { delaySeconds: delaySeconds as number };\n}\n"],"mappings":"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"}
|
|
@@ -307,6 +307,7 @@ function checkedQueueTimestampAdd(timestampMs, offsetMs, requiredHeadroomMs = 0)
|
|
|
307
307
|
const MAX_FLEET_RPC_TIMEOUT_MS = 3e5;
|
|
308
308
|
const MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS = 1200900;
|
|
309
309
|
const MAX_QUEUE_DELIVERY_TIMEOUT_MS = 3e5;
|
|
310
|
+
const QUEUE_CLAIM_STALE_MS = 9e5;
|
|
310
311
|
const MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS = 900001;
|
|
311
312
|
/** Latest admissible due time with room for a fresh queue claim. */
|
|
312
313
|
const MAX_QUEUE_SCHEDULE_TIMESTAMP_MS = 9999999099998;
|
|
@@ -661,6 +662,9 @@ function compact(obj) {
|
|
|
661
662
|
/** celld v0.6.0 follows this native Queue producer-delay ceiling. */
|
|
662
663
|
const NATIVE_QUEUE_MAX_DELAY_SECONDS = 86400;
|
|
663
664
|
const NATIVE_QUEUE_MAX_MESSAGE_BYTES = 128e3;
|
|
665
|
+
/** Unconfirmed producer reservations must become recoverable after an interrupted send. */
|
|
666
|
+
const QUEUE_PUBLICATION_LEASE_MS = 3e5;
|
|
667
|
+
const QUEUE_RESERVATION_GRACE_MS = 432e6;
|
|
664
668
|
const QUEUE_PAYLOAD_REGISTRY_PREFIX = "queue-payload:";
|
|
665
669
|
/** Workflow payload fields that carry user data, which run retention must be able to delete. */
|
|
666
670
|
const USER_DATA_FIELDS = [
|
|
@@ -805,6 +809,6 @@ async function listRunsPage(deps, request) {
|
|
|
805
809
|
};
|
|
806
810
|
}
|
|
807
811
|
//#endregion
|
|
808
|
-
export {
|
|
812
|
+
export { normalizeStreamError as $, boundedIntegerOption as A, MAX_STREAM_LONG_POLL_MS as B, HOOK_CLAIM_LEASE_MS as C, MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS as D, MAX_QUEUE_DELIVERY_TIMEOUT_MS as E, queueDelayDeadline as F, STREAM_CHUNK_LIMIT_HEADER as G, MAX_STREAM_READ_CHUNKS as H, strictIntegerSetting as I, decodeStreamWriteResult as J, decodeStreamReadResult as K, MAX_STREAM_BATCH_BYTES as L, isNonNegativeSafeInteger as M, isPositiveSafeInteger as N, MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS as O, isRecord as P, isChunkLimitRejection as Q, MAX_STREAM_CHUNK_BYTES as R, CATALOG_FENCE_GRACE_MS as S, MAX_FLEET_RPC_TIMEOUT_MS as T, MAX_STREAM_WRITE_CHUNKS as U, MAX_STREAM_READ_BYTES as V, STREAM_BATCH_CONTENT_TYPE as W, encodeStreamWriteBatch as X, encodeStreamReadResult as Y, encodeStreamWriteResult as Z, rpcStringify as _, QUEUE_PUBLICATION_LEASE_MS as a, createWorkflowIndex as b, nativeQueueDelaySeconds as c, queuePayloadObjectKey as d, validateStreamReadRequest as et, queuePayloadRegistryKey as f, rpcParse as g, compact as h, QUEUE_PAYLOAD_REGISTRY_PREFIX as i, checkedQueueTimestampAdd as j, QUEUE_CLAIM_STALE_MS as k, queueClaimName as l, validateNativeQueueSendOptions as m, listRunsPage as n, QUEUE_RESERVATION_GRACE_MS as o, validateNativeQueueEnvelope as p, decodeStreamWriteBatch as q, NATIVE_QUEUE_MAX_MESSAGE_BYTES as r, isInlineRunBody as s, MAX_RUN_LIST_LIMIT as t, validateStreamWriteChunks as tt, queueOrphanName as u, parse as v, LIFECYCLE_COMPACTION_RETRY_MS as w, runIndexMetadata as x, stringify as y, MAX_STREAM_ERROR_BYTES as z };
|
|
809
813
|
|
|
810
|
-
//# sourceMappingURL=run-list-
|
|
814
|
+
//# sourceMappingURL=run-list-C4B4SBYW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-list-C987PkJ2.js","names":[],"sources":["../src/stream-protocol.ts","../src/validation.ts","../src/lifecycle.ts","../src/indexes.ts","../src/vendor/shared/serialization.ts","../src/codec.ts","../src/vendor/shared/util.ts","../src/queue-protocol.ts","../src/run-list.ts"],"sourcesContent":["/**\n * Hard-cutover stream protocol shared by the client, Worker router, and\n * StreamDO. Chunk payloads use a compact binary envelope on the public HTTP\n * boundary and Uint8Array values on the DO/storage boundary.\n */\n\nexport const STREAM_BATCH_CONTENT_TYPE = 'application/vnd.world-celld.stream-batch.v1';\n\n/**\n * Chunks per write request that every worker accepts. A client sends larger\n * batches only after a worker advertises {@link STREAM_CHUNK_LIMIT_HEADER}.\n */\nexport const MAX_STREAM_WRITE_CHUNKS = 32;\n/** A chunk remains below the 2 MiB SQLite-backed DO key/value limit. */\nexport const MAX_STREAM_CHUNK_BYTES = 1024 * 1024;\n/** Keeps serialized RPC bodies well below the 32 MiB Workers RPC limit. */\nexport const MAX_STREAM_BATCH_BYTES = 8 * 1024 * 1024;\n/** Chunks per read request that every worker accepts; see {@link MAX_STREAM_WRITE_CHUNKS}. */\nexport const MAX_STREAM_READ_CHUNKS = 32;\n/** Chunks per write or read request accepted by a worker that advertises the header below. */\nexport const NEGOTIATED_STREAM_CHUNKS = 512;\n/** Response header on stream requests: the per-request chunk limit this worker accepts. */\nexport const STREAM_CHUNK_LIMIT_HEADER = 'x-world-celld-stream-chunks';\nexport const MAX_STREAM_READ_BYTES = 8 * 1024 * 1024;\nexport const MAX_STREAM_ERROR_BYTES = 16 * 1024;\n/** Must remain below the default 30 second fleet request deadline. */\nexport const MAX_STREAM_LONG_POLL_MS = 20_000;\n\nexport type StreamTerminalState = 'open' | 'closed' | 'errored' | 'expired';\n\nexport interface StreamErrorData {\n name: string;\n message: string;\n}\n\nexport interface StreamWriteResult {\n startIndex: number;\n count: number;\n tailIndex: number;\n}\n\nexport interface StreamReadRequest {\n runId: string;\n startIndex: number;\n maxChunks: number;\n maxBytes: number;\n waitMs: number;\n}\n\nexport interface StreamReadResult {\n startIndex: number;\n tailIndex: number;\n chunks: Uint8Array[];\n state: StreamTerminalState;\n timedOut: boolean;\n error?: StreamErrorData;\n}\n\nconst WRITE_MAGIC = 0x57435357; // WCSW\nconst WRITE_ACK_MAGIC = 0x57435341; // WCSA\nconst READ_MAGIC = 0x57435352; // WCSR\nconst PROTOCOL_VERSION = 1;\nconst WRITE_HEADER_BYTES = 8;\nconst WRITE_ACK_BYTES = 16;\nconst READ_HEADER_BYTES = 28;\n\nconst STATE_TO_WIRE: Record<StreamTerminalState, number> = {\n open: 0,\n closed: 1,\n errored: 2,\n expired: 3,\n};\n\nconst WIRE_TO_STATE: readonly StreamTerminalState[] = ['open', 'closed', 'errored', 'expired'];\n\nfunction protocolError(message: string): Error {\n const error = new Error(`world-celld: invalid stream protocol: ${message}`);\n error.name = 'StreamProtocolError';\n return error;\n}\n\nfunction requireSafeIndex(value: number, field: string): void {\n if (!Number.isSafeInteger(value) || value < -1 || value > 0x7fffffff) {\n throw protocolError(`${field} is out of range`);\n }\n}\n\n/** An older worker rejects an oversized request before it touches the stream. */\nexport function isChunkLimitRejection(error: unknown): boolean {\n const candidate = error as { status?: unknown; message?: unknown } | null;\n return (\n candidate?.status === 400 &&\n typeof candidate.message === 'string' &&\n /batch exceeds \\d+ chunks|maxChunks must be (?:an integer )?between/.test(candidate.message)\n );\n}\n\nexport function validateStreamWriteChunks(chunks: readonly Uint8Array[]): number {\n if (chunks.length === 0) throw protocolError('batch must contain at least one chunk');\n if (chunks.length > NEGOTIATED_STREAM_CHUNKS) {\n throw protocolError(`batch exceeds ${NEGOTIATED_STREAM_CHUNKS} chunks`);\n }\n\n let totalBytes = 0;\n for (const chunk of chunks) {\n if (!(chunk instanceof Uint8Array)) throw protocolError('chunk is not binary data');\n if (chunk.byteLength > MAX_STREAM_CHUNK_BYTES) {\n throw protocolError(`chunk exceeds ${MAX_STREAM_CHUNK_BYTES} bytes`);\n }\n totalBytes += chunk.byteLength;\n if (totalBytes > MAX_STREAM_BATCH_BYTES) {\n throw protocolError(`batch exceeds ${MAX_STREAM_BATCH_BYTES} bytes`);\n }\n }\n return totalBytes;\n}\n\nexport function validateStreamReadRequest(request: StreamReadRequest): void {\n if (!request.runId) throw protocolError('runId is required');\n if (\n !Number.isSafeInteger(request.startIndex) ||\n request.startIndex < 0 ||\n request.startIndex > 0x7fffffff\n ) {\n throw protocolError('startIndex must be between 0 and 2147483647');\n }\n if (\n !Number.isSafeInteger(request.maxChunks) ||\n request.maxChunks < 0 ||\n request.maxChunks > NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError(`maxChunks must be between 0 and ${NEGOTIATED_STREAM_CHUNKS}`);\n }\n if (\n !Number.isSafeInteger(request.maxBytes) ||\n request.maxBytes < MAX_STREAM_CHUNK_BYTES ||\n request.maxBytes > MAX_STREAM_READ_BYTES\n ) {\n throw protocolError(\n `maxBytes must be between ${MAX_STREAM_CHUNK_BYTES} and ${MAX_STREAM_READ_BYTES}`,\n );\n }\n if (\n !Number.isSafeInteger(request.waitMs) ||\n request.waitMs < 0 ||\n request.waitMs > MAX_STREAM_LONG_POLL_MS\n ) {\n throw protocolError(`waitMs must be between 0 and ${MAX_STREAM_LONG_POLL_MS}`);\n }\n}\n\nexport function encodeStreamWriteBatch(chunks: readonly Uint8Array[]): Uint8Array {\n const totalBytes = validateStreamWriteChunks(chunks);\n const encoded = new Uint8Array(WRITE_HEADER_BYTES + chunks.length * 4 + totalBytes);\n const view = new DataView(encoded.buffer);\n view.setUint32(0, WRITE_MAGIC);\n view.setUint16(4, PROTOCOL_VERSION);\n view.setUint16(6, chunks.length);\n\n let offset = WRITE_HEADER_BYTES;\n for (const chunk of chunks) {\n view.setUint32(offset, chunk.byteLength);\n offset += 4;\n encoded.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return encoded;\n}\n\nexport function decodeStreamWriteBatch(encoded: Uint8Array): Uint8Array[] {\n if (encoded.byteLength < WRITE_HEADER_BYTES) throw protocolError('truncated write header');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== WRITE_MAGIC) throw protocolError('bad write magic');\n if (view.getUint16(4) !== PROTOCOL_VERSION) throw protocolError('unsupported write version');\n const count = view.getUint16(6);\n const chunks: Uint8Array[] = [];\n let offset = WRITE_HEADER_BYTES;\n for (let index = 0; index < count; index++) {\n if (offset + 4 > encoded.byteLength) throw protocolError('truncated chunk length');\n const length = view.getUint32(offset);\n offset += 4;\n if (offset + length > encoded.byteLength) throw protocolError('truncated chunk data');\n // Persisted DO values are structured-cloned. A view would retain the\n // complete batch backing buffer and could exceed the per-value storage\n // limit even when this individual chunk is valid.\n chunks.push(new Uint8Array(encoded.subarray(offset, offset + length)));\n offset += length;\n }\n if (offset !== encoded.byteLength) throw protocolError('trailing write data');\n validateStreamWriteChunks(chunks);\n return chunks;\n}\n\nexport function encodeStreamWriteResult(result: StreamWriteResult): Uint8Array {\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n if (\n !Number.isSafeInteger(result.count) ||\n result.count < 1 ||\n result.count > NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError('write count is out of range');\n }\n const encoded = new Uint8Array(WRITE_ACK_BYTES);\n const view = new DataView(encoded.buffer);\n view.setUint32(0, WRITE_ACK_MAGIC);\n view.setUint16(4, PROTOCOL_VERSION);\n view.setUint16(6, result.count);\n view.setInt32(8, result.startIndex);\n view.setInt32(12, result.tailIndex);\n return encoded;\n}\n\nexport function decodeStreamWriteResult(encoded: Uint8Array): StreamWriteResult {\n if (encoded.byteLength !== WRITE_ACK_BYTES) throw protocolError('invalid write response size');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== WRITE_ACK_MAGIC) throw protocolError('bad write response magic');\n if (view.getUint16(4) !== PROTOCOL_VERSION) {\n throw protocolError('unsupported write response version');\n }\n const count = view.getUint16(6);\n if (count < 1 || count > NEGOTIATED_STREAM_CHUNKS) {\n throw protocolError('write response count is out of range');\n }\n const result = {\n count,\n startIndex: view.getInt32(8),\n tailIndex: view.getInt32(12),\n };\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n if (result.tailIndex !== result.startIndex + result.count - 1) {\n throw protocolError('write response offsets are inconsistent');\n }\n return result;\n}\n\nexport function encodeStreamReadResult(result: StreamReadResult): Uint8Array {\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n let chunkBytes = 0;\n for (const chunk of result.chunks) chunkBytes += 4 + chunk.byteLength;\n if (\n result.chunks.length > NEGOTIATED_STREAM_CHUNKS ||\n chunkBytes > MAX_STREAM_READ_BYTES + 4 * NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError('read result exceeds configured bounds');\n }\n\n const encoder = new TextEncoder();\n const errorName = result.error ? encoder.encode(result.error.name) : new Uint8Array();\n const errorMessage = result.error ? encoder.encode(result.error.message) : new Uint8Array();\n if (errorName.byteLength + errorMessage.byteLength > MAX_STREAM_ERROR_BYTES) {\n throw protocolError(`stream error exceeds ${MAX_STREAM_ERROR_BYTES} bytes`);\n }\n const encoded = new Uint8Array(\n READ_HEADER_BYTES + chunkBytes + errorName.byteLength + errorMessage.byteLength,\n );\n const view = new DataView(encoded.buffer);\n view.setUint32(0, READ_MAGIC);\n view.setUint8(4, PROTOCOL_VERSION);\n const state = STATE_TO_WIRE[result.state];\n if (state === undefined) throw protocolError('unknown stream state');\n view.setUint8(5, state);\n view.setUint8(6, result.timedOut ? 1 : 0);\n view.setUint8(7, 0);\n view.setInt32(8, result.startIndex);\n view.setInt32(12, result.tailIndex);\n view.setUint32(16, result.chunks.length);\n view.setUint32(20, errorName.byteLength);\n view.setUint32(24, errorMessage.byteLength);\n\n let offset = READ_HEADER_BYTES;\n for (const chunk of result.chunks) {\n view.setUint32(offset, chunk.byteLength);\n offset += 4;\n encoded.set(chunk, offset);\n offset += chunk.byteLength;\n }\n encoded.set(errorName, offset);\n offset += errorName.byteLength;\n encoded.set(errorMessage, offset);\n return encoded;\n}\n\nexport function decodeStreamReadResult(encoded: Uint8Array): StreamReadResult {\n if (encoded.byteLength < READ_HEADER_BYTES) throw protocolError('truncated read header');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== READ_MAGIC) throw protocolError('bad read magic');\n if (view.getUint8(4) !== PROTOCOL_VERSION) throw protocolError('unsupported read version');\n const state = WIRE_TO_STATE[view.getUint8(5)];\n if (!state) throw protocolError('unknown stream state');\n const startIndex = view.getInt32(8);\n const tailIndex = view.getInt32(12);\n requireSafeIndex(startIndex, 'startIndex');\n requireSafeIndex(tailIndex, 'tailIndex');\n const count = view.getUint32(16);\n const errorNameLength = view.getUint32(20);\n const errorMessageLength = view.getUint32(24);\n if (count > NEGOTIATED_STREAM_CHUNKS) throw protocolError('read chunk count exceeds limit');\n if (errorNameLength + errorMessageLength > MAX_STREAM_ERROR_BYTES) {\n throw protocolError('read error exceeds limit');\n }\n\n const chunks: Uint8Array[] = [];\n let offset = READ_HEADER_BYTES;\n let totalBytes = 0;\n for (let index = 0; index < count; index++) {\n if (offset + 4 > encoded.byteLength) throw protocolError('truncated read chunk length');\n const length = view.getUint32(offset);\n offset += 4;\n if (offset + length > encoded.byteLength) throw protocolError('truncated read chunk data');\n totalBytes += length;\n if (totalBytes > MAX_STREAM_READ_BYTES) throw protocolError('read bytes exceed limit');\n chunks.push(encoded.subarray(offset, offset + length));\n offset += length;\n }\n\n if (offset + errorNameLength + errorMessageLength !== encoded.byteLength) {\n throw protocolError('invalid read error payload');\n }\n const decoder = new TextDecoder();\n const error =\n errorNameLength > 0 || errorMessageLength > 0\n ? {\n name: decoder.decode(encoded.subarray(offset, offset + errorNameLength)),\n message: decoder.decode(encoded.subarray(offset + errorNameLength)),\n }\n : undefined;\n\n return {\n startIndex,\n tailIndex,\n chunks,\n state,\n timedOut: (view.getUint8(6) & 1) !== 0,\n error,\n };\n}\n\nexport function normalizeStreamError(error: unknown): StreamErrorData {\n let normalized: StreamErrorData;\n if (error instanceof Error) {\n normalized = { name: error.name || 'Error', message: error.message };\n } else if (typeof error === 'string') {\n normalized = { name: 'Error', message: error };\n } else if (\n error &&\n typeof error === 'object' &&\n typeof (error as { name?: unknown }).name === 'string' &&\n typeof (error as { message?: unknown }).message === 'string'\n ) {\n normalized = {\n name: (error as StreamErrorData).name,\n message: (error as StreamErrorData).message,\n };\n } else {\n normalized = { name: 'Error', message: String(error) };\n }\n\n // Bound persisted terminal metadata as well as its binary response frame.\n normalized.name = normalized.name.slice(0, 1024);\n normalized.message = normalized.message.slice(0, 4096);\n while (\n new TextEncoder().encode(normalized.name).byteLength +\n new TextEncoder().encode(normalized.message).byteLength >\n MAX_STREAM_ERROR_BYTES\n ) {\n normalized.message = normalized.message.slice(0, Math.max(0, normalized.message.length - 256));\n if (normalized.message.length === 0) {\n normalized.name = normalized.name.slice(0, Math.max(0, normalized.name.length - 256));\n }\n }\n return normalized;\n}\n","/** Largest epoch-ms deadline that fits the queue's fixed-width 13-digit keys. */\nexport const MAX_QUEUE_TIMESTAMP_MS = 9_999_999_999_999;\nexport const MAX_QUEUE_DELAY_SECONDS = Math.floor(MAX_QUEUE_TIMESTAMP_MS / 1000);\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function isNonNegativeSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0;\n}\n\nexport function isPositiveSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) > 0;\n}\n\nexport function boundedIntegerOption(\n name: string,\n value: unknown,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (value === undefined) return fallback;\n if (!Number.isSafeInteger(value) || (value as number) < minimum || (value as number) > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value as number;\n}\n\n/**\n * Parse a deployment/runtime integer setting without accepting whitespace,\n * exponents, fractions, or numeric prefixes such as `5junk`.\n */\nexport function strictIntegerSetting(\n name: string,\n raw: string | number | undefined,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (raw === undefined) return fallback;\n const value = typeof raw === 'number' ? raw : /^\\d+$/.test(raw) ? Number(raw) : Number.NaN;\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value;\n}\n\nexport function isValidQueueDelaySeconds(value: unknown, minimum: 0 | 1 = 0): value is number {\n return (\n Number.isSafeInteger(value) &&\n (value as number) >= minimum &&\n (value as number) <= MAX_QUEUE_DELAY_SECONDS\n );\n}\n\nexport function queueDelayDeadline(\n now: number,\n delaySeconds: unknown,\n minimum: 0 | 1 = 0,\n requiredHeadroomMs = 0,\n): number | null {\n if (!isNonNegativeSafeInteger(now) || !isValidQueueDelaySeconds(delaySeconds, minimum)) {\n return null;\n }\n return checkedQueueTimestampAdd(now, delaySeconds * 1000, requiredHeadroomMs);\n}\n\n/**\n * Add an offset to a queue timestamp while preserving its 13-digit key order.\n * Optional headroom reserves space for a later persisted derivative deadline.\n */\nexport function checkedQueueTimestampAdd(\n timestampMs: unknown,\n offsetMs: unknown,\n requiredHeadroomMs = 0,\n): number | null {\n if (\n !isNonNegativeSafeInteger(timestampMs) ||\n !isNonNegativeSafeInteger(offsetMs) ||\n !isNonNegativeSafeInteger(requiredHeadroomMs)\n ) {\n return null;\n }\n const timestamp = timestampMs;\n const offset = offsetMs;\n if (timestamp > MAX_QUEUE_TIMESTAMP_MS || offset > MAX_QUEUE_TIMESTAMP_MS - timestamp) {\n return null;\n }\n const result = timestamp + offset;\n return requiredHeadroomMs <= MAX_QUEUE_TIMESTAMP_MS - result ? result : null;\n}\n","import { MAX_QUEUE_TIMESTAMP_MS } from './validation.js';\n\n/**\n * Hard protocol bounds used by lifecycle leases and derivative-fence cleanup.\n *\n * These are not retention TTLs. They bound how long a request which was\n * admitted before expiry may still mutate a derivative Durable Object:\n *\n * - fleet calls have at most three 5-minute attempts plus bounded retry delay;\n * - one native Queue idempotency claim stays live for at most 15 minutes\n * without a successful delivery or explicit workflow suspension;\n * - hook admission spans reserve retries, one authoritative apply, and\n * finalize retries before the exact claim must be reacquired.\n */\nexport const MAX_FLEET_RPC_TIMEOUT_MS = 5 * 60 * 1000;\nexport const FLEET_IDEMPOTENT_ATTEMPTS = 3;\nexport const FLEET_RETRY_BACKOFF_MAX_MS = 900;\n\nexport const MAX_IDEMPOTENT_RPC_LIFETIME_MS =\n FLEET_IDEMPOTENT_ATTEMPTS * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS;\nexport const MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS =\n MAX_FLEET_RPC_TIMEOUT_MS + MAX_IDEMPOTENT_RPC_LIFETIME_MS;\n\nexport const MAX_QUEUE_DELIVERY_TIMEOUT_MS = 5 * 60 * 1000;\nexport const QUEUE_CLAIM_STALE_MS = 15 * 60 * 1000;\n/** A fresh delivery edge may advance an immediately-due message by one millisecond. */\nexport const QUEUE_ALARM_EDGE_MS = 1;\nexport const MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS = QUEUE_CLAIM_STALE_MS + QUEUE_ALARM_EDGE_MS;\n/** Latest admissible due time with room for a fresh queue claim. */\nexport const MAX_QUEUE_SCHEDULE_TIMESTAMP_MS =\n MAX_QUEUE_TIMESTAMP_MS - MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS;\n\nexport const CATALOG_FENCE_GRACE_MS = MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS;\n\nexport const HOOK_CLAIM_LEASE_MS =\n (FLEET_IDEMPOTENT_ATTEMPTS * 2 + 1) * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS * 2;\n\nexport const LIFECYCLE_COMPACTION_BATCH = 128;\nexport const LIFECYCLE_COMPACTION_RETRY_MS = 1000;\n","import type { RunListPage, RunListRequest } from './run-list.js';\nimport type { WorkflowRun } from '@workflow/world';\nimport type { HookTokenOwner } from './config.js';\nimport type {\n ExpireRunIndexesRequest,\n ExpireRunIndexesResult,\n ReleaseHookIndexesRequest,\n ReleaseHookIndexesResult,\n} from './retention.js';\n\nexport const RUN_CATALOG_SHARDS = 16;\nexport const HOOK_TOKEN_SHARDS = 32;\nexport const HOOK_ID_SHARDS = 32;\n\nconst INDEX_PROTOCOL_VERSION = 'v1';\nconst HOOK_RELEASE_BATCH = 64;\n\nexport interface IndexListOptions {\n prefix?: string;\n cursor?: string;\n /** Exclusive upper bound for creation-time retention scans. */\n end?: string;\n limit?: number;\n reverse?: boolean;\n}\n\nexport interface IndexListPage {\n /** sourceShard is populated by the merged fleet index for exact follow-up mutation. */\n keys: Array<{ name: string; value: string; sourceShard?: string }>;\n list_complete: boolean;\n cursor?: string;\n}\n\nexport interface RunCatalogShardStub {\n upsertRun(\n runId: string,\n keys: string[],\n serializedMetadata: string,\n publicationExpiresAt: number,\n ): Promise<{ stored: boolean }>;\n list(options?: IndexListOptions): Promise<IndexListPage>;\n deleteStaleGlobalRun(\n runId: string,\n key: string,\n expectedValue: string,\n ): Promise<{ deleted: boolean }>;\n expireRun(runId: string, expiredAt: number): Promise<ExpireRunIndexesResult>;\n}\n\nexport type HookClaimResult =\n | { claimed: true; claimId: string }\n | { claimed: false; holder: HookTokenOwner };\n\nexport interface HookReservation {\n claimId: string;\n tokenClaimId?: string;\n hookIdClaimId?: string;\n}\n\nexport type HookReservationResult =\n | { admitted: true; reservation: HookReservation }\n | { admitted: false; holder: HookTokenOwner };\n\nexport interface HookTokenShardStub {\n get(token: string): Promise<string | null>;\n reserve(token: string, owner: HookTokenOwner, proposedClaimId: string): Promise<HookClaimResult>;\n finalize(\n token: string,\n serializedHook: string,\n owner: HookTokenOwner,\n claimId?: string,\n ): Promise<{ stored: boolean }>;\n releaseClaim(token: string, owner: HookTokenOwner, claimId: string): Promise<void>;\n releaseBatch(\n hooks: Array<{ token: string; owner: HookTokenOwner }>,\n ): Promise<{ deleted: number }>;\n}\n\nexport interface HookIdShardStub {\n get(hookId: string): Promise<string | null>;\n reserve(hookId: string, owner: HookTokenOwner, proposedClaimId: string): Promise<HookClaimResult>;\n publish(\n hookId: string,\n serializedHook: string,\n owner: HookTokenOwner,\n claimId?: string,\n ): Promise<{ stored: boolean }>;\n releaseClaim(hookId: string, owner: HookTokenOwner, claimId: string): Promise<void>;\n releaseBatch(\n hooks: Array<{ hookId: string; owner: HookTokenOwner }>,\n ): Promise<{ deleted: number }>;\n}\n\ninterface CellIdLike {\n toString(): string;\n}\n\nexport interface CellNamespaceLike<T> {\n idFromName(name: string): CellIdLike;\n get(id: CellIdLike): T;\n}\n\nexport interface WorkflowIndexBindings {\n runCatalog: CellNamespaceLike<RunCatalogShardStub>;\n hookTokens: CellNamespaceLike<HookTokenShardStub>;\n hookIds: CellNamespaceLike<HookIdShardStub>;\n}\n\n/** High-level client used by the World storage layer and retention coordinator. */\nexport interface WorkflowIndex {\n commitRun(\n run: WorkflowRun,\n serializedMetadata: string,\n publicationExpiresAt: number,\n ): Promise<{ stored: boolean }>;\n listRuns(options?: IndexListOptions): Promise<IndexListPage>;\n /**\n * Remote only: the complete run listing performed inside the fleet. Resolves\n * to null when the worker predates the route; the caller then lists itself.\n */\n listResolvedRuns?(request: RunListRequest): Promise<RunListPage | null>;\n getHookByToken(token: string): Promise<string | null>;\n getHookById(hookId: string): Promise<string | null>;\n reserveHook(token: string, owner: HookTokenOwner): Promise<HookReservationResult>;\n finalizeHookIndexes(\n token: string,\n hookId: string,\n serializedHook: string,\n owner: HookTokenOwner,\n reservation?: HookReservation,\n ): Promise<void>;\n releaseHookReservation(\n token: string,\n owner: HookTokenOwner,\n reservation: HookReservation,\n ): Promise<void>;\n releaseHookIndexes(request: ReleaseHookIndexesRequest): Promise<ReleaseHookIndexesResult>;\n expireRun(request: ExpireRunIndexesRequest): Promise<ExpireRunIndexesResult>;\n}\n\n/** Stable FNV-1a routing hash. Collisions share a shard but never a storage key. */\nexport function stableIndexHash(value: string): number {\n let hash = 0x811c9dc5;\n for (const byte of new TextEncoder().encode(value)) {\n hash ^= byte;\n hash = Math.imul(hash, 0x01000193);\n }\n return hash >>> 0;\n}\n\nfunction shardName(domain: string, value: string, cardinality: number): string {\n const width = Math.max(2, (cardinality - 1).toString(16).length);\n const shard = stableIndexHash(value) % cardinality;\n return `${domain}:${INDEX_PROTOCOL_VERSION}:${shard.toString(16).padStart(width, '0')}`;\n}\n\nexport function runCatalogShardName(runId: string): string {\n return shardName('run-catalog', runId, RUN_CATALOG_SHARDS);\n}\n\nexport function hookTokenShardName(token: string): string {\n return shardName('hook-token', token, HOOK_TOKEN_SHARDS);\n}\n\nexport function hookIdShardName(hookId: string): string {\n return shardName('hook-id', hookId, HOOK_ID_SHARDS);\n}\n\nexport function allRunCatalogShardNames(): string[] {\n return Array.from(\n { length: RUN_CATALOG_SHARDS },\n (_, shard) => `run-catalog:${INDEX_PROTOCOL_VERSION}:${shard.toString(16).padStart(2, '0')}`,\n );\n}\n\n/** Catalog metadata for a run; the client and the worker router must agree on it. */\nexport function runIndexMetadata(run: Pick<WorkflowRun, 'runId' | 'createdAt' | 'status'>): string {\n return JSON.stringify({\n runId: run.runId,\n createdAt: run.createdAt.toISOString(),\n status: run.status,\n });\n}\n\nfunction stub<T>(namespace: CellNamespaceLike<T>, name: string): T {\n return namespace.get(namespace.idFromName(name));\n}\n\nfunction runKeys(run: Pick<WorkflowRun, 'runId' | 'workflowName' | 'createdAt'>): string[] {\n const timestamp = run.createdAt.getTime().toString().padStart(13, '0');\n return [`run:${run.workflowName}:${timestamp}:${run.runId}`, `runall:${timestamp}:${run.runId}`];\n}\n\nfunction groupByShard<T>(values: T[], route: (value: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const value of values) {\n const name = route(value);\n const group = groups.get(name);\n if (group) group.push(value);\n else groups.set(name, [value]);\n }\n return groups;\n}\n\nfunction sameOwner(left: HookTokenOwner, right: HookTokenOwner): boolean {\n return left.runId === right.runId && left.hookId === right.hookId;\n}\n\nfunction compareBytes(left: Uint8Array, right: Uint8Array): number {\n const length = Math.min(left.byteLength, right.byteLength);\n for (let index = 0; index < length; index++) {\n const difference = left[index] - right[index];\n if (difference !== 0) return difference;\n }\n return left.byteLength - right.byteLength;\n}\n\nasync function inBatches<T>(\n values: T[],\n operation: (batch: T[]) => Promise<{ deleted: number }>,\n): Promise<number> {\n let deleted = 0;\n for (let offset = 0; offset < values.length; offset += HOOK_RELEASE_BATCH) {\n deleted += (await operation(values.slice(offset, offset + HOOK_RELEASE_BATCH))).deleted;\n }\n return deleted;\n}\n\nexport function createWorkflowIndex(bindings: WorkflowIndexBindings): WorkflowIndex {\n const releaseHooks = async (request: ReleaseHookIndexesRequest): Promise<number> => {\n const tokenGroups = groupByShard(request.hooks, (hook) => hookTokenShardName(hook.token));\n const idGroups = groupByShard(request.hooks, (hook) => hookIdShardName(hook.hookId));\n const releases: Array<Promise<number>> = [];\n for (const [name, hooks] of tokenGroups) {\n const target = stub(bindings.hookTokens, name);\n releases.push(\n inBatches(\n hooks.map((hook) => ({\n token: hook.token,\n owner: { runId: request.runId, hookId: hook.hookId },\n })),\n (batch) => target.releaseBatch(batch),\n ),\n );\n }\n for (const [name, hooks] of idGroups) {\n const target = stub(bindings.hookIds, name);\n releases.push(\n inBatches(\n hooks.map((hook) => ({\n hookId: hook.hookId,\n owner: { runId: request.runId, hookId: hook.hookId },\n })),\n (batch) => target.releaseBatch(batch),\n ),\n );\n }\n return (await Promise.all(releases)).reduce((total, count) => total + count, 0);\n };\n\n return {\n async commitRun(run, serializedMetadata, publicationExpiresAt) {\n return await stub(bindings.runCatalog, runCatalogShardName(run.runId)).upsertRun(\n run.runId,\n runKeys(run),\n serializedMetadata,\n publicationExpiresAt,\n );\n },\n\n async listRuns(options) {\n const suppliedLimit = options?.limit;\n const requestedLimit =\n typeof suppliedLimit === 'number' && Number.isFinite(suppliedLimit)\n ? Math.floor(suppliedLimit)\n : 1000;\n const limit = Math.min(1000, Math.max(1, requestedLimit));\n const shardNames = allRunCatalogShardNames();\n const pages = await Promise.all(\n shardNames.map((name) =>\n stub(bindings.runCatalog, name).list({ ...options, limit: limit + 1 }),\n ),\n );\n const encoder = new TextEncoder();\n const candidates = pages\n .flatMap((shardPage, shardIndex) =>\n shardPage.keys.map((entry) => ({\n entry: { ...entry, sourceShard: shardNames[shardIndex] },\n encodedName: encoder.encode(entry.name),\n })),\n )\n .toSorted((left, right) => {\n const compared = compareBytes(left.encodedName, right.encodedName);\n return options?.reverse ? -compared : compared;\n });\n const page = candidates.slice(0, limit).map(({ entry }) => entry);\n const listComplete =\n candidates.length <= limit && pages.every((entry) => entry.list_complete);\n return {\n keys: page,\n list_complete: listComplete,\n cursor: listComplete ? undefined : page.at(-1)?.name,\n };\n },\n\n getHookByToken(token) {\n return stub(bindings.hookTokens, hookTokenShardName(token)).get(token);\n },\n\n getHookById(hookId) {\n return stub(bindings.hookIds, hookIdShardName(hookId)).get(hookId);\n },\n\n async reserveHook(token, owner) {\n const proposedClaimId = crypto.randomUUID();\n const tokenTarget = stub(bindings.hookTokens, hookTokenShardName(token));\n const tokenClaim = await tokenTarget.reserve(token, owner, proposedClaimId);\n if (!tokenClaim.claimed && !sameOwner(tokenClaim.holder, owner)) {\n return { admitted: false, holder: tokenClaim.holder };\n }\n\n const tokenClaimId = tokenClaim.claimed ? tokenClaim.claimId : undefined;\n const hookIdTarget = stub(bindings.hookIds, hookIdShardName(owner.hookId));\n const sharedClaimId = tokenClaimId ?? proposedClaimId;\n let hookIdClaim: HookClaimResult;\n try {\n hookIdClaim = await hookIdTarget.reserve(owner.hookId, owner, sharedClaimId);\n } catch (error) {\n await Promise.allSettled([\n ...(tokenClaimId ? [tokenTarget.releaseClaim(token, owner, tokenClaimId)] : []),\n hookIdTarget.releaseClaim(owner.hookId, owner, sharedClaimId),\n ]);\n throw error;\n }\n if (!hookIdClaim.claimed) {\n if (tokenClaimId) await tokenTarget.releaseClaim(token, owner, tokenClaimId);\n return { admitted: false, holder: hookIdClaim.holder };\n }\n\n const reservation: HookReservation = {\n claimId: `${tokenClaimId ?? '-'}:${hookIdClaim.claimId}`,\n tokenClaimId,\n hookIdClaimId: hookIdClaim.claimId,\n };\n return { admitted: true, reservation };\n },\n\n async finalizeHookIndexes(token, hookId, serializedHook, owner, reservation) {\n const tokenResult = await stub(bindings.hookTokens, hookTokenShardName(token)).finalize(\n token,\n serializedHook,\n owner,\n reservation?.tokenClaimId,\n );\n if (!tokenResult.stored) return;\n await stub(bindings.hookIds, hookIdShardName(hookId)).publish(\n hookId,\n serializedHook,\n owner,\n reservation?.hookIdClaimId,\n );\n },\n\n async releaseHookReservation(token, owner, reservation) {\n const releases: Array<Promise<void>> = [];\n if (reservation.tokenClaimId) {\n releases.push(\n stub(bindings.hookTokens, hookTokenShardName(token)).releaseClaim(\n token,\n owner,\n reservation.tokenClaimId,\n ),\n );\n }\n if (reservation.hookIdClaimId) {\n releases.push(\n stub(bindings.hookIds, hookIdShardName(owner.hookId)).releaseClaim(\n owner.hookId,\n owner,\n reservation.hookIdClaimId,\n ),\n );\n }\n await Promise.all(releases);\n },\n\n async releaseHookIndexes(request) {\n return { deleted: await releaseHooks(request) };\n },\n\n async expireRun(request) {\n const [catalog, hookDeletes] = await Promise.all([\n stub(bindings.runCatalog, runCatalogShardName(request.runId)).expireRun(\n request.runId,\n request.expiredAt,\n ),\n releaseHooks({ runId: request.runId, hooks: request.hooks }),\n ]);\n return { deleted: catalog.deleted + hookDeletes };\n },\n };\n}\n","/** Standard Date fields used across all worlds */\nexport const DATE_FIELDS = new Set([\n 'createdAt',\n 'updatedAt',\n 'startedAt',\n 'completedAt',\n 'retryAfter',\n] as const);\n\n/**\n * JSON reviver that converts ISO date strings to Date objects.\n * Use with JSON.parse(json, dateReviver).\n */\nexport function dateReviver(key: string, value: unknown): unknown {\n if (\n DATE_FIELDS.has(key as typeof DATE_FIELDS extends Set<infer T> ? T : never) &&\n typeof value === 'string'\n ) {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? value : date;\n }\n return value;\n}\n\n/**\n * Base64 helpers. Modified vs upstream: implemented without Buffer so this\n * module is safe inside the celld worker bundle (workerd has no Buffer\n * global). Uses the native Uint8Array base64 methods where the runtime has\n * them (Node >= 25, current V8) and falls back to atob/btoa elsewhere.\n */\nconst nativeToBase64 = (\n Uint8Array.prototype as Uint8Array & { toBase64?: (this: Uint8Array) => string }\n).toBase64;\nconst nativeFromBase64 = (Uint8Array as { fromBase64?: (text: string) => Uint8Array }).fromBase64;\n\n/** Small enough to stay far below engine argument-count limits and fast to spread. */\nconst FALLBACK_ENCODE_CHUNK = 0x1000;\n\n/** @internal Exported for tests; use b64encode. */\nexport function b64encodeFallback(bytes: Uint8Array): string {\n let bin = '';\n for (let i = 0; i < bytes.length; i += FALLBACK_ENCODE_CHUNK) {\n bin += String.fromCharCode.apply(\n null,\n bytes.subarray(i, i + FALLBACK_ENCODE_CHUNK) as unknown as number[],\n );\n }\n return btoa(bin);\n}\n\n/** @internal Exported for tests; use b64decode. */\nexport function b64decodeFallback(text: string): Uint8Array {\n const bin = atob(text);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) {\n out[i] = bin.charCodeAt(i);\n }\n return out;\n}\n\nexport function b64encode(bytes: Uint8Array): string {\n return nativeToBase64 ? nativeToBase64.call(bytes) : b64encodeFallback(bytes);\n}\n\nexport function b64decode(text: string): Uint8Array {\n return nativeFromBase64 ? nativeFromBase64(text) : b64decodeFallback(text);\n}\n\n/**\n * JSON replacer that encodes Uint8Array as a tagged object with base64 data.\n */\nexport function uint8ArrayReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Uint8Array) {\n return {\n __type: 'Uint8Array',\n data: b64encode(value),\n };\n }\n return value;\n}\n\n/**\n * JSON reviver that decodes tagged Uint8Array objects and ISO date strings.\n * Supports both:\n * - New format: { __type: 'Uint8Array', data: '<base64>' }\n * - Legacy format: { __uint8array: true, data: [1, 2, 3] }\n */\nexport function uint8ArrayReviver(key: string, value: unknown): unknown {\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // New format: base64-encoded\n if (obj.__type === 'Uint8Array') {\n if (typeof obj.data !== 'string') throw new SyntaxError('Malformed Uint8Array tag');\n try {\n return b64decode(obj.data);\n } catch {\n throw new SyntaxError('Malformed Uint8Array tag');\n }\n }\n // Legacy format: number array (backwards compat with NATS JetStream data)\n if (obj.__uint8array === true) {\n if (\n !Array.isArray(obj.data) ||\n !obj.data.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)\n ) {\n throw new SyntaxError('Malformed legacy Uint8Array tag');\n }\n return new Uint8Array(obj.data);\n }\n }\n return dateReviver(key, value);\n}\n\n/** Stringify with Uint8Array support. */\nexport function stringify(value: unknown): string {\n return JSON.stringify(value, uint8ArrayReplacer);\n}\n\n/** Parse with Uint8Array and Date support. */\nexport function parse<T>(text: string): T {\n return JSON.parse(text, uint8ArrayReviver) as T;\n}\n\n/** Deep clone using structuredClone */\nexport function deepClone<T>(value: T): T {\n return structuredClone(value);\n}\n","/**\n * RPC wire codec for the Node client <-> worker router HTTP boundary.\n *\n * Extends the shared tagged-JSON format (`{__type:'Uint8Array', data}` +\n * DATE_FIELDS revival) with explicitly tagged Dates: on Cloudflare the DO RPC\n * boundary is structured clone, which preserves EVERY Date — including ones\n * outside the well-known DATE_FIELDS (e.g. inside applyEvent outcomes and\n * user payloads). The HTTP hop must preserve them too, so Dates travel as\n * `{__type:'Date', iso}`.\n *\n * Runs on both sides of the wire, including inside the celld worker — so no\n * Node built-ins (Buffer): base64 uses the native Uint8Array methods or\n * atob/btoa.\n */\nimport { b64decode, b64encode, dateReviver } from './vendor/shared/serialization.js';\n\nfunction rpcReplacer(this: unknown, key: string, value: unknown): unknown {\n // JSON.stringify invokes Date.toJSON before the replacer sees the value;\n // recover the original from the holder object.\n const original =\n this && typeof this === 'object' ? (this as Record<string, unknown>)[key] : undefined;\n if (original instanceof Date) {\n return { __type: 'Date', iso: original.toISOString() };\n }\n if (value instanceof Uint8Array) {\n return { __type: 'Uint8Array', data: b64encode(value) };\n }\n return value;\n}\n\nfunction rpcReviver(key: string, value: unknown): unknown {\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n if (obj.__type === 'Date') {\n if (typeof obj.iso !== 'string') throw new SyntaxError('Malformed Date tag');\n const date = new Date(obj.iso);\n if (Number.isNaN(date.getTime())) throw new SyntaxError('Malformed Date tag');\n return date;\n }\n if (obj.__type === 'Uint8Array') {\n if (typeof obj.data !== 'string') throw new SyntaxError('Malformed Uint8Array tag');\n try {\n return b64decode(obj.data);\n } catch {\n throw new SyntaxError('Malformed Uint8Array tag');\n }\n }\n }\n // Fallback shared-codec semantics for untagged ISO strings in DATE_FIELDS.\n return dateReviver(key, value);\n}\n\nexport function rpcStringify(value: unknown): string {\n return JSON.stringify(value, rpcReplacer);\n}\n\nexport function rpcParse<T>(text: string): T {\n return JSON.parse(text, rpcReviver) as T;\n}\n","export class Mutex {\n promise: Promise<unknown> = Promise.resolve();\n andThen<T>(fn: () => Promise<T> | T): Promise<T> {\n this.promise = this.promise.then(\n () => fn(),\n () => fn(),\n );\n return this.promise as Promise<T>;\n }\n}\n\nexport function compact<T extends object>(obj: T) {\n const value = {} as {\n [key in keyof T]: null extends T[key] ? undefined | NonNullable<T[key]> : T[key];\n };\n for (const key in obj) {\n if (obj[key] !== null) {\n value[key] = obj[key] as any;\n } else {\n value[key] = undefined as any;\n }\n }\n return value;\n}\n\n/**\n * Reference counting helper for managing resource lifecycle\n */\nexport class Rc {\n private count = 0;\n private disposeFn?: () => void | Promise<void>;\n\n constructor(disposeFn?: () => void | Promise<void>) {\n this.disposeFn = disposeFn;\n }\n\n inc(): void {\n this.count++;\n }\n\n async dec(): Promise<void> {\n this.count--;\n if (this.count === 0 && this.disposeFn) {\n await this.disposeFn();\n }\n }\n\n getCount(): number {\n return this.count;\n }\n}\n","import { isNonNegativeSafeInteger, isRecord } from './validation.js';\nimport { MAX_QUEUE_SCHEDULE_TIMESTAMP_MS } from './lifecycle.js';\n\nexport { QUEUE_CLAIM_STALE_MS } from './lifecycle.js';\n\n/** celld v0.6.0 follows this native Queue producer-delay ceiling. */\nexport const NATIVE_QUEUE_MAX_DELAY_SECONDS = 86_400;\nexport const NATIVE_QUEUE_MAX_MESSAGE_BYTES = 128_000;\nexport const MAX_QUEUE_SUSPENSIONS = 256;\nexport const QUEUE_PAYLOAD_REGISTRY_PREFIX = 'queue-payload:';\n/** Largest run-bearing body that may travel inline in the broker envelope. */\nexport const MAX_INLINE_RUN_BODY_BYTES = 8 * 1024;\n/** Workflow payload fields that carry user data, which run retention must be able to delete. */\nconst USER_DATA_FIELDS = ['runInput', 'hookInput', 'stepInput'] as const;\n\n/**\n * A run-bearing body may stay inline when it is small and carries no user\n * data: then it holds only IDs, trace context, and metadata, and nothing in it\n * needs run retention to delete it from object storage.\n */\nexport function isInlineRunBody(body: string): boolean {\n if (body.length > MAX_INLINE_RUN_BODY_BYTES) return false;\n if (new TextEncoder().encode(body).byteLength > MAX_INLINE_RUN_BODY_BYTES) return false;\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return false;\n }\n return isRecord(parsed) && USER_DATA_FIELDS.every((field) => parsed[field] === undefined);\n}\n\nexport interface QueuePayloadRegistration {\n messageId: string;\n key: string;\n /** Delete an orphaned resilient-start payload after this deadline. */\n orphanExpiresAt: number;\n}\n\nexport interface QueuePayloadOrphan {\n messageId: string;\n runId: string;\n key: string;\n expiresAt: number;\n}\n\n/**\n * Small broker message carried by celld's native Queue.\n *\n * Run-bearing payload bytes live in object storage so the broker's 128 kB limit does not\n * narrow the Workflow World contract and run retention can delete those bytes\n * without waiting for the Queue's fixed four-day retention window.\n */\nexport interface NativeQueueEnvelope {\n version: 1;\n messageId: string;\n queueName: string;\n targetBaseUrl: string;\n runId?: string;\n idempotencyKey?: string;\n payloadKey?: string;\n /**\n * Inline body. Health checks always travel inline; a run-bearing body may\n * travel inline when it is small and carries no user data, in which case\n * delivery checks the run's expiry instead of reading a payload object.\n */\n body?: string;\n /** Absolute workflow redelivery deadline; long waits are chained by the consumer. */\n notBefore?: number;\n /**\n * Where the idempotency claim lives. Absent: the claim cell named by queue\n * and key. `run`: an entry in the run's own cell (requires `runId`).\n */\n claimScope?: 'run';\n /** Failed deliveries carried across suspension re-publishes. */\n deliveryFailures?: number;\n suspensionCount?: number;\n}\n\n/**\n * Enqueue-side answer from a run cell. `cell`: the run predates run-scoped\n * claims, so its idempotency claims stay in claim cells. `run`: the\n * reservation was made in the run's own cell.\n */\nexport type RunQueueReservation =\n | { ok: false; message: string }\n | { ok: true; scope: 'cell' }\n | { ok: true; scope: 'run'; admitted: boolean; messageId: string };\n\nexport interface NativeQueueSendOptions {\n delaySeconds?: number;\n}\n\nexport interface NativeQueueSendResult {\n messageId: string;\n}\n\nexport function queuePayloadRegistryKey(messageId: string): string {\n return `${QUEUE_PAYLOAD_REGISTRY_PREFIX}${messageId}`;\n}\n\nexport function queuePayloadObjectKey(runId: string, messageId: string): string {\n return `workflow-queue/${encodeURIComponent(runId)}/${encodeURIComponent(messageId)}`;\n}\n\nexport function queueClaimName(queueName: string, idempotencyKey: string): string {\n return `claim:${queueName.length}:${queueName}:${idempotencyKey}`;\n}\n\nexport function queueOrphanName(messageId: string): string {\n return `queue-orphan:${messageId}`;\n}\n\nexport function nativeQueueDelaySeconds(notBefore: number | undefined, now: number): number {\n if (notBefore === undefined || notBefore <= now) return 0;\n return Math.min(NATIVE_QUEUE_MAX_DELAY_SECONDS, Math.ceil((notBefore - now) / 1000));\n}\n\nexport function validateNativeQueueEnvelope(value: unknown): NativeQueueEnvelope {\n if (!isRecord(value)) throw new TypeError('world-celld native queue envelope must be an object');\n if (value.version !== 1)\n throw new TypeError('world-celld native queue envelope version must be 1');\n for (const field of ['messageId', 'queueName', 'targetBaseUrl'] as const) {\n if (typeof value[field] !== 'string' || value[field].length === 0) {\n throw new TypeError(`world-celld native queue envelope ${field} must be a non-empty string`);\n }\n }\n for (const field of ['runId', 'idempotencyKey', 'payloadKey', 'body'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string') {\n throw new TypeError(`world-celld native queue envelope ${field} must be a string`);\n }\n }\n if (value.claimScope !== undefined && (value.claimScope !== 'run' || value.runId === undefined)) {\n throw new TypeError(\"world-celld native queue envelope claimScope must be 'run' with a runId\");\n }\n if ((value.payloadKey === undefined) === (value.body === undefined)) {\n throw new TypeError(\n 'world-celld native queue envelope must contain exactly one payload source',\n );\n }\n for (const field of ['notBefore', 'deliveryFailures', 'suspensionCount'] as const) {\n if (value[field] !== undefined && !isNonNegativeSafeInteger(value[field])) {\n throw new TypeError(\n `world-celld native queue envelope ${field} must be a non-negative safe integer`,\n );\n }\n }\n if (\n value.notBefore !== undefined &&\n (value.notBefore as number) > MAX_QUEUE_SCHEDULE_TIMESTAMP_MS\n ) {\n throw new TypeError(\n `world-celld native queue envelope notBefore must not exceed ${MAX_QUEUE_SCHEDULE_TIMESTAMP_MS}`,\n );\n }\n return value as unknown as NativeQueueEnvelope;\n}\n\nexport function validateNativeQueueSendOptions(value: unknown): NativeQueueSendOptions {\n if (value === undefined) return {};\n if (!isRecord(value)) throw new TypeError('world-celld native queue options must be an object');\n const delaySeconds = value.delaySeconds;\n if (\n delaySeconds !== undefined &&\n (!Number.isSafeInteger(delaySeconds) ||\n (delaySeconds as number) < 0 ||\n (delaySeconds as number) > NATIVE_QUEUE_MAX_DELAY_SECONDS)\n ) {\n throw new TypeError(\n `world-celld native queue delaySeconds must be an integer between 0 and ${NATIVE_QUEUE_MAX_DELAY_SECONDS}`,\n );\n }\n return delaySeconds === undefined ? {} : { delaySeconds: delaySeconds as number };\n}\n","import { isTerminalWorkflowRunStatus, type WorkflowRun } from '@workflow/world';\nimport type { IndexListOptions, IndexListPage } from './indexes.js';\n\n/** Bound cross-run fanout so large list pages cannot create an RPC burst. */\nexport const RUN_LIST_CONCURRENCY = 8;\n/** Largest page the fleet-side list accepts, matching the catalog page limit. */\nexport const MAX_RUN_LIST_LIMIT = 1000;\n\nexport type RunStatus = WorkflowRun['status'];\n\n/** Wire shape of a run listing, shared by the client and the worker router. */\nexport interface RunListRequest {\n workflowName?: string;\n statuses?: RunStatus[];\n limit: number;\n cursor?: string;\n sortOrder?: 'asc' | 'desc';\n /** 'none' strips run input and output from the returned page. */\n resolveData?: 'none' | 'all';\n}\n\nexport interface RunListPage {\n data: WorkflowRun[];\n cursor: string | null;\n hasMore: boolean;\n}\n\nexport interface RunListDependencies {\n listRuns(options: IndexListOptions): Promise<IndexListPage>;\n /** The authoritative run, or null when it does not exist or has expired. */\n readRun(runId: string): Promise<WorkflowRun | null>;\n}\n\ninterface RunIndexMetadata {\n runId: string;\n status: RunStatus;\n}\n\n/**\n * Run statuses only move pending -> running -> terminal, and terminal statuses\n * are immutable. An older index value may therefore safely exclude a filter\n * only when it is already terminal, or when the caller asks for pending and\n * the index has advanced beyond pending. Earlier non-terminal metadata cannot\n * exclude a later status because a post-commit index write may need replay.\n */\nfunction indexStatusExcludes(indexed: RunStatus, requested: RunStatus | undefined): boolean {\n if (requested === undefined || indexed === requested) return false;\n return isTerminalWorkflowRunStatus(indexed) || requested === 'pending';\n}\n\nexport function stripRunData(run: WorkflowRun): WorkflowRun {\n const { input: _input, output: _output, ...rest } = run;\n return rest;\n}\n\n/**\n * Page through the run catalog, verifying every candidate against its\n * authoritative run cell. Runs on the client against remote bindings, or in\n * the worker router against fleet bindings.\n */\nexport async function listRunsPage(\n deps: RunListDependencies,\n request: RunListRequest,\n): Promise<RunListPage> {\n const { statuses, limit } = request;\n const prefix = request.workflowName ? `run:${request.workflowName}:` : 'runall:';\n const reverse = request.sortOrder === 'desc';\n const matches: Array<{ key: string; run: WorkflowRun }> = [];\n let scanCursor = request.cursor;\n let exhausted = false;\n\n // Keep scanning index pages until the requested page is full. This\n // prevents status filters and stale derived entries from producing\n // short pages or cursors that skip matching runs.\n while (matches.length <= limit && !exhausted) {\n const kvList = await deps.listRuns({\n prefix,\n limit: Math.min(MAX_RUN_LIST_LIMIT, Math.max(50, limit)),\n cursor: scanCursor,\n reverse,\n });\n if (kvList.keys.length === 0) {\n exhausted = true;\n break;\n }\n\n const candidates: Array<{ key: string; metadata: RunIndexMetadata }> = [];\n for (const key of kvList.keys) {\n const metadata = JSON.parse(key.value) as RunIndexMetadata;\n // Use monotonic status metadata as a conservative prefilter,\n // then still verify every candidate against the authoritative\n // run below. Earlier metadata cannot exclude a later status.\n if (statuses?.every((status) => indexStatusExcludes(metadata.status, status))) {\n continue;\n }\n candidates.push({ key: key.name, metadata });\n }\n\n // Fetch enough candidates to prove the requested page and hasMore,\n // retaining index order while limiting concurrent cross-run reads.\n for (let offset = 0; offset < candidates.length && matches.length <= limit;) {\n const needed = limit + 1 - matches.length;\n const batch = candidates.slice(offset, offset + Math.min(RUN_LIST_CONCURRENCY, needed));\n const resolved = await Promise.all(\n batch.map(async ({ key, metadata }) => {\n const run = await deps.readRun(metadata.runId);\n return run && (statuses === undefined || statuses.includes(run.status))\n ? { key, run }\n : null;\n }),\n );\n for (const match of resolved) {\n if (match) matches.push(match);\n }\n offset += batch.length;\n }\n\n exhausted = kvList.list_complete;\n scanCursor = kvList.cursor ?? kvList.keys.at(-1)?.name;\n }\n\n const hasMore = matches.length > limit;\n const page = matches.slice(0, limit);\n return {\n data: page.map(({ run }) => (request.resolveData === 'none' ? stripRunData(run) : run)),\n cursor: hasMore ? (page.at(-1)?.key ?? null) : null,\n hasMore,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-list-C4B4SBYW.js","names":[],"sources":["../src/stream-protocol.ts","../src/validation.ts","../src/lifecycle.ts","../src/indexes.ts","../src/vendor/shared/serialization.ts","../src/codec.ts","../src/vendor/shared/util.ts","../src/queue-protocol.ts","../src/run-list.ts"],"sourcesContent":["/**\n * Hard-cutover stream protocol shared by the client, Worker router, and\n * StreamDO. Chunk payloads use a compact binary envelope on the public HTTP\n * boundary and Uint8Array values on the DO/storage boundary.\n */\n\nexport const STREAM_BATCH_CONTENT_TYPE = 'application/vnd.world-celld.stream-batch.v1';\n\n/**\n * Chunks per write request that every worker accepts. A client sends larger\n * batches only after a worker advertises {@link STREAM_CHUNK_LIMIT_HEADER}.\n */\nexport const MAX_STREAM_WRITE_CHUNKS = 32;\n/** A chunk remains below the 2 MiB SQLite-backed DO key/value limit. */\nexport const MAX_STREAM_CHUNK_BYTES = 1024 * 1024;\n/** Keeps serialized RPC bodies well below the 32 MiB Workers RPC limit. */\nexport const MAX_STREAM_BATCH_BYTES = 8 * 1024 * 1024;\n/** Chunks per read request that every worker accepts; see {@link MAX_STREAM_WRITE_CHUNKS}. */\nexport const MAX_STREAM_READ_CHUNKS = 32;\n/** Chunks per write or read request accepted by a worker that advertises the header below. */\nexport const NEGOTIATED_STREAM_CHUNKS = 512;\n/** Response header on stream requests: the per-request chunk limit this worker accepts. */\nexport const STREAM_CHUNK_LIMIT_HEADER = 'x-world-celld-stream-chunks';\nexport const MAX_STREAM_READ_BYTES = 8 * 1024 * 1024;\nexport const MAX_STREAM_ERROR_BYTES = 16 * 1024;\n/** Must remain below the default 30 second fleet request deadline. */\nexport const MAX_STREAM_LONG_POLL_MS = 20_000;\n\nexport type StreamTerminalState = 'open' | 'closed' | 'errored' | 'expired';\n\nexport interface StreamErrorData {\n name: string;\n message: string;\n}\n\nexport interface StreamWriteResult {\n startIndex: number;\n count: number;\n tailIndex: number;\n}\n\nexport interface StreamReadRequest {\n runId: string;\n startIndex: number;\n maxChunks: number;\n maxBytes: number;\n waitMs: number;\n}\n\nexport interface StreamReadResult {\n startIndex: number;\n tailIndex: number;\n chunks: Uint8Array[];\n state: StreamTerminalState;\n timedOut: boolean;\n error?: StreamErrorData;\n}\n\nconst WRITE_MAGIC = 0x57435357; // WCSW\nconst WRITE_ACK_MAGIC = 0x57435341; // WCSA\nconst READ_MAGIC = 0x57435352; // WCSR\nconst PROTOCOL_VERSION = 1;\nconst WRITE_HEADER_BYTES = 8;\nconst WRITE_ACK_BYTES = 16;\nconst READ_HEADER_BYTES = 28;\n\nconst STATE_TO_WIRE: Record<StreamTerminalState, number> = {\n open: 0,\n closed: 1,\n errored: 2,\n expired: 3,\n};\n\nconst WIRE_TO_STATE: readonly StreamTerminalState[] = ['open', 'closed', 'errored', 'expired'];\n\nfunction protocolError(message: string): Error {\n const error = new Error(`world-celld: invalid stream protocol: ${message}`);\n error.name = 'StreamProtocolError';\n return error;\n}\n\nfunction requireSafeIndex(value: number, field: string): void {\n if (!Number.isSafeInteger(value) || value < -1 || value > 0x7fffffff) {\n throw protocolError(`${field} is out of range`);\n }\n}\n\n/** An older worker rejects an oversized request before it touches the stream. */\nexport function isChunkLimitRejection(error: unknown): boolean {\n const candidate = error as { status?: unknown; message?: unknown } | null;\n return (\n candidate?.status === 400 &&\n typeof candidate.message === 'string' &&\n /batch exceeds \\d+ chunks|maxChunks must be (?:an integer )?between/.test(candidate.message)\n );\n}\n\nexport function validateStreamWriteChunks(chunks: readonly Uint8Array[]): number {\n if (chunks.length === 0) throw protocolError('batch must contain at least one chunk');\n if (chunks.length > NEGOTIATED_STREAM_CHUNKS) {\n throw protocolError(`batch exceeds ${NEGOTIATED_STREAM_CHUNKS} chunks`);\n }\n\n let totalBytes = 0;\n for (const chunk of chunks) {\n if (!(chunk instanceof Uint8Array)) throw protocolError('chunk is not binary data');\n if (chunk.byteLength > MAX_STREAM_CHUNK_BYTES) {\n throw protocolError(`chunk exceeds ${MAX_STREAM_CHUNK_BYTES} bytes`);\n }\n totalBytes += chunk.byteLength;\n if (totalBytes > MAX_STREAM_BATCH_BYTES) {\n throw protocolError(`batch exceeds ${MAX_STREAM_BATCH_BYTES} bytes`);\n }\n }\n return totalBytes;\n}\n\nexport function validateStreamReadRequest(request: StreamReadRequest): void {\n if (!request.runId) throw protocolError('runId is required');\n if (\n !Number.isSafeInteger(request.startIndex) ||\n request.startIndex < 0 ||\n request.startIndex > 0x7fffffff\n ) {\n throw protocolError('startIndex must be between 0 and 2147483647');\n }\n if (\n !Number.isSafeInteger(request.maxChunks) ||\n request.maxChunks < 0 ||\n request.maxChunks > NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError(`maxChunks must be between 0 and ${NEGOTIATED_STREAM_CHUNKS}`);\n }\n if (\n !Number.isSafeInteger(request.maxBytes) ||\n request.maxBytes < MAX_STREAM_CHUNK_BYTES ||\n request.maxBytes > MAX_STREAM_READ_BYTES\n ) {\n throw protocolError(\n `maxBytes must be between ${MAX_STREAM_CHUNK_BYTES} and ${MAX_STREAM_READ_BYTES}`,\n );\n }\n if (\n !Number.isSafeInteger(request.waitMs) ||\n request.waitMs < 0 ||\n request.waitMs > MAX_STREAM_LONG_POLL_MS\n ) {\n throw protocolError(`waitMs must be between 0 and ${MAX_STREAM_LONG_POLL_MS}`);\n }\n}\n\nexport function encodeStreamWriteBatch(chunks: readonly Uint8Array[]): Uint8Array {\n const totalBytes = validateStreamWriteChunks(chunks);\n const encoded = new Uint8Array(WRITE_HEADER_BYTES + chunks.length * 4 + totalBytes);\n const view = new DataView(encoded.buffer);\n view.setUint32(0, WRITE_MAGIC);\n view.setUint16(4, PROTOCOL_VERSION);\n view.setUint16(6, chunks.length);\n\n let offset = WRITE_HEADER_BYTES;\n for (const chunk of chunks) {\n view.setUint32(offset, chunk.byteLength);\n offset += 4;\n encoded.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return encoded;\n}\n\nexport function decodeStreamWriteBatch(encoded: Uint8Array): Uint8Array[] {\n if (encoded.byteLength < WRITE_HEADER_BYTES) throw protocolError('truncated write header');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== WRITE_MAGIC) throw protocolError('bad write magic');\n if (view.getUint16(4) !== PROTOCOL_VERSION) throw protocolError('unsupported write version');\n const count = view.getUint16(6);\n const chunks: Uint8Array[] = [];\n let offset = WRITE_HEADER_BYTES;\n for (let index = 0; index < count; index++) {\n if (offset + 4 > encoded.byteLength) throw protocolError('truncated chunk length');\n const length = view.getUint32(offset);\n offset += 4;\n if (offset + length > encoded.byteLength) throw protocolError('truncated chunk data');\n // Persisted DO values are structured-cloned. A view would retain the\n // complete batch backing buffer and could exceed the per-value storage\n // limit even when this individual chunk is valid.\n chunks.push(new Uint8Array(encoded.subarray(offset, offset + length)));\n offset += length;\n }\n if (offset !== encoded.byteLength) throw protocolError('trailing write data');\n validateStreamWriteChunks(chunks);\n return chunks;\n}\n\nexport function encodeStreamWriteResult(result: StreamWriteResult): Uint8Array {\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n if (\n !Number.isSafeInteger(result.count) ||\n result.count < 1 ||\n result.count > NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError('write count is out of range');\n }\n const encoded = new Uint8Array(WRITE_ACK_BYTES);\n const view = new DataView(encoded.buffer);\n view.setUint32(0, WRITE_ACK_MAGIC);\n view.setUint16(4, PROTOCOL_VERSION);\n view.setUint16(6, result.count);\n view.setInt32(8, result.startIndex);\n view.setInt32(12, result.tailIndex);\n return encoded;\n}\n\nexport function decodeStreamWriteResult(encoded: Uint8Array): StreamWriteResult {\n if (encoded.byteLength !== WRITE_ACK_BYTES) throw protocolError('invalid write response size');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== WRITE_ACK_MAGIC) throw protocolError('bad write response magic');\n if (view.getUint16(4) !== PROTOCOL_VERSION) {\n throw protocolError('unsupported write response version');\n }\n const count = view.getUint16(6);\n if (count < 1 || count > NEGOTIATED_STREAM_CHUNKS) {\n throw protocolError('write response count is out of range');\n }\n const result = {\n count,\n startIndex: view.getInt32(8),\n tailIndex: view.getInt32(12),\n };\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n if (result.tailIndex !== result.startIndex + result.count - 1) {\n throw protocolError('write response offsets are inconsistent');\n }\n return result;\n}\n\nexport function encodeStreamReadResult(result: StreamReadResult): Uint8Array {\n requireSafeIndex(result.startIndex, 'startIndex');\n requireSafeIndex(result.tailIndex, 'tailIndex');\n let chunkBytes = 0;\n for (const chunk of result.chunks) chunkBytes += 4 + chunk.byteLength;\n if (\n result.chunks.length > NEGOTIATED_STREAM_CHUNKS ||\n chunkBytes > MAX_STREAM_READ_BYTES + 4 * NEGOTIATED_STREAM_CHUNKS\n ) {\n throw protocolError('read result exceeds configured bounds');\n }\n\n const encoder = new TextEncoder();\n const errorName = result.error ? encoder.encode(result.error.name) : new Uint8Array();\n const errorMessage = result.error ? encoder.encode(result.error.message) : new Uint8Array();\n if (errorName.byteLength + errorMessage.byteLength > MAX_STREAM_ERROR_BYTES) {\n throw protocolError(`stream error exceeds ${MAX_STREAM_ERROR_BYTES} bytes`);\n }\n const encoded = new Uint8Array(\n READ_HEADER_BYTES + chunkBytes + errorName.byteLength + errorMessage.byteLength,\n );\n const view = new DataView(encoded.buffer);\n view.setUint32(0, READ_MAGIC);\n view.setUint8(4, PROTOCOL_VERSION);\n const state = STATE_TO_WIRE[result.state];\n if (state === undefined) throw protocolError('unknown stream state');\n view.setUint8(5, state);\n view.setUint8(6, result.timedOut ? 1 : 0);\n view.setUint8(7, 0);\n view.setInt32(8, result.startIndex);\n view.setInt32(12, result.tailIndex);\n view.setUint32(16, result.chunks.length);\n view.setUint32(20, errorName.byteLength);\n view.setUint32(24, errorMessage.byteLength);\n\n let offset = READ_HEADER_BYTES;\n for (const chunk of result.chunks) {\n view.setUint32(offset, chunk.byteLength);\n offset += 4;\n encoded.set(chunk, offset);\n offset += chunk.byteLength;\n }\n encoded.set(errorName, offset);\n offset += errorName.byteLength;\n encoded.set(errorMessage, offset);\n return encoded;\n}\n\nexport function decodeStreamReadResult(encoded: Uint8Array): StreamReadResult {\n if (encoded.byteLength < READ_HEADER_BYTES) throw protocolError('truncated read header');\n const view = new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength);\n if (view.getUint32(0) !== READ_MAGIC) throw protocolError('bad read magic');\n if (view.getUint8(4) !== PROTOCOL_VERSION) throw protocolError('unsupported read version');\n const state = WIRE_TO_STATE[view.getUint8(5)];\n if (!state) throw protocolError('unknown stream state');\n const startIndex = view.getInt32(8);\n const tailIndex = view.getInt32(12);\n requireSafeIndex(startIndex, 'startIndex');\n requireSafeIndex(tailIndex, 'tailIndex');\n const count = view.getUint32(16);\n const errorNameLength = view.getUint32(20);\n const errorMessageLength = view.getUint32(24);\n if (count > NEGOTIATED_STREAM_CHUNKS) throw protocolError('read chunk count exceeds limit');\n if (errorNameLength + errorMessageLength > MAX_STREAM_ERROR_BYTES) {\n throw protocolError('read error exceeds limit');\n }\n\n const chunks: Uint8Array[] = [];\n let offset = READ_HEADER_BYTES;\n let totalBytes = 0;\n for (let index = 0; index < count; index++) {\n if (offset + 4 > encoded.byteLength) throw protocolError('truncated read chunk length');\n const length = view.getUint32(offset);\n offset += 4;\n if (offset + length > encoded.byteLength) throw protocolError('truncated read chunk data');\n totalBytes += length;\n if (totalBytes > MAX_STREAM_READ_BYTES) throw protocolError('read bytes exceed limit');\n chunks.push(encoded.subarray(offset, offset + length));\n offset += length;\n }\n\n if (offset + errorNameLength + errorMessageLength !== encoded.byteLength) {\n throw protocolError('invalid read error payload');\n }\n const decoder = new TextDecoder();\n const error =\n errorNameLength > 0 || errorMessageLength > 0\n ? {\n name: decoder.decode(encoded.subarray(offset, offset + errorNameLength)),\n message: decoder.decode(encoded.subarray(offset + errorNameLength)),\n }\n : undefined;\n\n return {\n startIndex,\n tailIndex,\n chunks,\n state,\n timedOut: (view.getUint8(6) & 1) !== 0,\n error,\n };\n}\n\nexport function normalizeStreamError(error: unknown): StreamErrorData {\n let normalized: StreamErrorData;\n if (error instanceof Error) {\n normalized = { name: error.name || 'Error', message: error.message };\n } else if (typeof error === 'string') {\n normalized = { name: 'Error', message: error };\n } else if (\n error &&\n typeof error === 'object' &&\n typeof (error as { name?: unknown }).name === 'string' &&\n typeof (error as { message?: unknown }).message === 'string'\n ) {\n normalized = {\n name: (error as StreamErrorData).name,\n message: (error as StreamErrorData).message,\n };\n } else {\n normalized = { name: 'Error', message: String(error) };\n }\n\n // Bound persisted terminal metadata as well as its binary response frame.\n normalized.name = normalized.name.slice(0, 1024);\n normalized.message = normalized.message.slice(0, 4096);\n while (\n new TextEncoder().encode(normalized.name).byteLength +\n new TextEncoder().encode(normalized.message).byteLength >\n MAX_STREAM_ERROR_BYTES\n ) {\n normalized.message = normalized.message.slice(0, Math.max(0, normalized.message.length - 256));\n if (normalized.message.length === 0) {\n normalized.name = normalized.name.slice(0, Math.max(0, normalized.name.length - 256));\n }\n }\n return normalized;\n}\n","/** Largest epoch-ms deadline that fits the queue's fixed-width 13-digit keys. */\nexport const MAX_QUEUE_TIMESTAMP_MS = 9_999_999_999_999;\nexport const MAX_QUEUE_DELAY_SECONDS = Math.floor(MAX_QUEUE_TIMESTAMP_MS / 1000);\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function isNonNegativeSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0;\n}\n\nexport function isPositiveSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) > 0;\n}\n\nexport function boundedIntegerOption(\n name: string,\n value: unknown,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (value === undefined) return fallback;\n if (!Number.isSafeInteger(value) || (value as number) < minimum || (value as number) > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value as number;\n}\n\n/**\n * Parse a deployment/runtime integer setting without accepting whitespace,\n * exponents, fractions, or numeric prefixes such as `5junk`.\n */\nexport function strictIntegerSetting(\n name: string,\n raw: string | number | undefined,\n fallback: number,\n minimum: number,\n maximum = Number.MAX_SAFE_INTEGER,\n): number {\n if (raw === undefined) return fallback;\n const value = typeof raw === 'number' ? raw : /^\\d+$/.test(raw) ? Number(raw) : Number.NaN;\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${name} must be an integer between ${minimum} and ${maximum}`);\n }\n return value;\n}\n\nexport function isValidQueueDelaySeconds(value: unknown, minimum: 0 | 1 = 0): value is number {\n return (\n Number.isSafeInteger(value) &&\n (value as number) >= minimum &&\n (value as number) <= MAX_QUEUE_DELAY_SECONDS\n );\n}\n\nexport function queueDelayDeadline(\n now: number,\n delaySeconds: unknown,\n minimum: 0 | 1 = 0,\n requiredHeadroomMs = 0,\n): number | null {\n if (!isNonNegativeSafeInteger(now) || !isValidQueueDelaySeconds(delaySeconds, minimum)) {\n return null;\n }\n return checkedQueueTimestampAdd(now, delaySeconds * 1000, requiredHeadroomMs);\n}\n\n/**\n * Add an offset to a queue timestamp while preserving its 13-digit key order.\n * Optional headroom reserves space for a later persisted derivative deadline.\n */\nexport function checkedQueueTimestampAdd(\n timestampMs: unknown,\n offsetMs: unknown,\n requiredHeadroomMs = 0,\n): number | null {\n if (\n !isNonNegativeSafeInteger(timestampMs) ||\n !isNonNegativeSafeInteger(offsetMs) ||\n !isNonNegativeSafeInteger(requiredHeadroomMs)\n ) {\n return null;\n }\n const timestamp = timestampMs;\n const offset = offsetMs;\n if (timestamp > MAX_QUEUE_TIMESTAMP_MS || offset > MAX_QUEUE_TIMESTAMP_MS - timestamp) {\n return null;\n }\n const result = timestamp + offset;\n return requiredHeadroomMs <= MAX_QUEUE_TIMESTAMP_MS - result ? result : null;\n}\n","import { MAX_QUEUE_TIMESTAMP_MS } from './validation.js';\n\n/**\n * Hard protocol bounds used by lifecycle leases and derivative-fence cleanup.\n *\n * These are not retention TTLs. They bound how long a request which was\n * admitted before expiry may still mutate a derivative Durable Object:\n *\n * - fleet calls have at most three 5-minute attempts plus bounded retry delay;\n * - one native Queue idempotency claim stays live for at most 15 minutes\n * without a successful delivery or explicit workflow suspension;\n * - hook admission spans reserve retries, one authoritative apply, and\n * finalize retries before the exact claim must be reacquired.\n */\nexport const MAX_FLEET_RPC_TIMEOUT_MS = 5 * 60 * 1000;\nexport const FLEET_IDEMPOTENT_ATTEMPTS = 3;\nexport const FLEET_RETRY_BACKOFF_MAX_MS = 900;\n\nexport const MAX_IDEMPOTENT_RPC_LIFETIME_MS =\n FLEET_IDEMPOTENT_ATTEMPTS * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS;\nexport const MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS =\n MAX_FLEET_RPC_TIMEOUT_MS + MAX_IDEMPOTENT_RPC_LIFETIME_MS;\n\nexport const MAX_QUEUE_DELIVERY_TIMEOUT_MS = 5 * 60 * 1000;\nexport const QUEUE_CLAIM_STALE_MS = 15 * 60 * 1000;\n/** A fresh delivery edge may advance an immediately-due message by one millisecond. */\nexport const QUEUE_ALARM_EDGE_MS = 1;\nexport const MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS = QUEUE_CLAIM_STALE_MS + QUEUE_ALARM_EDGE_MS;\n/** Latest admissible due time with room for a fresh queue claim. */\nexport const MAX_QUEUE_SCHEDULE_TIMESTAMP_MS =\n MAX_QUEUE_TIMESTAMP_MS - MAX_QUEUE_DERIVED_DEADLINE_HEADROOM_MS;\n\nexport const CATALOG_FENCE_GRACE_MS = MAX_RUN_INDEX_PUBLICATION_LIFETIME_MS;\n\nexport const HOOK_CLAIM_LEASE_MS =\n (FLEET_IDEMPOTENT_ATTEMPTS * 2 + 1) * MAX_FLEET_RPC_TIMEOUT_MS + FLEET_RETRY_BACKOFF_MAX_MS * 2;\n\nexport const LIFECYCLE_COMPACTION_BATCH = 128;\nexport const LIFECYCLE_COMPACTION_RETRY_MS = 1000;\n","import type { RunListPage, RunListRequest } from './run-list.js';\nimport type { WorkflowRun } from '@workflow/world';\nimport type { HookTokenOwner } from './config.js';\nimport type {\n ExpireRunIndexesRequest,\n ExpireRunIndexesResult,\n ReleaseHookIndexesRequest,\n ReleaseHookIndexesResult,\n} from './retention.js';\n\nexport const RUN_CATALOG_SHARDS = 16;\nexport const HOOK_TOKEN_SHARDS = 32;\nexport const HOOK_ID_SHARDS = 32;\n\nconst INDEX_PROTOCOL_VERSION = 'v1';\nconst HOOK_RELEASE_BATCH = 64;\n\nexport interface IndexListOptions {\n prefix?: string;\n cursor?: string;\n /** Exclusive upper bound for creation-time retention scans. */\n end?: string;\n limit?: number;\n reverse?: boolean;\n}\n\nexport interface IndexListPage {\n /** sourceShard is populated by the merged fleet index for exact follow-up mutation. */\n keys: Array<{ name: string; value: string; sourceShard?: string }>;\n list_complete: boolean;\n cursor?: string;\n}\n\nexport interface RunCatalogShardStub {\n upsertRun(\n runId: string,\n keys: string[],\n serializedMetadata: string,\n publicationExpiresAt: number,\n ): Promise<{ stored: boolean }>;\n list(options?: IndexListOptions): Promise<IndexListPage>;\n deleteStaleGlobalRun(\n runId: string,\n key: string,\n expectedValue: string,\n ): Promise<{ deleted: boolean }>;\n expireRun(runId: string, expiredAt: number): Promise<ExpireRunIndexesResult>;\n}\n\nexport type HookClaimResult =\n | { claimed: true; claimId: string }\n | { claimed: false; holder: HookTokenOwner };\n\nexport interface HookReservation {\n claimId: string;\n tokenClaimId?: string;\n hookIdClaimId?: string;\n}\n\nexport type HookReservationResult =\n | { admitted: true; reservation: HookReservation }\n | { admitted: false; holder: HookTokenOwner };\n\nexport interface HookTokenShardStub {\n get(token: string): Promise<string | null>;\n reserve(token: string, owner: HookTokenOwner, proposedClaimId: string): Promise<HookClaimResult>;\n finalize(\n token: string,\n serializedHook: string,\n owner: HookTokenOwner,\n claimId?: string,\n ): Promise<{ stored: boolean }>;\n releaseClaim(token: string, owner: HookTokenOwner, claimId: string): Promise<void>;\n releaseBatch(\n hooks: Array<{ token: string; owner: HookTokenOwner }>,\n ): Promise<{ deleted: number }>;\n}\n\nexport interface HookIdShardStub {\n get(hookId: string): Promise<string | null>;\n reserve(hookId: string, owner: HookTokenOwner, proposedClaimId: string): Promise<HookClaimResult>;\n publish(\n hookId: string,\n serializedHook: string,\n owner: HookTokenOwner,\n claimId?: string,\n ): Promise<{ stored: boolean }>;\n releaseClaim(hookId: string, owner: HookTokenOwner, claimId: string): Promise<void>;\n releaseBatch(\n hooks: Array<{ hookId: string; owner: HookTokenOwner }>,\n ): Promise<{ deleted: number }>;\n}\n\ninterface CellIdLike {\n toString(): string;\n}\n\nexport interface CellNamespaceLike<T> {\n idFromName(name: string): CellIdLike;\n get(id: CellIdLike): T;\n}\n\nexport interface WorkflowIndexBindings {\n runCatalog: CellNamespaceLike<RunCatalogShardStub>;\n hookTokens: CellNamespaceLike<HookTokenShardStub>;\n hookIds: CellNamespaceLike<HookIdShardStub>;\n}\n\n/** High-level client used by the World storage layer and retention coordinator. */\nexport interface WorkflowIndex {\n commitRun(\n run: WorkflowRun,\n serializedMetadata: string,\n publicationExpiresAt: number,\n ): Promise<{ stored: boolean }>;\n listRuns(options?: IndexListOptions): Promise<IndexListPage>;\n /**\n * Remote only: the complete run listing performed inside the fleet. Resolves\n * to null when the worker predates the route; the caller then lists itself.\n */\n listResolvedRuns?(request: RunListRequest): Promise<RunListPage | null>;\n getHookByToken(token: string): Promise<string | null>;\n getHookById(hookId: string): Promise<string | null>;\n reserveHook(token: string, owner: HookTokenOwner): Promise<HookReservationResult>;\n finalizeHookIndexes(\n token: string,\n hookId: string,\n serializedHook: string,\n owner: HookTokenOwner,\n reservation?: HookReservation,\n ): Promise<void>;\n releaseHookReservation(\n token: string,\n owner: HookTokenOwner,\n reservation: HookReservation,\n ): Promise<void>;\n releaseHookIndexes(request: ReleaseHookIndexesRequest): Promise<ReleaseHookIndexesResult>;\n expireRun(request: ExpireRunIndexesRequest): Promise<ExpireRunIndexesResult>;\n}\n\n/** Stable FNV-1a routing hash. Collisions share a shard but never a storage key. */\nexport function stableIndexHash(value: string): number {\n let hash = 0x811c9dc5;\n for (const byte of new TextEncoder().encode(value)) {\n hash ^= byte;\n hash = Math.imul(hash, 0x01000193);\n }\n return hash >>> 0;\n}\n\nfunction shardName(domain: string, value: string, cardinality: number): string {\n const width = Math.max(2, (cardinality - 1).toString(16).length);\n const shard = stableIndexHash(value) % cardinality;\n return `${domain}:${INDEX_PROTOCOL_VERSION}:${shard.toString(16).padStart(width, '0')}`;\n}\n\nexport function runCatalogShardName(runId: string): string {\n return shardName('run-catalog', runId, RUN_CATALOG_SHARDS);\n}\n\nexport function hookTokenShardName(token: string): string {\n return shardName('hook-token', token, HOOK_TOKEN_SHARDS);\n}\n\nexport function hookIdShardName(hookId: string): string {\n return shardName('hook-id', hookId, HOOK_ID_SHARDS);\n}\n\nexport function allRunCatalogShardNames(): string[] {\n return Array.from(\n { length: RUN_CATALOG_SHARDS },\n (_, shard) => `run-catalog:${INDEX_PROTOCOL_VERSION}:${shard.toString(16).padStart(2, '0')}`,\n );\n}\n\n/** Catalog metadata for a run; the client and the worker router must agree on it. */\nexport function runIndexMetadata(run: Pick<WorkflowRun, 'runId' | 'createdAt' | 'status'>): string {\n return JSON.stringify({\n runId: run.runId,\n createdAt: run.createdAt.toISOString(),\n status: run.status,\n });\n}\n\nfunction stub<T>(namespace: CellNamespaceLike<T>, name: string): T {\n return namespace.get(namespace.idFromName(name));\n}\n\nfunction runKeys(run: Pick<WorkflowRun, 'runId' | 'workflowName' | 'createdAt'>): string[] {\n const timestamp = run.createdAt.getTime().toString().padStart(13, '0');\n return [`run:${run.workflowName}:${timestamp}:${run.runId}`, `runall:${timestamp}:${run.runId}`];\n}\n\nfunction groupByShard<T>(values: T[], route: (value: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const value of values) {\n const name = route(value);\n const group = groups.get(name);\n if (group) group.push(value);\n else groups.set(name, [value]);\n }\n return groups;\n}\n\nfunction sameOwner(left: HookTokenOwner, right: HookTokenOwner): boolean {\n return left.runId === right.runId && left.hookId === right.hookId;\n}\n\nfunction compareBytes(left: Uint8Array, right: Uint8Array): number {\n const length = Math.min(left.byteLength, right.byteLength);\n for (let index = 0; index < length; index++) {\n const difference = left[index] - right[index];\n if (difference !== 0) return difference;\n }\n return left.byteLength - right.byteLength;\n}\n\nasync function inBatches<T>(\n values: T[],\n operation: (batch: T[]) => Promise<{ deleted: number }>,\n): Promise<number> {\n let deleted = 0;\n for (let offset = 0; offset < values.length; offset += HOOK_RELEASE_BATCH) {\n deleted += (await operation(values.slice(offset, offset + HOOK_RELEASE_BATCH))).deleted;\n }\n return deleted;\n}\n\nexport function createWorkflowIndex(bindings: WorkflowIndexBindings): WorkflowIndex {\n const releaseHooks = async (request: ReleaseHookIndexesRequest): Promise<number> => {\n const tokenGroups = groupByShard(request.hooks, (hook) => hookTokenShardName(hook.token));\n const idGroups = groupByShard(request.hooks, (hook) => hookIdShardName(hook.hookId));\n const releases: Array<Promise<number>> = [];\n for (const [name, hooks] of tokenGroups) {\n const target = stub(bindings.hookTokens, name);\n releases.push(\n inBatches(\n hooks.map((hook) => ({\n token: hook.token,\n owner: { runId: request.runId, hookId: hook.hookId },\n })),\n (batch) => target.releaseBatch(batch),\n ),\n );\n }\n for (const [name, hooks] of idGroups) {\n const target = stub(bindings.hookIds, name);\n releases.push(\n inBatches(\n hooks.map((hook) => ({\n hookId: hook.hookId,\n owner: { runId: request.runId, hookId: hook.hookId },\n })),\n (batch) => target.releaseBatch(batch),\n ),\n );\n }\n return (await Promise.all(releases)).reduce((total, count) => total + count, 0);\n };\n\n return {\n async commitRun(run, serializedMetadata, publicationExpiresAt) {\n return await stub(bindings.runCatalog, runCatalogShardName(run.runId)).upsertRun(\n run.runId,\n runKeys(run),\n serializedMetadata,\n publicationExpiresAt,\n );\n },\n\n async listRuns(options) {\n const suppliedLimit = options?.limit;\n const requestedLimit =\n typeof suppliedLimit === 'number' && Number.isFinite(suppliedLimit)\n ? Math.floor(suppliedLimit)\n : 1000;\n const limit = Math.min(1000, Math.max(1, requestedLimit));\n const shardNames = allRunCatalogShardNames();\n const pages = await Promise.all(\n shardNames.map((name) =>\n stub(bindings.runCatalog, name).list({ ...options, limit: limit + 1 }),\n ),\n );\n const encoder = new TextEncoder();\n const candidates = pages\n .flatMap((shardPage, shardIndex) =>\n shardPage.keys.map((entry) => ({\n entry: { ...entry, sourceShard: shardNames[shardIndex] },\n encodedName: encoder.encode(entry.name),\n })),\n )\n .toSorted((left, right) => {\n const compared = compareBytes(left.encodedName, right.encodedName);\n return options?.reverse ? -compared : compared;\n });\n const page = candidates.slice(0, limit).map(({ entry }) => entry);\n const listComplete =\n candidates.length <= limit && pages.every((entry) => entry.list_complete);\n return {\n keys: page,\n list_complete: listComplete,\n cursor: listComplete ? undefined : page.at(-1)?.name,\n };\n },\n\n getHookByToken(token) {\n return stub(bindings.hookTokens, hookTokenShardName(token)).get(token);\n },\n\n getHookById(hookId) {\n return stub(bindings.hookIds, hookIdShardName(hookId)).get(hookId);\n },\n\n async reserveHook(token, owner) {\n const proposedClaimId = crypto.randomUUID();\n const tokenTarget = stub(bindings.hookTokens, hookTokenShardName(token));\n const tokenClaim = await tokenTarget.reserve(token, owner, proposedClaimId);\n if (!tokenClaim.claimed && !sameOwner(tokenClaim.holder, owner)) {\n return { admitted: false, holder: tokenClaim.holder };\n }\n\n const tokenClaimId = tokenClaim.claimed ? tokenClaim.claimId : undefined;\n const hookIdTarget = stub(bindings.hookIds, hookIdShardName(owner.hookId));\n const sharedClaimId = tokenClaimId ?? proposedClaimId;\n let hookIdClaim: HookClaimResult;\n try {\n hookIdClaim = await hookIdTarget.reserve(owner.hookId, owner, sharedClaimId);\n } catch (error) {\n await Promise.allSettled([\n ...(tokenClaimId ? [tokenTarget.releaseClaim(token, owner, tokenClaimId)] : []),\n hookIdTarget.releaseClaim(owner.hookId, owner, sharedClaimId),\n ]);\n throw error;\n }\n if (!hookIdClaim.claimed) {\n if (tokenClaimId) await tokenTarget.releaseClaim(token, owner, tokenClaimId);\n return { admitted: false, holder: hookIdClaim.holder };\n }\n\n const reservation: HookReservation = {\n claimId: `${tokenClaimId ?? '-'}:${hookIdClaim.claimId}`,\n tokenClaimId,\n hookIdClaimId: hookIdClaim.claimId,\n };\n return { admitted: true, reservation };\n },\n\n async finalizeHookIndexes(token, hookId, serializedHook, owner, reservation) {\n const tokenResult = await stub(bindings.hookTokens, hookTokenShardName(token)).finalize(\n token,\n serializedHook,\n owner,\n reservation?.tokenClaimId,\n );\n if (!tokenResult.stored) return;\n await stub(bindings.hookIds, hookIdShardName(hookId)).publish(\n hookId,\n serializedHook,\n owner,\n reservation?.hookIdClaimId,\n );\n },\n\n async releaseHookReservation(token, owner, reservation) {\n const releases: Array<Promise<void>> = [];\n if (reservation.tokenClaimId) {\n releases.push(\n stub(bindings.hookTokens, hookTokenShardName(token)).releaseClaim(\n token,\n owner,\n reservation.tokenClaimId,\n ),\n );\n }\n if (reservation.hookIdClaimId) {\n releases.push(\n stub(bindings.hookIds, hookIdShardName(owner.hookId)).releaseClaim(\n owner.hookId,\n owner,\n reservation.hookIdClaimId,\n ),\n );\n }\n await Promise.all(releases);\n },\n\n async releaseHookIndexes(request) {\n return { deleted: await releaseHooks(request) };\n },\n\n async expireRun(request) {\n const [catalog, hookDeletes] = await Promise.all([\n stub(bindings.runCatalog, runCatalogShardName(request.runId)).expireRun(\n request.runId,\n request.expiredAt,\n ),\n releaseHooks({ runId: request.runId, hooks: request.hooks }),\n ]);\n return { deleted: catalog.deleted + hookDeletes };\n },\n };\n}\n","/** Standard Date fields used across all worlds */\nexport const DATE_FIELDS = new Set([\n 'createdAt',\n 'updatedAt',\n 'startedAt',\n 'completedAt',\n 'retryAfter',\n] as const);\n\n/**\n * JSON reviver that converts ISO date strings to Date objects.\n * Use with JSON.parse(json, dateReviver).\n */\nexport function dateReviver(key: string, value: unknown): unknown {\n if (\n DATE_FIELDS.has(key as typeof DATE_FIELDS extends Set<infer T> ? T : never) &&\n typeof value === 'string'\n ) {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? value : date;\n }\n return value;\n}\n\n/**\n * Base64 helpers. Modified vs upstream: implemented without Buffer so this\n * module is safe inside the celld worker bundle (workerd has no Buffer\n * global). Uses the native Uint8Array base64 methods where the runtime has\n * them (Node >= 25, current V8) and falls back to atob/btoa elsewhere.\n */\nconst nativeToBase64 = (\n Uint8Array.prototype as Uint8Array & { toBase64?: (this: Uint8Array) => string }\n).toBase64;\nconst nativeFromBase64 = (Uint8Array as { fromBase64?: (text: string) => Uint8Array }).fromBase64;\n\n/** Small enough to stay far below engine argument-count limits and fast to spread. */\nconst FALLBACK_ENCODE_CHUNK = 0x1000;\n\n/** @internal Exported for tests; use b64encode. */\nexport function b64encodeFallback(bytes: Uint8Array): string {\n let bin = '';\n for (let i = 0; i < bytes.length; i += FALLBACK_ENCODE_CHUNK) {\n bin += String.fromCharCode.apply(\n null,\n bytes.subarray(i, i + FALLBACK_ENCODE_CHUNK) as unknown as number[],\n );\n }\n return btoa(bin);\n}\n\n/** @internal Exported for tests; use b64decode. */\nexport function b64decodeFallback(text: string): Uint8Array {\n const bin = atob(text);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) {\n out[i] = bin.charCodeAt(i);\n }\n return out;\n}\n\nexport function b64encode(bytes: Uint8Array): string {\n return nativeToBase64 ? nativeToBase64.call(bytes) : b64encodeFallback(bytes);\n}\n\nexport function b64decode(text: string): Uint8Array {\n return nativeFromBase64 ? nativeFromBase64(text) : b64decodeFallback(text);\n}\n\n/**\n * JSON replacer that encodes Uint8Array as a tagged object with base64 data.\n */\nexport function uint8ArrayReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Uint8Array) {\n return {\n __type: 'Uint8Array',\n data: b64encode(value),\n };\n }\n return value;\n}\n\n/**\n * JSON reviver that decodes tagged Uint8Array objects and ISO date strings.\n * Supports both:\n * - New format: { __type: 'Uint8Array', data: '<base64>' }\n * - Legacy format: { __uint8array: true, data: [1, 2, 3] }\n */\nexport function uint8ArrayReviver(key: string, value: unknown): unknown {\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // New format: base64-encoded\n if (obj.__type === 'Uint8Array') {\n if (typeof obj.data !== 'string') throw new SyntaxError('Malformed Uint8Array tag');\n try {\n return b64decode(obj.data);\n } catch {\n throw new SyntaxError('Malformed Uint8Array tag');\n }\n }\n // Legacy format: number array (backwards compat with NATS JetStream data)\n if (obj.__uint8array === true) {\n if (\n !Array.isArray(obj.data) ||\n !obj.data.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)\n ) {\n throw new SyntaxError('Malformed legacy Uint8Array tag');\n }\n return new Uint8Array(obj.data);\n }\n }\n return dateReviver(key, value);\n}\n\n/** Stringify with Uint8Array support. */\nexport function stringify(value: unknown): string {\n return JSON.stringify(value, uint8ArrayReplacer);\n}\n\n/** Parse with Uint8Array and Date support. */\nexport function parse<T>(text: string): T {\n return JSON.parse(text, uint8ArrayReviver) as T;\n}\n\n/** Deep clone using structuredClone */\nexport function deepClone<T>(value: T): T {\n return structuredClone(value);\n}\n","/**\n * RPC wire codec for the Node client <-> worker router HTTP boundary.\n *\n * Extends the shared tagged-JSON format (`{__type:'Uint8Array', data}` +\n * DATE_FIELDS revival) with explicitly tagged Dates: on Cloudflare the DO RPC\n * boundary is structured clone, which preserves EVERY Date — including ones\n * outside the well-known DATE_FIELDS (e.g. inside applyEvent outcomes and\n * user payloads). The HTTP hop must preserve them too, so Dates travel as\n * `{__type:'Date', iso}`.\n *\n * Runs on both sides of the wire, including inside the celld worker — so no\n * Node built-ins (Buffer): base64 uses the native Uint8Array methods or\n * atob/btoa.\n */\nimport { b64decode, b64encode, dateReviver } from './vendor/shared/serialization.js';\n\nfunction rpcReplacer(this: unknown, key: string, value: unknown): unknown {\n // JSON.stringify invokes Date.toJSON before the replacer sees the value;\n // recover the original from the holder object.\n const original =\n this && typeof this === 'object' ? (this as Record<string, unknown>)[key] : undefined;\n if (original instanceof Date) {\n return { __type: 'Date', iso: original.toISOString() };\n }\n if (value instanceof Uint8Array) {\n return { __type: 'Uint8Array', data: b64encode(value) };\n }\n return value;\n}\n\nfunction rpcReviver(key: string, value: unknown): unknown {\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n if (obj.__type === 'Date') {\n if (typeof obj.iso !== 'string') throw new SyntaxError('Malformed Date tag');\n const date = new Date(obj.iso);\n if (Number.isNaN(date.getTime())) throw new SyntaxError('Malformed Date tag');\n return date;\n }\n if (obj.__type === 'Uint8Array') {\n if (typeof obj.data !== 'string') throw new SyntaxError('Malformed Uint8Array tag');\n try {\n return b64decode(obj.data);\n } catch {\n throw new SyntaxError('Malformed Uint8Array tag');\n }\n }\n }\n // Fallback shared-codec semantics for untagged ISO strings in DATE_FIELDS.\n return dateReviver(key, value);\n}\n\nexport function rpcStringify(value: unknown): string {\n return JSON.stringify(value, rpcReplacer);\n}\n\nexport function rpcParse<T>(text: string): T {\n return JSON.parse(text, rpcReviver) as T;\n}\n","export class Mutex {\n promise: Promise<unknown> = Promise.resolve();\n andThen<T>(fn: () => Promise<T> | T): Promise<T> {\n this.promise = this.promise.then(\n () => fn(),\n () => fn(),\n );\n return this.promise as Promise<T>;\n }\n}\n\nexport function compact<T extends object>(obj: T) {\n const value = {} as {\n [key in keyof T]: null extends T[key] ? undefined | NonNullable<T[key]> : T[key];\n };\n for (const key in obj) {\n if (obj[key] !== null) {\n value[key] = obj[key] as any;\n } else {\n value[key] = undefined as any;\n }\n }\n return value;\n}\n\n/**\n * Reference counting helper for managing resource lifecycle\n */\nexport class Rc {\n private count = 0;\n private disposeFn?: () => void | Promise<void>;\n\n constructor(disposeFn?: () => void | Promise<void>) {\n this.disposeFn = disposeFn;\n }\n\n inc(): void {\n this.count++;\n }\n\n async dec(): Promise<void> {\n this.count--;\n if (this.count === 0 && this.disposeFn) {\n await this.disposeFn();\n }\n }\n\n getCount(): number {\n return this.count;\n }\n}\n","import { isNonNegativeSafeInteger, isRecord } from './validation.js';\nimport { MAX_QUEUE_SCHEDULE_TIMESTAMP_MS } from './lifecycle.js';\n\nexport { QUEUE_CLAIM_STALE_MS } from './lifecycle.js';\n\n/** celld v0.6.0 follows this native Queue producer-delay ceiling. */\nexport const NATIVE_QUEUE_MAX_DELAY_SECONDS = 86_400;\nexport const NATIVE_QUEUE_MAX_MESSAGE_BYTES = 128_000;\nexport const MAX_QUEUE_SUSPENSIONS = 256;\n/** Unconfirmed producer reservations must become recoverable after an interrupted send. */\nexport const QUEUE_PUBLICATION_LEASE_MS = 5 * 60 * 1000;\nexport const QUEUE_RESERVATION_GRACE_MS = 5 * 24 * 60 * 60 * 1000;\nexport const QUEUE_PAYLOAD_REGISTRY_PREFIX = 'queue-payload:';\n/** Largest run-bearing body that may travel inline in the broker envelope. */\nexport const MAX_INLINE_RUN_BODY_BYTES = 8 * 1024;\n/** Workflow payload fields that carry user data, which run retention must be able to delete. */\nconst USER_DATA_FIELDS = ['runInput', 'hookInput', 'stepInput'] as const;\n\n/**\n * A run-bearing body may stay inline when it is small and carries no user\n * data: then it holds only IDs, trace context, and metadata, and nothing in it\n * needs run retention to delete it from object storage.\n */\nexport function isInlineRunBody(body: string): boolean {\n if (body.length > MAX_INLINE_RUN_BODY_BYTES) return false;\n if (new TextEncoder().encode(body).byteLength > MAX_INLINE_RUN_BODY_BYTES) return false;\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return false;\n }\n return isRecord(parsed) && USER_DATA_FIELDS.every((field) => parsed[field] === undefined);\n}\n\nexport interface QueuePayloadRegistration {\n messageId: string;\n key: string;\n /** Delete an orphaned resilient-start payload after this deadline. */\n orphanExpiresAt: number;\n}\n\nexport interface QueuePayloadOrphan {\n messageId: string;\n runId: string;\n key: string;\n expiresAt: number;\n}\n\n/**\n * Small broker message carried by celld's native Queue.\n *\n * Run-bearing payload bytes live in object storage so the broker's 128 kB limit does not\n * narrow the Workflow World contract and run retention can delete those bytes\n * without waiting for the Queue's fixed four-day retention window.\n */\nexport interface NativeQueueEnvelope {\n version: 1;\n messageId: string;\n queueName: string;\n targetBaseUrl: string;\n runId?: string;\n idempotencyKey?: string;\n payloadKey?: string;\n /**\n * Inline body. Health checks always travel inline; a run-bearing body may\n * travel inline when it is small and carries no user data, in which case\n * delivery checks the run's expiry instead of reading a payload object.\n */\n body?: string;\n /** Absolute workflow redelivery deadline; long waits are chained by the consumer. */\n notBefore?: number;\n /**\n * Where the idempotency claim lives. Absent: the claim cell named by queue\n * and key. `run`: an entry in the run's own cell (requires `runId`).\n */\n claimScope?: 'run';\n /** Failed deliveries carried across suspension re-publishes. */\n deliveryFailures?: number;\n suspensionCount?: number;\n}\n\n/**\n * Enqueue-side answer from a run cell. `cell`: the run predates run-scoped\n * claims, so its idempotency claims stay in claim cells. `run`: the\n * reservation was made in the run's own cell.\n */\nexport type RunQueueReservation =\n | { ok: false; message: string }\n | { ok: true; scope: 'cell' }\n | { ok: true; scope: 'run'; admitted: boolean; messageId: string; publicationPending?: true };\n\nexport interface NativeQueueSendOptions {\n delaySeconds?: number;\n}\n\nexport interface NativeQueueSendResult {\n messageId: string;\n}\n\nexport function queuePayloadRegistryKey(messageId: string): string {\n return `${QUEUE_PAYLOAD_REGISTRY_PREFIX}${messageId}`;\n}\n\nexport function queuePayloadObjectKey(runId: string, messageId: string): string {\n return `workflow-queue/${encodeURIComponent(runId)}/${encodeURIComponent(messageId)}`;\n}\n\nexport function queueClaimName(queueName: string, idempotencyKey: string): string {\n return `claim:${queueName.length}:${queueName}:${idempotencyKey}`;\n}\n\nexport function queueOrphanName(messageId: string): string {\n return `queue-orphan:${messageId}`;\n}\n\nexport function nativeQueueDelaySeconds(notBefore: number | undefined, now: number): number {\n if (notBefore === undefined || notBefore <= now) return 0;\n return Math.min(NATIVE_QUEUE_MAX_DELAY_SECONDS, Math.ceil((notBefore - now) / 1000));\n}\n\nexport function validateNativeQueueEnvelope(value: unknown): NativeQueueEnvelope {\n if (!isRecord(value)) throw new TypeError('world-celld native queue envelope must be an object');\n if (value.version !== 1)\n throw new TypeError('world-celld native queue envelope version must be 1');\n for (const field of ['messageId', 'queueName', 'targetBaseUrl'] as const) {\n if (typeof value[field] !== 'string' || value[field].length === 0) {\n throw new TypeError(`world-celld native queue envelope ${field} must be a non-empty string`);\n }\n }\n for (const field of ['runId', 'idempotencyKey', 'payloadKey', 'body'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string') {\n throw new TypeError(`world-celld native queue envelope ${field} must be a string`);\n }\n }\n if (value.claimScope !== undefined && (value.claimScope !== 'run' || value.runId === undefined)) {\n throw new TypeError(\"world-celld native queue envelope claimScope must be 'run' with a runId\");\n }\n if ((value.payloadKey === undefined) === (value.body === undefined)) {\n throw new TypeError(\n 'world-celld native queue envelope must contain exactly one payload source',\n );\n }\n for (const field of ['notBefore', 'deliveryFailures', 'suspensionCount'] as const) {\n if (value[field] !== undefined && !isNonNegativeSafeInteger(value[field])) {\n throw new TypeError(\n `world-celld native queue envelope ${field} must be a non-negative safe integer`,\n );\n }\n }\n if (\n value.notBefore !== undefined &&\n (value.notBefore as number) > MAX_QUEUE_SCHEDULE_TIMESTAMP_MS\n ) {\n throw new TypeError(\n `world-celld native queue envelope notBefore must not exceed ${MAX_QUEUE_SCHEDULE_TIMESTAMP_MS}`,\n );\n }\n return value as unknown as NativeQueueEnvelope;\n}\n\nexport function validateNativeQueueSendOptions(value: unknown): NativeQueueSendOptions {\n if (value === undefined) return {};\n if (!isRecord(value)) throw new TypeError('world-celld native queue options must be an object');\n const delaySeconds = value.delaySeconds;\n if (\n delaySeconds !== undefined &&\n (!Number.isSafeInteger(delaySeconds) ||\n (delaySeconds as number) < 0 ||\n (delaySeconds as number) > NATIVE_QUEUE_MAX_DELAY_SECONDS)\n ) {\n throw new TypeError(\n `world-celld native queue delaySeconds must be an integer between 0 and ${NATIVE_QUEUE_MAX_DELAY_SECONDS}`,\n );\n }\n return delaySeconds === undefined ? {} : { delaySeconds: delaySeconds as number };\n}\n","import { isTerminalWorkflowRunStatus, type WorkflowRun } from '@workflow/world';\nimport type { IndexListOptions, IndexListPage } from './indexes.js';\n\n/** Bound cross-run fanout so large list pages cannot create an RPC burst. */\nexport const RUN_LIST_CONCURRENCY = 8;\n/** Largest page the fleet-side list accepts, matching the catalog page limit. */\nexport const MAX_RUN_LIST_LIMIT = 1000;\n\nexport type RunStatus = WorkflowRun['status'];\n\n/** Wire shape of a run listing, shared by the client and the worker router. */\nexport interface RunListRequest {\n workflowName?: string;\n statuses?: RunStatus[];\n limit: number;\n cursor?: string;\n sortOrder?: 'asc' | 'desc';\n /** 'none' strips run input and output from the returned page. */\n resolveData?: 'none' | 'all';\n}\n\nexport interface RunListPage {\n data: WorkflowRun[];\n cursor: string | null;\n hasMore: boolean;\n}\n\nexport interface RunListDependencies {\n listRuns(options: IndexListOptions): Promise<IndexListPage>;\n /** The authoritative run, or null when it does not exist or has expired. */\n readRun(runId: string): Promise<WorkflowRun | null>;\n}\n\ninterface RunIndexMetadata {\n runId: string;\n status: RunStatus;\n}\n\n/**\n * Run statuses only move pending -> running -> terminal, and terminal statuses\n * are immutable. An older index value may therefore safely exclude a filter\n * only when it is already terminal, or when the caller asks for pending and\n * the index has advanced beyond pending. Earlier non-terminal metadata cannot\n * exclude a later status because a post-commit index write may need replay.\n */\nfunction indexStatusExcludes(indexed: RunStatus, requested: RunStatus | undefined): boolean {\n if (requested === undefined || indexed === requested) return false;\n return isTerminalWorkflowRunStatus(indexed) || requested === 'pending';\n}\n\nexport function stripRunData(run: WorkflowRun): WorkflowRun {\n const { input: _input, output: _output, ...rest } = run;\n return rest;\n}\n\n/**\n * Page through the run catalog, verifying every candidate against its\n * authoritative run cell. Runs on the client against remote bindings, or in\n * the worker router against fleet bindings.\n */\nexport async function listRunsPage(\n deps: RunListDependencies,\n request: RunListRequest,\n): Promise<RunListPage> {\n const { statuses, limit } = request;\n const prefix = request.workflowName ? `run:${request.workflowName}:` : 'runall:';\n const reverse = request.sortOrder === 'desc';\n const matches: Array<{ key: string; run: WorkflowRun }> = [];\n let scanCursor = request.cursor;\n let exhausted = false;\n\n // Keep scanning index pages until the requested page is full. This\n // prevents status filters and stale derived entries from producing\n // short pages or cursors that skip matching runs.\n while (matches.length <= limit && !exhausted) {\n const kvList = await deps.listRuns({\n prefix,\n limit: Math.min(MAX_RUN_LIST_LIMIT, Math.max(50, limit)),\n cursor: scanCursor,\n reverse,\n });\n if (kvList.keys.length === 0) {\n exhausted = true;\n break;\n }\n\n const candidates: Array<{ key: string; metadata: RunIndexMetadata }> = [];\n for (const key of kvList.keys) {\n const metadata = JSON.parse(key.value) as RunIndexMetadata;\n // Use monotonic status metadata as a conservative prefilter,\n // then still verify every candidate against the authoritative\n // run below. Earlier metadata cannot exclude a later status.\n if (statuses?.every((status) => indexStatusExcludes(metadata.status, status))) {\n continue;\n }\n candidates.push({ key: key.name, metadata });\n }\n\n // Fetch enough candidates to prove the requested page and hasMore,\n // retaining index order while limiting concurrent cross-run reads.\n for (let offset = 0; offset < candidates.length && matches.length <= limit;) {\n const needed = limit + 1 - matches.length;\n const batch = candidates.slice(offset, offset + Math.min(RUN_LIST_CONCURRENCY, needed));\n const resolved = await Promise.all(\n batch.map(async ({ key, metadata }) => {\n const run = await deps.readRun(metadata.runId);\n return run && (statuses === undefined || statuses.includes(run.status))\n ? { key, run }\n : null;\n }),\n );\n for (const match of resolved) {\n if (match) matches.push(match);\n }\n offset += batch.length;\n }\n\n exhausted = kvList.list_complete;\n scanCursor = kvList.cursor ?? kvList.keys.at(-1)?.name;\n }\n\n const hasMore = matches.length > limit;\n const page = matches.slice(0, limit);\n return {\n data: page.map(({ run }) => (request.resolveData === 'none' ? stripRunData(run) : run)),\n cursor: hasMore ? (page.at(-1)?.key ?? null) : null,\n hasMore,\n };\n}\n"],"mappings":"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"}
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as NativeQueueEnvelope } from "./queue-protocol-8iiZ8o_1.js";
|
|
1
2
|
//#region src/testing/fake-cell.d.ts
|
|
2
3
|
/**
|
|
3
4
|
* In-process fake celld fleet (the eve-ambient celld-harness pattern):
|
|
@@ -168,12 +169,28 @@ declare class FakeFleet {
|
|
|
168
169
|
settle(): Promise<void>;
|
|
169
170
|
}
|
|
170
171
|
//#endregion
|
|
172
|
+
//#region src/worker/queue-delivery.d.ts
|
|
173
|
+
type QueueDeliveryResult = {
|
|
174
|
+
kind: 'complete';
|
|
175
|
+
} | {
|
|
176
|
+
kind: 'suspend';
|
|
177
|
+
timeoutSeconds: number;
|
|
178
|
+
} | {
|
|
179
|
+
kind: 'retry';
|
|
180
|
+
};
|
|
181
|
+
//#endregion
|
|
171
182
|
//#region src/testing/http-harness.d.ts
|
|
183
|
+
interface QueuedMessage {
|
|
184
|
+
body: string;
|
|
185
|
+
delaySeconds: number;
|
|
186
|
+
}
|
|
172
187
|
interface Harness {
|
|
173
188
|
url: string;
|
|
174
189
|
fleet: FakeFleet;
|
|
175
190
|
queueMessages: string[];
|
|
191
|
+
queuePublications: QueuedMessage[];
|
|
176
192
|
queuePayloads: ReadonlyMap<string, string>;
|
|
193
|
+
deliverQueueMessage(secret: string, envelope: NativeQueueEnvelope, attempt: number): Promise<QueueDeliveryResult>;
|
|
177
194
|
close(): Promise<void>;
|
|
178
195
|
}
|
|
179
196
|
interface HarnessOptions {
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","names":[],"sources":["../src/testing/fake-cell.ts","../src/testing/http-harness.ts","../src/testing/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"testing.d.ts","names":[],"sources":["../src/testing/fake-cell.ts","../src/worker/queue-delivery.ts","../src/testing/http-harness.ts","../src/testing/index.ts"],"mappings":";;;;;;;;UAOiB;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf,SAAS;EACT;EACA;;UAGe;EACf;EACA;EACA;EACA;;;;;;;cAmCW;UA6BS;EA5BpB,MAAI;EACJ;WACS;WACA,iBAAiB;UAUlB;UACA;;EAER,WAAW;EACX,gBAAgB;UACR;UAKA;EAKR,YAAoB;EAEd,IAAI,GAAG,cAAc,QAAQ;EAC7B,IAAI,GAAG,iBAAiB,QAAQ,YAAY;EAiB5C,IAAI,GAAG,aAAa,OAAO,IAAI;EAC/B,IAAI,GAAG,SAAS,eAAe,KAAK;EAmBpC,OAAO,cAAc;EACrB,OAAO,iBAAiB;EAgBxB,aAAa;EAIb,KAAK,GAAG,UAAS,kBAAuB,QAAQ,YAAY;EAQ5D,YAAY,GAAG,KAAK,KAAK,oBAAoB,QAAQ,KAAK,QAAQ;;EAsBxE,oBAAoB;EAKd,YAAY;EAIZ,SAAS,aAAa,OAAO;EAI7B,eAAe;EAIrB;EAIA;;EASA,gBAAgB,iBAAiB;;EAKjC,kBACE,WAAW,uCACX,gBACA;;EAMF,iBACE,YAAY,UAAU,iCACtB,QAAK,OACL;;EAMF,aACE,YAAY,MAAM,6BAClB,QAAK;;EAMP,kBAAkB,UAAU;;EAS5B,cAAc,MAAM;;EAQpB,WAAW,SAAS,iBAAiB,oBAAoB;;cAKrD;UAKgB;UAJZ;UACA;UACA;EAER,YAAoB,SAAS;EAEvB,IAAI,GAAG,cAAc,QAAQ;EAC7B,IAAI,GAAG,iBAAiB,QAAQ,YAAY;EAwB5C,IAAI,GAAG,aAAa,OAAO,IAAI;EAC/B,IAAI,GAAG,SAAS,eAAe,KAAK;EAqBpC,OAAO,cAAc;EACrB,OAAO,iBAAiB;UActB;EAQF,KAAK,GAAG,UAAS,kBAAuB,QAAQ,YAAY;EAW5D,YAAY;EAIZ,SAAS,aAAa,OAAO;EAI7B,eAAe;EAIrB;;KAOG,iBACH,cACA;EAEA,OAAO;IAAS;MAAwB;;UAGhC;EACR,UAAU,aAAa;EACvB,SAAS;EACT,cAAc;EACd;EACA;;;;;;;;cAYW;UAKD;UACA;UALF;EACR;EAEA,YACU,SAAS,eAAe,YACxB,UAAS,yBACjB;EAKF,UAAU;IAEN,WAAU;MACC;;IAEX,MAAG;MAAS;;MArCF,OAAA;QAAE;UAAwB;;;UAyChC;;EAsBR,QAAQ,oBAAoB;EAI5B,KAAK,oBAAoB,eAAe;;EAmBxC,YAAY,oBAAoB,eAAe,aAAa;EAM5D,QAAQ;;;;;;;EAUF,iBAAiB;UAsBT;;EAQR,UAAU;;;;KCvgBN;EACN;;EACA;EAAiB;;EACjB;;;;UCGW;EACf;EACA;;UAGe;EACf;EACA,OAAO;EACP;EACA,mBAAmB;EACnB,eAAe;EACf,oBACE,gBACA,UAAU,qBACV,kBACC,QAAQ;EACX,SAAS;;UAGM;EACf;;EAEA;;EAEA,eAAe,oBAAoB,cAAc;;EAEjD,UAAU;;iBAGU,aAAa,UAAS,iBAAsB,QAAQ;;;UC/BzD,iBAAiB;EAChC,QAAQ;;iBAMY,cAAc,UAAS,iBAAsB,QAAQ"}
|