@ewhauser/world-celld 0.3.0 → 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,29 @@
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
+
13
+ ## 0.3.1 (2026-08-19)
14
+
15
+ ## What's Changed
16
+ * perf: reduce runs.list RPC fanout by @ewhauser in https://github.com/ewhauser/world-celld/pull/21
17
+ * perf: remove unused correlation index by @ewhauser in https://github.com/ewhauser/world-celld/pull/23
18
+ * perf: bound QueueDO inflight deadline work by @ewhauser in https://github.com/ewhauser/world-celld/pull/24
19
+ * chore(deps-dev): bump @types/node from 22.20.1 to 26.1.2 by @dependabot[bot] in https://github.com/ewhauser/world-celld/pull/4
20
+ * chore(deps-dev): bump the development-dependencies group across 1 directory with 2 updates by @dependabot[bot] in https://github.com/ewhauser/world-celld/pull/25
21
+ * perf: batch and long-poll stream I/O by @ewhauser in https://github.com/ewhauser/world-celld/pull/26
22
+ * perf: bound cleanup and batch Durable Object storage by @ewhauser in https://github.com/ewhauser/world-celld/pull/27
23
+ * perf: shard workflow indexes by @ewhauser in https://github.com/ewhauser/world-celld/pull/28
24
+
25
+
26
+ **Full Changelog**: https://github.com/ewhauser/world-celld/compare/v0.3.0...v0.3.1
27
+
5
28
  ## 0.3.0 (2026-08-16)
6
29
 
7
30
  ## What's Changed
package/README.md CHANGED
@@ -115,12 +115,14 @@ More deployment detail is in [`celld-worker/README.md`](./celld-worker/README.md
115
115
  ```text
116
116
  Workflow application
117
117
  |
118
- | authenticated HTTP RPC
118
+ | authenticated HTTP RPC + binary stream batches
119
119
  v
120
120
  celld worker router
121
121
  |-- WorkflowRunDO one cell per workflow run
122
+ |-- RunCatalogDO 16 stable run-id shards; merged ordered listing
123
+ |-- HookTokenDO 32 stable token-ownership shards
124
+ |-- HookIdDO 32 stable hook-id lookup shards
122
125
  |-- StreamDO stream chunks and run/stream indexes
123
- |-- IndexDO run and hook lookup indexes
124
126
  `-- QueueDO delayed delivery, retries, and dead letters
125
127
  |
126
128
  | HTTP callbacks
@@ -129,25 +131,46 @@ Workflow application /.well-known/workflow/v1/flow
129
131
  ```
130
132
 
131
133
  The application-side package implements the Workflow `World` interface and
132
- translates its storage, stream, and queue operations into RPC calls. The celld
133
- worker accepts only a fixed set of methods and routes each request to the named
134
- cell that owns the data.
134
+ translates its storage and queue operations into JSON RPC calls. Stream chunk
135
+ writes and bounded long-poll reads use a binary batch route; stream control and
136
+ retention operations remain fixed, authenticated RPC methods. The worker routes
137
+ each request to the named cell that owns the data.
138
+
139
+ Index routing is a versioned hard-cutover protocol. Run catalog writes hash the
140
+ `runId` across 16 shards, while hook ownership and hook-ID lookup hash their
141
+ natural keys across 32 shards each. A single stateless worker request queries
142
+ all 16 catalog shards in parallel and merges their lexicographic pages before
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
149
+ catalog listing, terminal commits, hook finalization, and hook release to one
150
+ public request each while exposing the internal shard work in measurements.
151
+
152
+ The routing rationale and before/after RPC, storage, latency, and contention
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).
135
157
 
136
158
  ## Configuration
137
159
 
138
160
  Application options can be passed to `createCelldWorld()` unless an environment
139
161
  variable is shown below.
140
162
 
141
- | Option | Environment variable | Default |
142
- | ---------------- | ------------------------ | ------------------------ |
143
- | `fleetUrl` | `CELLD_FLEET_URL` | required |
144
- | `secret` | `CELLD_WORLD_SECRET` | required with `fleetUrl` |
145
- | `baseUrl` | `WORKFLOW_BASE_URL` | `http://localhost:$PORT` |
146
- | `deploymentId` | `CELLD_DEPLOYMENT_ID` | `celld-default` |
147
- | `queueShards` | — | `1` |
148
- | `runRetentionMs` | `CELLD_RUN_RETENTION_MS` | `0` (disabled) |
149
- | `readPollMs` | — | `250` |
150
- | `rpcTimeoutMs` | — | `30000` |
163
+ | Option | Environment variable | Default |
164
+ | ----------------------- | ------------------------ | ------------------------ |
165
+ | `fleetUrl` | `CELLD_FLEET_URL` | required |
166
+ | `secret` | `CELLD_WORLD_SECRET` | required with `fleetUrl` |
167
+ | `baseUrl` | `WORKFLOW_BASE_URL` | `http://localhost:$PORT` |
168
+ | `deploymentId` | `CELLD_DEPLOYMENT_ID` | `celld-default` |
169
+ | `queueShards` | — | `1` |
170
+ | `runRetentionMs` | `CELLD_RUN_RETENTION_MS` | `0` (disabled) |
171
+ | `streamLongPollMs` | — | `20000` |
172
+ | `streamFlushIntervalMs` | — | `0` |
173
+ | `rpcTimeoutMs` | — | `30000` (max `300000`) |
151
174
 
152
175
  The deployed worker also accepts these celld variables:
153
176
 
@@ -156,8 +179,8 @@ The deployed worker also accepts these celld variables:
156
179
  | `WORLD_SECRET` | none | Required bearer secret for RPC routes |
157
180
  | `WORKFLOW_CALLBACK_SECRET` | none | Sent with deliveries as `x-workflow-callback-secret` |
158
181
  | `QUEUE_MAX_ATTEMPTS` | `5` | Attempts before a message is dead-lettered |
159
- | `QUEUE_MAX_INFLIGHT` | `5` | Concurrent deliveries per queue cell |
160
- | `QUEUE_DELIVERY_TIMEOUT_MS` | `300000` | Timeout for an application callback |
182
+ | `QUEUE_MAX_INFLIGHT` | `5` | Concurrent deliveries per queue cell (maximum `128`) |
183
+ | `QUEUE_DELIVERY_TIMEOUT_MS` | `300000` | Callback timeout (maximum `300000`) |
161
184
 
162
185
  `queueShards` is part of queue placement and is pinned when a queue cell is
163
186
  first used. Drain pending work before changing it.
@@ -171,8 +194,13 @@ pending runs are never eligible for automatic cleanup.
171
194
 
172
195
  At expiration, the run cell fences new writes and removes the run's derived
173
196
  indexes, stream chunks, pending and dead-letter queue messages, and durable run
174
- payloads. Cleanup is a persisted, idempotent state machine: an interrupted
175
- phase records its error and re-arms itself with capped backoff.
197
+ payloads. Cleanup is a persisted, idempotent state machine. Each alarm processes
198
+ one bounded page, persists its progress, and re-arms the next alarm; an
199
+ interrupted phase records its error and retries with capped backoff.
200
+
201
+ Terminal hook and wait disposal uses the same alarm mechanism even when run
202
+ retention is disabled, so a terminal event never performs an unbounded storage
203
+ transaction.
176
204
 
177
205
  The final state is a metadata-only tombstone, not an empty cell. It prevents a
178
206
  delayed queue delivery or stale RPC from recreating an expired run. Reads and
@@ -199,6 +227,8 @@ an existing terminal run that has no cleanup record.
199
227
  must be idempotent.
200
228
  - Queue cells expose `stats`, `listDeadLetters`, `redriveDeadLetter`,
201
229
  `purgeDeadLetters`, and `rearmAlarm` through the authenticated RPC endpoint.
230
+ `purgeDeadLetters` deletes at most 128 entries per call; repeat it while its
231
+ result reports `hasMore`.
202
232
  - Run cells expose retention status, scheduling, immediate cleanup, and alarm
203
233
  recovery through `world.retention`.
204
234
  - A new application URL applies to newly enqueued messages. Existing messages
@@ -1,8 +1,10 @@
1
1
  # world-celld worker
2
2
 
3
- The celld-deployable half of `@ewhauser/world-celld`: four cell classes
4
- (WorkflowRunDO, StreamDO, IndexDO, QueueDO) behind an authenticated HTTP RPC
5
- 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
+ Storage, control, and queue methods use fixed JSON RPC routes; stream chunks use
7
+ bounded binary batch writes and binary long-poll reads.
6
8
 
7
9
  ## Deploy
8
10
 
@@ -2,4 +2,12 @@
2
2
  // project directory; this one-liner resolves the real worker through the
3
3
  // application's node_modules so the deployed bundle stays in step with the
4
4
  // installed @ewhauser/world-celld version.
5
- export { IndexDO, QueueDO, StreamDO, WorkflowRunDO, default } from '@ewhauser/world-celld/worker';
5
+ export {
6
+ HookIdDO,
7
+ HookTokenDO,
8
+ QueueDO,
9
+ RunCatalogDO,
10
+ StreamDO,
11
+ WorkflowRunDO,
12
+ default,
13
+ } from '@ewhauser/world-celld/worker';
@@ -9,19 +9,28 @@
9
9
  "bindings": [
10
10
  { "name": "WORKFLOW_DB", "class_name": "WorkflowRunDO" },
11
11
  { "name": "WORKFLOW_STREAMS", "class_name": "StreamDO" },
12
- { "name": "WORKFLOW_INDEX", "class_name": "IndexDO" },
12
+ { "name": "WORKFLOW_RUN_CATALOG", "class_name": "RunCatalogDO" },
13
+ { "name": "WORKFLOW_HOOK_TOKENS", "class_name": "HookTokenDO" },
14
+ { "name": "WORKFLOW_HOOK_IDS", "class_name": "HookIdDO" },
13
15
  { "name": "WORKFLOW_QUEUE", "class_name": "QueueDO" },
14
16
  ],
15
17
  },
16
18
  "migrations": [
17
19
  {
18
20
  "tag": "v1",
19
- "new_sqlite_classes": ["WorkflowRunDO", "StreamDO", "IndexDO", "QueueDO"],
21
+ "new_sqlite_classes": [
22
+ "WorkflowRunDO",
23
+ "StreamDO",
24
+ "RunCatalogDO",
25
+ "HookTokenDO",
26
+ "HookIdDO",
27
+ "QueueDO",
28
+ ],
20
29
  },
21
30
  ],
22
31
  "vars": {
23
- // REQUIRED: bearer secret for the world's RPC surface. All /v1/rpc
24
- // routes fail closed with 503 while this is empty. Inject the real value
32
+ // REQUIRED: bearer secret for the world's RPC and binary stream surface.
33
+ // Authenticated routes fail closed with 503 while this is empty. Inject the real value
25
34
  // at the node level with CELLD_VAR_WORLD_SECRET instead of committing it.
26
35
  "WORLD_SECRET": "",
27
36
  // Optional: forwarded as x-workflow-callback-secret on queue deliveries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CreateEventParams, CreateEventRequest, Event, Hook, RunCreatedEventRequest, Step, TerminalWorkflowRunStatus, ValidQueueName, Wait, WorkflowRun, World } from "@workflow/world";
1
+ import { CreateEventParams, CreateEventRequest, Event, GetChunksOptions, Hook, RunCreatedEventRequest, Step, StreamChunksResponse, StreamInfoResponse, Streamer, TerminalWorkflowRunStatus, ValidQueueName, Wait, WorkflowRun, World } from "@workflow/world";
2
2
  //#region src/retention.d.ts
3
3
  type CleanupPhase = 'retained' | 'index' | 'streams' | 'queues' | 'payload' | 'tombstoned';
4
4
  interface CleanupRecord {
@@ -11,6 +11,8 @@ interface CleanupRecord {
11
11
  dueAt: Date;
12
12
  queueShards: number;
13
13
  phase: CleanupPhase;
14
+ /** Optimistic-concurrency token for alarm/RPC work that awaits another cell. */
15
+ generation: number;
14
16
  attempts: number;
15
17
  lastError?: string;
16
18
  lastAttemptAt?: Date;
@@ -26,7 +28,10 @@ interface RunTombstone {
26
28
  completedAt: Date;
27
29
  expiredAt: Date;
28
30
  tombstonedAt: Date;
31
+ /** Final cleanup accounting retained inside the single authoritative record. */
32
+ cleanup: CleanupRecord;
29
33
  }
34
+ type RunLifecycleStatus = 'active' | 'terminal' | 'expired' | 'missing';
30
35
  type RunReadOutcome<T> = {
31
36
  ok: true;
32
37
  value: T;
@@ -40,6 +45,13 @@ interface HookIndexReference {
40
45
  hookId: string;
41
46
  token: string;
42
47
  }
48
+ interface ReleaseHookIndexesRequest {
49
+ runId: string;
50
+ hooks: HookIndexReference[];
51
+ }
52
+ interface ReleaseHookIndexesResult {
53
+ deleted: number;
54
+ }
43
55
  interface ExpireRunIndexesRequest {
44
56
  runId: string;
45
57
  keys: string[];
@@ -52,12 +64,36 @@ interface ExpireRunIndexesResult {
52
64
  interface ExpireRunStreamsResult {
53
65
  streams: string[];
54
66
  }
67
+ interface FinalizeRunStreamsResult {
68
+ /** Cumulative registry entries removed for this run. */
69
+ deleted: number;
70
+ done: boolean;
71
+ }
55
72
  interface ExpireStreamResult {
73
+ /** True only when this call installed the stream's expiration fence. */
56
74
  deleted: boolean;
75
+ /** Chunk rows removed by this bounded call. */
57
76
  chunks: number;
77
+ /** Payload bytes represented by the removed chunk rows. */
78
+ bytes: number;
79
+ done: boolean;
80
+ }
81
+ interface QueueExpiryReceipt {
82
+ expiredAt: number;
83
+ deleted: number;
58
84
  }
59
- interface ExpireQueueRunResult {
85
+ type ExpireQueueRunResult = {
86
+ /** Cumulative messages removed for this run in this queue shard. */
60
87
  deleted: number;
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;
61
97
  }
62
98
  interface ScheduleCleanupRequest {
63
99
  retentionMs: number;
@@ -72,17 +108,19 @@ interface ApplyEventRequest {
72
108
  /** Workflow 5 event-log position and preload options. */
73
109
  params?: CreateEventParams;
74
110
  /**
75
- * Current holder of the hook token per the global KV token index
111
+ * Current holder of the hook token per the sharded token-ownership index
76
112
  * (hook_created only). `null` means the token is unclaimed.
77
113
  */
78
114
  tokenHolder?: {
79
115
  runId: string;
80
116
  hookId: string;
81
117
  } | null;
118
+ /** Exact token/ID reservation fenced on ambiguous-delivery resolution. */
119
+ hookClaimId?: string;
82
120
  /** Internal world-celld retention policy captured with the event. */
83
121
  cleanup?: ScheduleCleanupRequest;
84
122
  }
85
- type ApplyEventErrorCode = 'RUN_NOT_FOUND' | 'STEP_NOT_FOUND' | 'HOOK_NOT_FOUND' | 'WAIT_NOT_FOUND' | 'ENTITY_CONFLICT' | 'RUN_EXPIRED' | 'TOO_EARLY' | 'RUN_NOT_SUPPORTED';
123
+ type ApplyEventErrorCode = 'RUN_NOT_FOUND' | 'STEP_NOT_FOUND' | 'HOOK_NOT_FOUND' | 'WAIT_NOT_FOUND' | 'ENTITY_CONFLICT' | 'HOOK_CLAIM_CANCELLED' | 'RUN_EXPIRED' | 'TOO_EARLY' | 'RUN_NOT_SUPPORTED';
86
124
  interface ApplyEventFailure {
87
125
  ok: false;
88
126
  code: ApplyEventErrorCode;
@@ -102,7 +140,7 @@ interface ApplyEventSuccess {
102
140
  wait?: Wait;
103
141
  /** True when a lazy step_started atomically created its step. */
104
142
  stepCreated?: true;
105
- /** Hooks whose tokens must be released from the global KV index. */
143
+ /** Hooks whose token and ID indexes must be released. */
106
144
  releasedHooks: Array<{
107
145
  hookId: string;
108
146
  token: string;
@@ -112,7 +150,7 @@ interface ApplyEventSuccess {
112
150
  workflowName: string;
113
151
  createdAt: Date;
114
152
  };
115
- /** Set when the global KV hook index must be (re)written. */
153
+ /** Set when the sharded hook indexes must be (re)written. */
116
154
  hookToIndex?: Hook;
117
155
  /** All events (ascending), preloaded for run_started responses. */
118
156
  events?: Event[];
@@ -121,6 +159,8 @@ interface ApplyEventSuccess {
121
159
  hasMore?: boolean;
122
160
  /** Server-owned event ceiling advertised on run lifecycle writes. */
123
161
  maxEvents?: number;
162
+ /** Deadline for publishing this authoritative mutation to derivative indexes. */
163
+ indexPublicationExpiresAt?: number;
124
164
  }
125
165
  type ApplyEventOutcome = ApplyEventSuccess | ApplyEventFailure;
126
166
  //#endregion
@@ -131,6 +171,14 @@ type ApplyEventOutcome = ApplyEventSuccess | ApplyEventFailure;
131
171
  */
132
172
  interface WorkflowRunDOStub {
133
173
  applyEvent(request: ApplyEventRequest): Promise<ApplyEventOutcome>;
174
+ resolveHookTokenClaim(request: {
175
+ hookId: string;
176
+ token: string;
177
+ claimId: string;
178
+ }): Promise<{
179
+ committed: boolean;
180
+ }>;
181
+ getLifecycleStatus(): Promise<RunLifecycleStatus>;
134
182
  getRun(): Promise<RunReadOutcome<WorkflowRun | null>>;
135
183
  getStep(stepId: string): Promise<RunReadOutcome<Step | null>>;
136
184
  getEvent(eventId: string): Promise<RunReadOutcome<Event | null>>;
@@ -174,32 +222,74 @@ interface DurableObjectIdLike {
174
222
  toString(): string;
175
223
  }
176
224
  //#endregion
225
+ //#region src/stream-protocol.d.ts
226
+ /** Metadata plus payload and size-index entries remain below the 128-key platform limit. */
227
+ declare const MAX_STREAM_WRITE_CHUNKS = 32;
228
+ /** A chunk remains below the 2 MiB SQLite-backed DO key/value limit. */
229
+ declare const MAX_STREAM_CHUNK_BYTES: number;
230
+ /** Keeps serialized RPC bodies well below the 32 MiB Workers RPC limit. */
231
+ declare const MAX_STREAM_BATCH_BYTES: number;
232
+ declare const MAX_STREAM_READ_CHUNKS = 32;
233
+ declare const MAX_STREAM_READ_BYTES: number;
234
+ declare const MAX_STREAM_ERROR_BYTES: number;
235
+ /** Must remain below the default 30 second fleet request deadline. */
236
+ declare const MAX_STREAM_LONG_POLL_MS = 20000;
237
+ type StreamTerminalState = 'open' | 'closed' | 'errored' | 'expired';
238
+ interface StreamErrorData {
239
+ name: string;
240
+ message: string;
241
+ }
242
+ interface StreamWriteResult {
243
+ startIndex: number;
244
+ count: number;
245
+ tailIndex: number;
246
+ }
247
+ interface StreamReadRequest {
248
+ runId: string;
249
+ startIndex: number;
250
+ maxChunks: number;
251
+ maxBytes: number;
252
+ waitMs: number;
253
+ }
254
+ interface StreamReadResult {
255
+ startIndex: number;
256
+ tailIndex: number;
257
+ chunks: Uint8Array[];
258
+ state: StreamTerminalState;
259
+ timedOut: boolean;
260
+ error?: StreamErrorData;
261
+ }
262
+ //#endregion
177
263
  //#region src/streamer.d.ts
178
- /**
179
- * RPC surface of StreamDO (see durable-objects/StreamDO.ts). The streamer
180
- * talks to the DO exclusively via these methods — there is no fetch()
181
- * protocol.
182
- */
264
+ interface CelldStreamer extends Omit<Streamer, 'streams'> {
265
+ streams: Streamer['streams'] & {
266
+ fail(runId: string, name: string, error: StreamErrorData | string): Promise<void>;
267
+ };
268
+ writeToStream(name: string, runId: string | Promise<string>, chunk: string | Uint8Array): Promise<void>;
269
+ writeChunksToStream(name: string, runId: string | Promise<string>, chunks: readonly (string | Uint8Array)[]): Promise<void>;
270
+ closeStream(name: string, runId: string | Promise<string>): Promise<void>;
271
+ errorStream(name: string, runId: string | Promise<string>, error: StreamErrorData | string): Promise<void>;
272
+ readFromStream(name: string, runId: string, startIndex?: number): Promise<ReadableStream<Uint8Array>>;
273
+ listStreamsByRunId(runId: string): Promise<string[]>;
274
+ getStreamChunks(name: string, runId: string, options?: GetChunksOptions): Promise<StreamChunksResponse>;
275
+ getStreamInfo(name: string, runId: string): Promise<StreamInfoResponse>;
276
+ }
277
+ /** Direct StreamDO RPC surface. Remote stubs specialize read/write as binary HTTP. */
183
278
  interface StreamDOStub {
184
- writeChunk(runId: string, data: Uint8Array): Promise<number>;
279
+ writeChunks(runId: string, chunks: Uint8Array[]): Promise<StreamWriteResult>;
280
+ readChunks(request: StreamReadRequest, signal?: AbortSignal): Promise<StreamReadResult>;
185
281
  closeStream(runId: string): Promise<void>;
186
- getChunks(params: {
187
- startIndex: number;
188
- limit: number;
189
- }): Promise<{
190
- chunks: Uint8Array[];
191
- done: boolean;
192
- tailIndex: number;
193
- }>;
194
- getInfo(): Promise<{
195
- tailIndex: number;
196
- done: boolean;
197
- }>;
282
+ failStream(runId: string, error: StreamErrorData | string): Promise<void>;
198
283
  registerStream(runId: string, name: string): Promise<void>;
199
284
  listStreams(): Promise<string[]>;
200
- expireRegistry(runId: string, expiredAt: number): Promise<ExpireRunStreamsResult>;
201
- finalizeRegistry(runId: string): Promise<void>;
202
- expireStream(runId: string, expiredAt: number): Promise<ExpireStreamResult>;
285
+ expireRegistry(runId: string, expiredAt: number, options?: {
286
+ limit?: number;
287
+ }): Promise<ExpireRunStreamsResult>;
288
+ finalizeRegistry(runId: string, streams: string[]): Promise<FinalizeRunStreamsResult>;
289
+ expireStream(runId: string, expiredAt: number, options?: {
290
+ limit?: number;
291
+ byteLimit?: number;
292
+ }): Promise<ExpireStreamResult>;
203
293
  }
204
294
  interface StreamDONamespace {
205
295
  idFromName(name: string): StreamDOId;
@@ -249,7 +339,10 @@ type EnqueueOutcome = {
249
339
  /** RPC surface of QueueDO used by the queue producer. */
250
340
  interface QueueCellStub {
251
341
  enqueue(request: EnqueueRequest): Promise<EnqueueOutcome>;
252
- expireRun(runId: string, expiredAt: number): Promise<ExpireQueueRunResult>;
342
+ expireRun(runId: string, expiredAt: number, options?: {
343
+ limit?: number;
344
+ }): Promise<ExpireQueueRunResult>;
345
+ acknowledgeExpireRun(runId: string, receipt: QueueExpiryReceipt): Promise<AcknowledgeQueueExpiryResult>;
253
346
  }
254
347
  interface QueueCellNamespace {
255
348
  idFromName(name: string): {
@@ -260,36 +353,51 @@ interface QueueCellNamespace {
260
353
  }): QueueCellStub;
261
354
  }
262
355
  //#endregion
263
- //#region src/config.d.ts
264
- /** Storage-layer KV interface (satisfied by IndexDO over HTTP, or a mock). */
265
- interface IndexNamespace {
266
- get(key: string): Promise<string | null>;
267
- put(key: string, value: string): Promise<void>;
268
- delete(key: string): Promise<void>;
269
- putOwned(runId: string, key: string, value: string): Promise<{
356
+ //#region src/indexes.d.ts
357
+ interface IndexListOptions {
358
+ prefix?: string;
359
+ cursor?: string;
360
+ limit?: number;
361
+ reverse?: boolean;
362
+ }
363
+ interface IndexListPage {
364
+ keys: Array<{
365
+ name: string;
366
+ value: string;
367
+ }>;
368
+ list_complete: boolean;
369
+ cursor?: string;
370
+ }
371
+ interface HookReservation {
372
+ claimId: string;
373
+ tokenClaimId?: string;
374
+ hookIdClaimId?: string;
375
+ }
376
+ type HookReservationResult = {
377
+ admitted: true;
378
+ reservation: HookReservation;
379
+ } | {
380
+ admitted: false;
381
+ holder: HookTokenOwner;
382
+ };
383
+ /** High-level client used by the World storage layer and retention coordinator. */
384
+ interface WorkflowIndex {
385
+ commitRun(run: WorkflowRun, serializedMetadata: string, publicationExpiresAt: number): Promise<{
270
386
  stored: boolean;
271
387
  }>;
388
+ listRuns(options?: IndexListOptions): Promise<IndexListPage>;
389
+ getHookByToken(token: string): Promise<string | null>;
390
+ getHookById(hookId: string): Promise<string | null>;
391
+ reserveHook(token: string, owner: HookTokenOwner): Promise<HookReservationResult>;
392
+ finalizeHookIndexes(token: string, hookId: string, serializedHook: string, owner: HookTokenOwner, reservation?: HookReservation): Promise<void>;
393
+ releaseHookReservation(token: string, owner: HookTokenOwner, reservation: HookReservation): Promise<void>;
394
+ releaseHookIndexes(request: ReleaseHookIndexesRequest): Promise<ReleaseHookIndexesResult>;
272
395
  expireRun(request: ExpireRunIndexesRequest): Promise<ExpireRunIndexesResult>;
273
- list(options?: {
274
- prefix?: string;
275
- cursor?: string;
276
- limit?: number;
277
- reverse?: boolean;
278
- }): Promise<{
279
- keys: Array<{
280
- name: string;
281
- }>;
282
- list_complete: boolean;
283
- cursor?: string;
284
- }>;
285
- reserveHookToken(token: string, owner: HookTokenOwner): Promise<{
286
- claimed: boolean;
287
- holder?: HookTokenOwner;
288
- }>;
289
- finalizeHookIndexes(token: string, hookId: string, serializedHook: string, owner: HookTokenOwner): Promise<void>;
290
- releaseHookToken(token: string, owner: HookTokenOwner): Promise<void>;
291
- deleteHookIndexes(token: string, hookId: string, owner: HookTokenOwner): Promise<void>;
292
396
  }
397
+ //#endregion
398
+ //#region src/config.d.ts
399
+ /** Public alias retained for custom in-process environments. */
400
+ type IndexNamespace = WorkflowIndex;
293
401
  interface HookTokenOwner {
294
402
  runId: string;
295
403
  hookId: string;
@@ -334,8 +442,10 @@ interface CelldWorldConfig {
334
442
  * Default: process.env.CELLD_RUN_RETENTION_MS || 0
335
443
  */
336
444
  runRetentionMs?: number;
337
- /** Poll interval (ms) while waiting for new chunks on a live stream. Default: 250 */
338
- readPollMs?: number;
445
+ /** Duration of one bounded idle stream read. Default: 20000 */
446
+ streamLongPollMs?: number;
447
+ /** Runtime stream batching delay. Default: 0 */
448
+ streamFlushIntervalMs?: number;
339
449
  /** Per-attempt fleet RPC deadline in milliseconds. Default: 30000 */
340
450
  rpcTimeoutMs?: number;
341
451
  }
@@ -347,10 +457,10 @@ interface CelldRetentionAdmin {
347
457
  cleanupNow(runId: string): Promise<CleanupRecord | null>;
348
458
  rearm(runId: string): Promise<CleanupRecord | null>;
349
459
  }
350
- type CelldWorld = World & {
460
+ type CelldWorld = World & CelldStreamer & {
351
461
  retention: CelldRetentionAdmin;
352
462
  };
353
463
  declare function createCelldWorld(config?: CelldWorldConfig): CelldWorld;
354
464
  //#endregion
355
- export { CelldRetentionAdmin, CelldWorld, type CelldWorldConfig, type CelldWorldEnv, type CleanupPhase, type CleanupRecord, type EnqueueOutcome, type EnqueueRequest, type IndexNamespace, type QueueCellConfig, type QueueCellNamespace, type QueueCellStub, type RunTombstone, type StreamDONamespace, type StreamDOStub, type WorkflowRunDONamespace, type WorkflowRunDOStub, createCelldWorld, createCelldWorld as createWorld };
465
+ export { CelldRetentionAdmin, CelldWorld, type CelldWorldConfig, type CelldWorldEnv, type CleanupPhase, type CleanupRecord, type EnqueueOutcome, type EnqueueRequest, type IndexNamespace, MAX_STREAM_BATCH_BYTES, MAX_STREAM_CHUNK_BYTES, MAX_STREAM_ERROR_BYTES, MAX_STREAM_LONG_POLL_MS, MAX_STREAM_READ_BYTES, MAX_STREAM_READ_CHUNKS, MAX_STREAM_WRITE_CHUNKS, type QueueCellConfig, type QueueCellNamespace, type QueueCellStub, type RunTombstone, type StreamDONamespace, type StreamDOStub, type StreamErrorData, type StreamReadRequest, type StreamReadResult, type StreamTerminalState, type StreamWriteResult, type WorkflowRunDONamespace, type WorkflowRunDOStub, createCelldWorld, createCelldWorld as createWorld };
356
466
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retention.ts","../src/apply-event.ts","../src/storage.ts","../src/streamer.ts","../src/queue.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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"}