@ewhauser/world-celld 0.3.1 → 0.3.2

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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.3.2 (2026-08-19)
6
+
7
+ ## What's Changed
8
+ * fix: compact expired-run lifecycle fences by @ewhauser in https://github.com/ewhauser/world-celld/pull/29
9
+
10
+
11
+ **Full Changelog**: https://github.com/ewhauser/world-celld/compare/v0.3.1...v0.3.2
12
+
5
13
  ## 0.3.1 (2026-08-19)
6
14
 
7
15
  ## What's Changed
package/README.md CHANGED
@@ -120,7 +120,6 @@ Workflow application
120
120
  celld worker router
121
121
  |-- WorkflowRunDO one cell per workflow run
122
122
  |-- RunCatalogDO 16 stable run-id shards; merged ordered listing
123
- |-- RunFenceDO one lifecycle fence cell per workflow run
124
123
  |-- HookTokenDO 32 stable token-ownership shards
125
124
  |-- HookIdDO 32 stable hook-id lookup shards
126
125
  |-- StreamDO stream chunks and run/stream indexes
@@ -141,17 +140,20 @@ Index routing is a versioned hard-cutover protocol. Run catalog writes hash the
141
140
  `runId` across 16 shards, while hook ownership and hook-ID lookup hash their
142
141
  natural keys across 32 shards each. A single stateless worker request queries
143
142
  all 16 catalog shards in parallel and merges their lexicographic pages before
144
- authoritative RunDO reads. A terminal or expired run is hidden through its own
145
- `RunFenceDO`, so no global fence cell remains. Token and hook-ID admission are
146
- each transactional inside their natural-key shards. The RunDO remains the
147
- authoritative commit domain, and exact claim IDs plus a serialized cancellation
148
- fence resolve ambiguous delivery without pretending the two ownership shards
149
- form a cross-Durable-Object transaction. Stateless cohesive index routes keep
143
+ authoritative RunDO reads. The RunDO is also the only permanent lifecycle
144
+ authority: hook shards consult it directly, while queue and catalog expiry
145
+ fences compact after bounded protocol leases. Token and hook-ID admission are
146
+ each transactional inside their natural-key shards. Exact claim IDs plus a
147
+ serialized cancellation fence resolve ambiguous delivery without pretending
148
+ the two ownership shards form a cross-Durable-Object transaction. Stateless cohesive index routes keep
150
149
  catalog listing, terminal commits, hook finalization, and hook release to one
151
150
  public request each while exposing the internal shard work in measurements.
152
151
 
153
152
  The routing rationale and before/after RPC, storage, latency, and contention
154
153
  evidence are recorded in [`docs/index-sharding.md`](./docs/index-sharding.md).
154
+ The expiry authority, producer/consumer map, bounded horizons, and
155
+ post-compaction costs are recorded in
156
+ [`docs/lifecycle-compaction.md`](./docs/lifecycle-compaction.md).
155
157
 
156
158
  ## Configuration
157
159
 
@@ -168,7 +170,7 @@ variable is shown below.
168
170
  | `runRetentionMs` | `CELLD_RUN_RETENTION_MS` | `0` (disabled) |
169
171
  | `streamLongPollMs` | — | `20000` |
170
172
  | `streamFlushIntervalMs` | — | `0` |
171
- | `rpcTimeoutMs` | — | `30000` |
173
+ | `rpcTimeoutMs` | — | `30000` (max `300000`) |
172
174
 
173
175
  The deployed worker also accepts these celld variables:
174
176
 
@@ -178,7 +180,7 @@ The deployed worker also accepts these celld variables:
178
180
  | `WORKFLOW_CALLBACK_SECRET` | none | Sent with deliveries as `x-workflow-callback-secret` |
179
181
  | `QUEUE_MAX_ATTEMPTS` | `5` | Attempts before a message is dead-lettered |
180
182
  | `QUEUE_MAX_INFLIGHT` | `5` | Concurrent deliveries per queue cell (maximum `128`) |
181
- | `QUEUE_DELIVERY_TIMEOUT_MS` | `300000` | Timeout for an application callback |
183
+ | `QUEUE_DELIVERY_TIMEOUT_MS` | `300000` | Callback timeout (maximum `300000`) |
182
184
 
183
185
  `queueShards` is part of queue placement and is pinned when a queue cell is
184
186
  first used. Drain pending work before changing it.
@@ -1,8 +1,8 @@
1
1
  # world-celld worker
2
2
 
3
- The celld-deployable half of `@ewhauser/world-celld`: seven cell classes
4
- (WorkflowRunDO, RunCatalogDO, RunFenceDO, HookTokenDO, HookIdDO, StreamDO, and
5
- QueueDO) behind an authenticated HTTP router.
3
+ The celld-deployable half of `@ewhauser/world-celld`: six cell classes
4
+ (WorkflowRunDO, RunCatalogDO, HookTokenDO, HookIdDO, StreamDO, and QueueDO)
5
+ behind an authenticated HTTP router.
6
6
  Storage, control, and queue methods use fixed JSON RPC routes; stream chunks use
7
7
  bounded binary batch writes and binary long-poll reads.
8
8
 
@@ -7,7 +7,6 @@ export {
7
7
  HookTokenDO,
8
8
  QueueDO,
9
9
  RunCatalogDO,
10
- RunFenceDO,
11
10
  StreamDO,
12
11
  WorkflowRunDO,
13
12
  default,
@@ -10,7 +10,6 @@
10
10
  { "name": "WORKFLOW_DB", "class_name": "WorkflowRunDO" },
11
11
  { "name": "WORKFLOW_STREAMS", "class_name": "StreamDO" },
12
12
  { "name": "WORKFLOW_RUN_CATALOG", "class_name": "RunCatalogDO" },
13
- { "name": "WORKFLOW_RUN_FENCES", "class_name": "RunFenceDO" },
14
13
  { "name": "WORKFLOW_HOOK_TOKENS", "class_name": "HookTokenDO" },
15
14
  { "name": "WORKFLOW_HOOK_IDS", "class_name": "HookIdDO" },
16
15
  { "name": "WORKFLOW_QUEUE", "class_name": "QueueDO" },
@@ -23,7 +22,6 @@
23
22
  "WorkflowRunDO",
24
23
  "StreamDO",
25
24
  "RunCatalogDO",
26
- "RunFenceDO",
27
25
  "HookTokenDO",
28
26
  "HookIdDO",
29
27
  "QueueDO",
package/dist/index.d.ts CHANGED
@@ -28,7 +28,10 @@ interface RunTombstone {
28
28
  completedAt: Date;
29
29
  expiredAt: Date;
30
30
  tombstonedAt: Date;
31
+ /** Final cleanup accounting retained inside the single authoritative record. */
32
+ cleanup: CleanupRecord;
31
33
  }
34
+ type RunLifecycleStatus = 'active' | 'terminal' | 'expired' | 'missing';
32
35
  type RunReadOutcome<T> = {
33
36
  ok: true;
34
37
  value: T;
@@ -45,8 +48,6 @@ interface HookIndexReference {
45
48
  interface ReleaseHookIndexesRequest {
46
49
  runId: string;
47
50
  hooks: HookIndexReference[];
48
- /** Install a fence that prevents delayed hook finalization after terminal state. */
49
- terminal: boolean;
50
51
  }
51
52
  interface ReleaseHookIndexesResult {
52
53
  deleted: number;
@@ -77,10 +78,22 @@ interface ExpireStreamResult {
77
78
  bytes: number;
78
79
  done: boolean;
79
80
  }
80
- interface ExpireQueueRunResult {
81
+ interface QueueExpiryReceipt {
82
+ expiredAt: number;
83
+ deleted: number;
84
+ }
85
+ type ExpireQueueRunResult = {
81
86
  /** Cumulative messages removed for this run in this queue shard. */
82
87
  deleted: number;
83
- done: boolean;
88
+ } & ({
89
+ done: false;
90
+ } | {
91
+ done: true;
92
+ /** Durable receipt which the cleanup coordinator must acknowledge. */
93
+ receipt: QueueExpiryReceipt;
94
+ });
95
+ interface AcknowledgeQueueExpiryResult {
96
+ acknowledged: boolean;
84
97
  }
85
98
  interface ScheduleCleanupRequest {
86
99
  retentionMs: number;
@@ -146,6 +159,8 @@ interface ApplyEventSuccess {
146
159
  hasMore?: boolean;
147
160
  /** Server-owned event ceiling advertised on run lifecycle writes. */
148
161
  maxEvents?: number;
162
+ /** Deadline for publishing this authoritative mutation to derivative indexes. */
163
+ indexPublicationExpiresAt?: number;
149
164
  }
150
165
  type ApplyEventOutcome = ApplyEventSuccess | ApplyEventFailure;
151
166
  //#endregion
@@ -163,6 +178,7 @@ interface WorkflowRunDOStub {
163
178
  }): Promise<{
164
179
  committed: boolean;
165
180
  }>;
181
+ getLifecycleStatus(): Promise<RunLifecycleStatus>;
166
182
  getRun(): Promise<RunReadOutcome<WorkflowRun | null>>;
167
183
  getStep(stepId: string): Promise<RunReadOutcome<Step | null>>;
168
184
  getEvent(eventId: string): Promise<RunReadOutcome<Event | null>>;
@@ -326,6 +342,7 @@ interface QueueCellStub {
326
342
  expireRun(runId: string, expiredAt: number, options?: {
327
343
  limit?: number;
328
344
  }): Promise<ExpireQueueRunResult>;
345
+ acknowledgeExpireRun(runId: string, receipt: QueueExpiryReceipt): Promise<AcknowledgeQueueExpiryResult>;
329
346
  }
330
347
  interface QueueCellNamespace {
331
348
  idFromName(name: string): {
@@ -365,7 +382,7 @@ type HookReservationResult = {
365
382
  };
366
383
  /** High-level client used by the World storage layer and retention coordinator. */
367
384
  interface WorkflowIndex {
368
- commitRun(run: WorkflowRun, serializedMetadata: string): Promise<{
385
+ commitRun(run: WorkflowRun, serializedMetadata: string, publicationExpiresAt: number): Promise<{
369
386
  stored: boolean;
370
387
  }>;
371
388
  listRuns(options?: IndexListOptions): Promise<IndexListPage>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retention.ts","../src/apply-event.ts","../src/storage.ts","../src/stream-protocol.ts","../src/streamer.ts","../src/queue.ts","../src/indexes.ts","../src/config.ts","../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retention.ts","../src/apply-event.ts","../src/storage.ts","../src/stream-protocol.ts","../src/streamer.ts","../src/queue.ts","../src/indexes.ts","../src/config.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { S as normalizeStreamError, a as stringify, b as encodeStreamWriteBatch, c as MAX_STREAM_BATCH_BYTES, d as MAX_STREAM_LONG_POLL_MS, f as MAX_STREAM_READ_BYTES, g as decodeStreamReadResult, h as STREAM_BATCH_CONTENT_TYPE, i as parse, l as MAX_STREAM_CHUNK_BYTES, m as MAX_STREAM_WRITE_CHUNKS, n as rpcParse, o as createWorkflowIndex, p as MAX_STREAM_READ_CHUNKS, r as rpcStringify, t as compact, u as MAX_STREAM_ERROR_BYTES, v as decodeStreamWriteResult } from "./util-DmO0XkFw.js";
1
+ import { C as decodeStreamReadResult, D as encodeStreamWriteBatch, S as STREAM_BATCH_CONTENT_TYPE, T as decodeStreamWriteResult, _ as MAX_STREAM_ERROR_BYTES, a as stringify, b as MAX_STREAM_READ_CHUNKS, g as MAX_STREAM_CHUNK_BYTES, h as MAX_STREAM_BATCH_BYTES, i as parse, k as normalizeStreamError, n as rpcParse, o as createWorkflowIndex, r as rpcStringify, t as compact, u as MAX_FLEET_RPC_TIMEOUT_MS, v as MAX_STREAM_LONG_POLL_MS, x as MAX_STREAM_WRITE_CHUNKS, y as MAX_STREAM_READ_BYTES } from "./util-ya3V_FTA.js";
2
2
  import { EventSchema, HookSchema, MessageId, SPEC_VERSION_CURRENT, StepSchema, WorkflowRunSchema, isTerminalWorkflowRunStatus, parseQueueName } from "@workflow/world";
3
3
  import { EntityConflictError, HookNotFoundError, RunExpiredError, RunNotSupportedError, TooEarlyError, WorkflowRunNotFoundError, WorkflowWorldError } from "@workflow/errors";
4
4
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
@@ -9,7 +9,7 @@ function resolveConfig(config) {
9
9
  const runRetentionMs = typeof retentionRaw === "number" ? retentionRaw : Number.parseInt(retentionRaw, 10);
10
10
  if (!Number.isSafeInteger(runRetentionMs) || runRetentionMs < 0) throw new Error("world-celld: runRetentionMs must be a non-negative safe integer");
11
11
  const rpcTimeoutMs = config?.rpcTimeoutMs ?? 3e4;
12
- if (!Number.isSafeInteger(rpcTimeoutMs) || rpcTimeoutMs < 1) throw new Error("world-celld: rpcTimeoutMs must be a positive safe integer");
12
+ if (!Number.isSafeInteger(rpcTimeoutMs) || rpcTimeoutMs < 1 || rpcTimeoutMs > 3e5) throw new Error(`world-celld: rpcTimeoutMs must be between 1 and ${MAX_FLEET_RPC_TIMEOUT_MS}`);
13
13
  const streamLongPollMs = config?.streamLongPollMs ?? Math.min(2e4, Math.max(1, rpcTimeoutMs - 1e3));
14
14
  if (!Number.isSafeInteger(streamLongPollMs) || streamLongPollMs < 1 || streamLongPollMs > 2e4) throw new Error(`world-celld: streamLongPollMs must be between 1 and ${MAX_STREAM_LONG_POLL_MS}`);
15
15
  if (streamLongPollMs >= rpcTimeoutMs) throw new Error("world-celld: streamLongPollMs must be less than rpcTimeoutMs");
@@ -79,6 +79,8 @@ async function callFleetRoute(transport, path, args, opts) {
79
79
  const doFetch = transport.fetchImpl ?? fetch;
80
80
  const url = `${transport.fleetUrl.replace(/\/$/, "")}${path}`;
81
81
  const attempts = opts?.idempotent ? 3 : 1;
82
+ const timeoutMs = transport.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
83
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 3e5) throw new Error(`world-celld: fleet RPC timeout must be between 1 and ${MAX_FLEET_RPC_TIMEOUT_MS}`);
82
84
  let lastError;
83
85
  for (let attempt = 1; attempt <= attempts; attempt++) {
84
86
  if (attempt > 1) await delayMs$1(100 * attempt + Math.random() * 200);
@@ -91,7 +93,7 @@ async function callFleetRoute(transport, path, args, opts) {
91
93
  authorization: `Bearer ${transport.secret}`
92
94
  },
93
95
  body: rpcStringify(args),
94
- signal: AbortSignal.timeout(Math.max(1, transport.timeoutMs ?? DEFAULT_TIMEOUT_MS$1))
96
+ signal: AbortSignal.timeout(timeoutMs)
95
97
  });
96
98
  } catch (error) {
97
99
  lastError = new FleetTransportError(`world-celld: fleet unreachable at ${url}`, error);
@@ -258,6 +260,7 @@ async function readStreamChunks(transport, name, request, signal) {
258
260
  const RUNS = {
259
261
  methods: [
260
262
  "applyEvent",
263
+ "getLifecycleStatus",
261
264
  "getRun",
262
265
  "getStep",
263
266
  "getEvent",
@@ -318,14 +321,16 @@ const QUEUE = {
318
321
  "redriveDeadLetter",
319
322
  "purgeDeadLetters",
320
323
  "rearmAlarm",
321
- "expireRun"
324
+ "expireRun",
325
+ "acknowledgeExpireRun"
322
326
  ],
323
327
  mutating: /* @__PURE__ */ new Set([
324
328
  "enqueue",
325
329
  "redriveDeadLetter",
326
330
  "purgeDeadLetters",
327
331
  "rearmAlarm",
328
- "expireRun"
332
+ "expireRun",
333
+ "acknowledgeExpireRun"
329
334
  ])
330
335
  };
331
336
  function makeStub(transport, binding, name, spec) {
@@ -351,14 +356,6 @@ const RUN_CATALOG = {
351
356
  ],
352
357
  mutating: /* @__PURE__ */ new Set()
353
358
  };
354
- const RUN_FENCES = {
355
- methods: [
356
- "getStatus",
357
- "fenceTerminal",
358
- "fenceExpired"
359
- ],
360
- mutating: /* @__PURE__ */ new Set()
361
- };
362
359
  const HOOK_TOKENS = {
363
360
  methods: [
364
361
  "get",
@@ -381,12 +378,10 @@ const HOOK_IDS = {
381
378
  };
382
379
  function createRemoteEnv(transport) {
383
380
  const runCatalog = makeNamespace(transport, "run-catalog", RUN_CATALOG);
384
- const runFences = makeNamespace(transport, "run-fences", RUN_FENCES);
385
381
  const hookTokens = makeNamespace(transport, "hook-tokens", HOOK_TOKENS);
386
382
  const hookIds = makeNamespace(transport, "hook-ids", HOOK_IDS);
387
383
  const workflowIndex = createWorkflowIndex({
388
384
  runCatalog,
389
- runFences,
390
385
  hookTokens,
391
386
  hookIds
392
387
  });
@@ -395,7 +390,11 @@ function createRemoteEnv(transport) {
395
390
  WORKFLOW_STREAMS: makeStreamNamespace(transport),
396
391
  WORKFLOW_INDEX: {
397
392
  ...workflowIndex,
398
- commitRun: (run, serializedMetadata) => callFleetRoute(transport, "/v1/index/runs/commit", [run, serializedMetadata], { idempotent: true }),
393
+ commitRun: (run, serializedMetadata, publicationExpiresAt) => callFleetRoute(transport, "/v1/index/runs/commit", [
394
+ run,
395
+ serializedMetadata,
396
+ publicationExpiresAt
397
+ ], { idempotent: true }),
399
398
  listRuns: (options) => callFleetRoute(transport, "/v1/index/runs/list", [options], { idempotent: true }),
400
399
  expireRun: (request) => callFleetRoute(transport, "/v1/index/runs/expire", [request], { idempotent: true }),
401
400
  reserveHook: (token, owner) => callFleetRoute(transport, "/v1/index/hooks/reserve", [token, owner], { idempotent: true }),
@@ -940,17 +939,16 @@ function createStorage(config) {
940
939
  createdAt: outcome.run.createdAt.toISOString(),
941
940
  status: outcome.run.status
942
941
  });
943
- await env.WORKFLOW_INDEX.commitRun(outcome.run, meta);
942
+ if (outcome.indexPublicationExpiresAt === void 0) throw new Error("world-celld: authoritative run mutation omitted its index lease");
943
+ await env.WORKFLOW_INDEX.commitRun(outcome.run, meta, outcome.indexPublicationExpiresAt);
944
944
  }
945
945
  if (outcome.hookToIndex) {
946
946
  const serialized = stringify(outcome.hookToIndex);
947
947
  await env.WORKFLOW_INDEX.finalizeHookIndexes(outcome.hookToIndex.token, outcome.hookToIndex.hookId, serialized, hookOwner(outcome.hookToIndex), hookAdmission?.reservation);
948
948
  } else if (hookAdmission) await env.WORKFLOW_INDEX.releaseHookReservation(hookAdmission.token, hookAdmission.owner, hookAdmission.reservation);
949
- const terminal = Boolean(outcome.run && isTerminalWorkflowRunStatus(outcome.run.status));
950
949
  if (outcome.releasedHooks.length > 0) await env.WORKFLOW_INDEX.releaseHookIndexes({
951
950
  runId: effectiveRunId,
952
- hooks: outcome.releasedHooks,
953
- terminal
951
+ hooks: outcome.releasedHooks
954
952
  });
955
953
  const eventPage = outcome.events === void 0 ? {} : {
956
954
  events: outcome.events,