@powerhousedao/reactor 6.2.3-dev.33 → 6.2.3-dev.35

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/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { Action, ActionSigner, AuthRequest, AuthSubject, CreateDocumentActionInput, DocumentModelModule, HoldReason, ISigner, Operation, OperationContext, OperationOutcome, OperationWithContext, OperationWithContext as OperationWithContext$1, PHAuthState, PHDocument, PHDocumentState, PeerCapability, PeerCapabilityFlags, PeerManifest, ProtocolVersions, SignaturePolicy, SignatureVerificationHandler, Supports, UpgradeDocumentActionInput, UpgradeManifest, UpgradeReducer, UpgradeTransition, actions as documentActions } from "@powerhousedao/shared/document-model";
1
+ import { Action, ActionSigner, AuthRequest, AuthSubject, CreateDocumentActionInput, DocumentModelModule, HoldReason, ISigner, Operation, OperationContext, OperationContext as OperationContext$1, OperationOutcome, OperationWithContext, OperationWithContext as OperationWithContext$1, PHAuthState, PHDocument, PHDocumentState, PURGE_DOCUMENT, PeerCapability, PeerCapabilityFlags, PeerManifest, ProtocolVersions, PurgeDocumentAction, PurgeDocumentActionInput, PurgeMarkerOperation, SignaturePolicy, SignatureVerificationHandler, Supports, UpgradeDocumentActionInput, UpgradeManifest, UpgradeReducer, UpgradeTransition, actions as documentActions, isPurgeMarker } from "@powerhousedao/shared/document-model";
2
2
  import { DocumentDriveDocument, DriveInput, FolderNode, Node } from "@powerhousedao/shared/document-drive";
3
3
  import { ILogger } from "document-model";
4
- import { ColumnType, Generated, Insertable, Kysely, Transaction } from "kysely";
4
+ import { ColumnType, Generated, Insertable, Kysely, Selectable, Transaction } from "kysely";
5
5
  import { IProcessor, IProcessorHostModuleBase, IProcessorHostModuleBase as IProcessorHostModuleBase$1, IProcessorManager, IProcessorManager as IProcessorManager$1, IRelationalDb, ProcessorApp, ProcessorFactory, ProcessorFactory as ProcessorFactory$1, ProcessorFactoryBuilder, ProcessorFilter, ProcessorRecord, ProcessorRecord as ProcessorRecord$1, ProcessorStatus, RelationalDbProcessor, TrackedProcessor, TrackedProcessor as TrackedProcessor$1, createRelationalDb } from "@powerhousedao/shared/processors";
6
6
  import "node:worker_threads";
7
7
  import { Pool } from "pg";
@@ -55,106 +55,73 @@ export declare function updateRelationshipAction(sourceId: string, targetId: str
55
55
  */
56
56
  export declare function removeRelationshipAction(sourceId: string, targetId: string, relationshipType?: string): Action;
57
57
  //#endregion
58
- //#region src/queue/types.d.ts
59
- /**
60
- * What a job carries: a mutation applies actions, a load imports synced
61
- * operations, and a reevaluation re-judges a document's stored operations
62
- * because a read-set stream elsewhere (a group document) changed. A
63
- * reevaluation job carries no actions or operations; its work is derived
64
- * from what is already stored.
65
- */
66
- type JobKind = "mutation" | "load" | "reevaluation";
67
- /**
68
- * State of a job in the queue
69
- */
70
- declare enum JobQueueState {
71
- UNKNOWN = -1,
72
- PREPROCESSING = 0,
73
- PENDING = 1,
74
- READY = 2,
75
- RUNNING = 3,
76
- RESOLVED = 4
77
- }
78
- /**
79
- * How a retry is accounted against the job's retry limit.
80
- * - `CountAgainstLimit` (default): a fault; the job eventually exhausts its
81
- * retries and fails terminally.
82
- * - `ExemptFromLimit`: not a fault, so the attempt is not charged to the job.
83
- * Used for concurrency conflicts, where the retry does new work.
84
- */
85
- export declare enum RetryAccounting {
86
- CountAgainstLimit = "count-against-limit",
87
- ExemptFromLimit = "exempt-from-limit"
88
- }
89
- /**
90
- * Interface for a job execution handle
91
- */
92
- interface IJobExecutionHandle {
93
- readonly job: Job;
94
- readonly state: JobQueueState;
95
- start(): void;
96
- complete(): void;
97
- fail(error: ErrorInfo$1): void;
98
- defer(): void;
58
+ //#region src/catch-up/types.d.ts
59
+ type WatermarkStatus = {
60
+ head: number;
61
+ settledThrough: number;
62
+ waitingOn: string[];
63
+ stalledSinceUtcMs?: number;
64
+ };
65
+ interface ISettledWatermark {
66
+ /** Every ordinal at or below this is visible or will never exist. */
67
+ readonly settledThrough: number;
68
+ /** Probes, coalesced with one in flight; resolves with settledThrough. */
69
+ refresh(signal?: AbortSignal): Promise<number>;
70
+ onAdvance(listener: (settledThrough: number) => void): Unsubscribe;
71
+ status(): WatermarkStatus;
99
72
  }
100
- /**
101
- * Represents a job to be executed by the job executor
102
- */
103
- type Job = {
104
- /** Unique identifier for the job */
105
- id: string;
106
- /** Classification of the job so executors can switch behavior */
107
- kind: JobKind;
108
- /** The document ID this job operates on */
73
+ type SweepBlockedAt = {
74
+ ordinal: number;
109
75
  documentId: string;
110
- /** The scope of the operations */
111
76
  scope: string;
112
- /** The branch of the operations */
113
77
  branch: string;
114
- /** The actions to be executed (processed sequentially) */
115
- actions: Action[];
116
- /** Pre-existing operations to import (used for load jobs) */
117
- operations: Operation[];
118
- /** Timestamp when the job was created */
119
- createdAt: string;
120
- /** The hint for the queue to use for ordering the job */
121
- queueHint: string[];
122
- /** Number of retry attempts */
123
- retryCount?: number;
124
- /** Maximum number of retries allowed */
125
- maxRetries?: number;
126
- /** Last error if job failed */
127
- lastError?: ErrorInfo$1;
128
- /** History of all errors from each attempt (ordered) */
129
- errorHistory: ErrorInfo$1[];
130
- /** Metadata that flows through the job lifecycle */
131
- meta: JobMeta;
78
+ type: string;
79
+ error: string;
132
80
  };
133
- /**
134
- * Event types for the queue system
135
- */
136
- export declare const QueueEventTypes: {
137
- readonly JOB_AVAILABLE: 10000;
81
+ type SweepResult = {
82
+ consumerId: string;
83
+ from: number;
84
+ to: number;
85
+ durationMs: number;
86
+ /** Late operations applied. */
87
+ replayed: number;
88
+ /** Later operations of their streams applied again. */
89
+ reapplied: number;
90
+ blockedAt?: SweepBlockedAt;
138
91
  };
139
- /**
140
- * Minimal projection of a Job used by IQueue.dequeueNextMatching predicates.
141
- * Exposes only the routing-relevant fields so routing logic (e.g. hash(documentId) % numWorkers)
142
- * can live outside the queue without leaking the full Job.
143
- */
144
- type JobRoutingMeta = {
145
- documentId: string;
146
- scope: string;
147
- branch: string;
92
+ interface ICatchUpConsumer {
93
+ readonly consumerId: string;
94
+ readonly appliedThrough: number;
95
+ /** Ordinals above the cursor this consumer holds in memory. */
96
+ readonly trackedAbove: number;
97
+ sweep(settledThrough: number, present: readonly number[], signal?: AbortSignal): Promise<SweepResult>;
98
+ }
99
+ type CatchUpThread = "host" | "projection";
100
+ type CatchUpConsumerStatus = {
101
+ consumerId: string;
102
+ thread: CatchUpThread;
103
+ appliedThrough: number;
104
+ trackedAbove: number;
105
+ blockedAt?: SweepBlockedAt;
106
+ lastAdvanceUtcMs: number;
148
107
  };
149
- /**
150
- * Event data for job available events
151
- */
152
- type JobAvailableEvent = {
153
- documentId: string;
154
- scope: string;
155
- branch: string;
156
- jobId: string;
108
+ type CatchUpStatus = {
109
+ watermark: WatermarkStatus;
110
+ consumers: CatchUpConsumerStatus[];
157
111
  };
112
+ type CatchUpConfig = {
113
+ intervalMs: number;
114
+ stuckWarnMs: number;
115
+ maxTrackedAboveCursor: number;
116
+ /** Present ordinals read per tick. */
117
+ sweepPageSize: number;
118
+ };
119
+ export declare const defaultCatchUpConfig: CatchUpConfig;
120
+ /** The catch-up surface a reactor module exposes. */
121
+ interface ICatchUp {
122
+ status(): CatchUpStatus;
123
+ sweepNow(): Promise<SweepResult[]>;
124
+ }
158
125
  //#endregion
159
126
  //#region src/shared/types.d.ts
160
127
  /**
@@ -168,6 +135,8 @@ type ErrorInfo$1 = {
168
135
  name: string;
169
136
  message: string;
170
137
  stack: string;
138
+ /** The document the error names, when it carries one. */
139
+ documentId?: string;
171
140
  };
172
141
  /**
173
142
  * Describes the status of a shutdown operation.
@@ -352,6 +321,117 @@ type ConsistencyToken = {
352
321
  coordinates: ConsistencyCoordinate[];
353
322
  };
354
323
  //#endregion
324
+ //#region src/queue/types.d.ts
325
+ /**
326
+ * What a job carries: a mutation applies actions, a load imports synced
327
+ * operations, and a reevaluation re-judges a document's stored operations
328
+ * because a read-set stream elsewhere (a group document) changed. A
329
+ * reevaluation job carries no actions or operations; its work is derived
330
+ * from what is already stored. A purge job erases a deleted document and
331
+ * writes its PURGE_DOCUMENT marker; only DocumentPurgeService enqueues one.
332
+ */
333
+ type JobKind = "mutation" | "load" | "reevaluation" | "purge";
334
+ /** What a purge job carries beyond its document id. */
335
+ type PurgeJobOptions = {
336
+ /** The erasure request that ordered the purge; the marker's requestId. */
337
+ requestId: string;
338
+ /** Lifts the maxPurgeOperations cap for this document. */
339
+ allowLarge: boolean;
340
+ };
341
+ /**
342
+ * State of a job in the queue
343
+ */
344
+ declare enum JobQueueState {
345
+ UNKNOWN = -1,
346
+ PREPROCESSING = 0,
347
+ PENDING = 1,
348
+ READY = 2,
349
+ RUNNING = 3,
350
+ RESOLVED = 4
351
+ }
352
+ /**
353
+ * How a retry is accounted against the job's retry limit.
354
+ * - `CountAgainstLimit` (default): a fault; the job eventually exhausts its
355
+ * retries and fails terminally.
356
+ * - `ExemptFromLimit`: not a fault, so the attempt is not charged to the job.
357
+ * Used for concurrency conflicts, where the retry does new work.
358
+ */
359
+ export declare enum RetryAccounting {
360
+ CountAgainstLimit = "count-against-limit",
361
+ ExemptFromLimit = "exempt-from-limit"
362
+ }
363
+ /**
364
+ * Interface for a job execution handle
365
+ */
366
+ interface IJobExecutionHandle {
367
+ readonly job: Job;
368
+ readonly state: JobQueueState;
369
+ start(): void;
370
+ complete(): void;
371
+ fail(error: ErrorInfo$1): void;
372
+ defer(): void;
373
+ }
374
+ /**
375
+ * Represents a job to be executed by the job executor
376
+ */
377
+ type Job = {
378
+ /** Unique identifier for the job */
379
+ id: string;
380
+ /** Classification of the job so executors can switch behavior */
381
+ kind: JobKind;
382
+ /** The document ID this job operates on */
383
+ documentId: string;
384
+ /** The scope of the operations */
385
+ scope: string;
386
+ /** The branch of the operations */
387
+ branch: string;
388
+ /** The actions to be executed (processed sequentially) */
389
+ actions: Action[];
390
+ /** Pre-existing operations to import (used for load jobs) */
391
+ operations: Operation[];
392
+ /** Timestamp when the job was created */
393
+ createdAt: string;
394
+ /** The hint for the queue to use for ordering the job */
395
+ queueHint: string[];
396
+ /** Number of retry attempts */
397
+ retryCount?: number;
398
+ /** Maximum number of retries allowed */
399
+ maxRetries?: number;
400
+ /** Last error if job failed */
401
+ lastError?: ErrorInfo$1;
402
+ /** History of all errors from each attempt (ordered) */
403
+ errorHistory: ErrorInfo$1[];
404
+ /** Metadata that flows through the job lifecycle */
405
+ meta: JobMeta;
406
+ /** Set on a purge job only. */
407
+ purge?: PurgeJobOptions;
408
+ };
409
+ /**
410
+ * Event types for the queue system
411
+ */
412
+ export declare const QueueEventTypes: {
413
+ readonly JOB_AVAILABLE: 10000;
414
+ };
415
+ /**
416
+ * Minimal projection of a Job used by IQueue.dequeueNextMatching predicates.
417
+ * Exposes only the routing-relevant fields so routing logic (e.g. hash(documentId) % numWorkers)
418
+ * can live outside the queue without leaking the full Job.
419
+ */
420
+ type JobRoutingMeta = {
421
+ documentId: string;
422
+ scope: string;
423
+ branch: string;
424
+ };
425
+ /**
426
+ * Event data for job available events
427
+ */
428
+ type JobAvailableEvent = {
429
+ documentId: string;
430
+ scope: string;
431
+ branch: string;
432
+ jobId: string;
433
+ };
434
+ //#endregion
355
435
  //#region src/read-models/interfaces.d.ts
356
436
  /**
357
437
  * Generic interface for any read model that can index operations.
@@ -512,6 +592,14 @@ type SyncOperationErrorType = "SIGNATURE_INVALID" | "HASH_MISMATCH" | "LIBRARY_E
512
592
  "PEER_PROTOCOL_UNSUPPORTED" |
513
593
  /** An arriving operation carried a timestamp that is not an ISO-8601 instant. */
514
594
  "INVALID_TIMESTAMP" |
595
+ /** The document was purged here; its operations are dropped, not kept. */
596
+ "DOCUMENT_PURGED" |
597
+ /** A purge's precondition failed; the document itself is unaffected. */
598
+ "PURGE_PRECONDITION" |
599
+ /** A peer sent a reserved action type as a regular write. */
600
+ "RESERVED_ACTION" |
601
+ /** A peer's purge marker was refused; the document keeps syncing. */
602
+ "MARKER_REFUSED" |
515
603
  /** No classification applies, including rows written before the field. */
516
604
  "UNCLASSIFIED";
517
605
  type ChannelHealth = {
@@ -560,6 +648,12 @@ type LocalPeer = {
560
648
  protocolVersionsOf?: (documentId: string, branch: string) => Promise<{
561
649
  [protocol: string]: number;
562
650
  } | undefined>;
651
+ /** Drops a purged document from the host cache behind protocolVersionsOf. */
652
+ forgetDocument?: (documentId: string) => void;
653
+ };
654
+ /** The tombstone index, as the sync manager reads it at startup. */
655
+ type PurgeLookup = {
656
+ listPurged(): Promise<string[]>;
563
657
  };
564
658
  /** What the peer announced, and when; a null manifest is a silent peer. */
565
659
  type RemotePeer = {
@@ -590,6 +684,7 @@ export declare const SyncEventTypes: {
590
684
  readonly CONNECTION_STATE_CHANGED: 20005;
591
685
  readonly SYNC_HELD: 20006;
592
686
  readonly SYNC_RELEASED: 20007;
687
+ readonly PURGE_REFUSED: 20008;
593
688
  };
594
689
  /** A document held back from one remote because its peer cannot run it. */
595
690
  type SyncHold = {
@@ -605,6 +700,13 @@ type SyncHeldEvent = {
605
700
  branch: string;
606
701
  reason: HoldReason;
607
702
  };
703
+ /** A remote reported it could not apply a purged document's marker. */
704
+ type SyncPurgeRefusedEvent = {
705
+ remoteName: string;
706
+ documentId: string;
707
+ branch: string;
708
+ errorMessage: string;
709
+ };
608
710
  type SyncReleasedEvent = {
609
711
  remoteName: string;
610
712
  documentId: string;
@@ -1018,6 +1120,7 @@ interface IDocumentView extends IReadModel {
1018
1120
  * @param view - Optional filter containing branch and scopes information
1019
1121
  * @param consistencyToken - Optional token for read-after-write consistency
1020
1122
  * @param signal - Optional abort signal to cancel the request
1123
+ * @throws {DocumentNotFoundError} If the view does not hold the document
1021
1124
  */
1022
1125
  get<TDocument extends PHDocument>(documentId: string, view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
1023
1126
  /**
@@ -1037,6 +1140,7 @@ interface IDocumentView extends IReadModel {
1037
1140
  * @param view - Optional filter containing branch and scopes information
1038
1141
  * @param consistencyToken - Optional token for read-after-write consistency
1039
1142
  * @param signal - Optional abort signal to cancel the request
1143
+ * @throws {DocumentNotFoundError} If neither an id nor a slug matches
1040
1144
  * @throws {Error} If identifier matches both an ID and slug referring to different documents
1041
1145
  */
1042
1146
  getByIdOrSlug<TDocument extends PHDocument>(identifier: string, view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
@@ -1080,7 +1184,8 @@ interface IDocumentView extends IReadModel {
1080
1184
  * @param consistencyToken - Optional token for read-after-write consistency
1081
1185
  * @param signal - Optional abort signal to cancel the request
1082
1186
  * @returns The document ID
1083
- * @throws {Error} If document not found or identifier matches both an ID and slug referring to different documents
1187
+ * @throws {DocumentNotFoundError} If neither an id nor a slug matches
1188
+ * @throws {Error} If identifier matches both an ID and slug referring to different documents
1084
1189
  */
1085
1190
  resolveIdOrSlug(identifier: string, view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string>;
1086
1191
  }
@@ -1238,10 +1343,41 @@ interface ISyncHoldStorage {
1238
1343
  remoteName?: string;
1239
1344
  documentId?: string;
1240
1345
  }): Promise<SyncHoldRecord[]>;
1346
+ /** Throws DocumentPurgedError for a purged id, except for its marker's hold. */
1241
1347
  upsert(hold: SyncHoldRecord): Promise<void>;
1242
1348
  remove(remoteName: string, documentId: string, branch: string): Promise<void>;
1243
1349
  removeRemote(remoteName: string): Promise<void>;
1244
1350
  }
1351
+ /** A purge marker received from a remote, kept until its outcome. */
1352
+ type ReceivedMarkerRecord = {
1353
+ remoteName: string;
1354
+ /** The marker operation's id. */
1355
+ markerId: string;
1356
+ documentId: string;
1357
+ branch: string;
1358
+ operation: OperationWithContext$1;
1359
+ receivedAtUtcMs: number;
1360
+ };
1361
+ /** Received markers that survive a restart, so the inbox ack stays below them. */
1362
+ interface ISyncReceivedMarkerStorage {
1363
+ list(remoteName: string): Promise<ReceivedMarkerRecord[]>;
1364
+ upsert(record: ReceivedMarkerRecord): Promise<void>;
1365
+ remove(remoteName: string, markerId: string): Promise<void>;
1366
+ removeRemote(remoteName: string): Promise<void>;
1367
+ }
1368
+ /** A remote's refusal of a purge marker; no message, which may name a signer. */
1369
+ type PurgeRefusalRecord = {
1370
+ remoteName: string;
1371
+ documentId: string;
1372
+ branch: string;
1373
+ refusedAtUtcMs: number;
1374
+ };
1375
+ /** Marker refusals, kept after the remote goes so the erasure can report them. */
1376
+ interface ISyncPurgeRefusalStorage {
1377
+ list(documentId: string): Promise<PurgeRefusalRecord[]>;
1378
+ /** One statement; the first time per remote, document and branch is kept. */
1379
+ record(refusals: readonly PurgeRefusalRecord[]): Promise<void>;
1380
+ }
1245
1381
  /**
1246
1382
  * Persistent storage for sync remote configurations. Each remote represents
1247
1383
  * a connection to an external system that operations can be synced with.
@@ -1349,7 +1485,8 @@ interface ISyncDeadLetterStorage {
1349
1485
  */
1350
1486
  list(remoteName: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DeadLetterRecord>>;
1351
1487
  /**
1352
- * Adds a dead letter. Duplicate ids are silently ignored.
1488
+ * Adds a dead letter. Duplicate ids are silently ignored. Throws
1489
+ * DocumentPurgedError, persisting nothing, when the document is purged.
1353
1490
  *
1354
1491
  * @param deadLetter - The dead letter record to persist
1355
1492
  * @param signal - Optional abort signal to cancel the request
@@ -1495,12 +1632,14 @@ interface IOperationIndex {
1495
1632
  * reference other groups.
1496
1633
  */
1497
1634
  getGroupReferencers(groupId: string, signal?: AbortSignal): Promise<string[]>;
1635
+ /** Collections with a member with a row in (after, through], within `among`. */
1636
+ getCollectionsInRange(after: number, through: number, among?: readonly string[], signal?: AbortSignal): Promise<string[]>;
1498
1637
  /** Ordinals in (after, through], ascending, at most `limit`. */
1499
1638
  getOrdinalsInRange(after: number, through: number, limit: number, signal?: AbortSignal): Promise<number[]>;
1500
1639
  /** Rows for these ordinals, ascending; a missing row is left out. */
1501
1640
  getByOrdinals(ordinals: readonly number[], signal?: AbortSignal): Promise<OperationWithContext$1[]>;
1502
- /** A stream's rows above an ordinal, ascending. */
1503
- getStreamAfter(stream: DocumentStreamKey, after: number, signal?: AbortSignal): Promise<OperationWithContext$1[]>;
1641
+ /** A stream's rows above an ordinal, ascending, at most `limit` if given. */
1642
+ getStreamAfter(stream: DocumentStreamKey, after: number, signal?: AbortSignal, limit?: number): Promise<OperationWithContext$1[]>;
1504
1643
  /** The latest ordinal of each of `opIds` indexed in one stream. */
1505
1644
  getOrdinalsByOpIds(documentId: string, scope: string, branch: string, opIds: string[], signal?: AbortSignal): Promise<Map<string, number>>;
1506
1645
  }
@@ -1531,125 +1670,6 @@ export declare class DriveCollectionId {
1531
1670
  equals(other: DriveCollectionId): boolean;
1532
1671
  }
1533
1672
  //#endregion
1534
- //#region src/cache/write/interfaces.d.ts
1535
- /**
1536
- * IWriteCache is a write-side projection that optimizes document state retrieval
1537
- * for the job executor. This is separate from IDocumentView (read-side projection) which optimizes
1538
- * queries and searches.
1539
- */
1540
- interface IWriteCache {
1541
- /**
1542
- * Retrieves or builds the document at the specified revision.
1543
- * If targetRevision is not provided, retrieves the latest state.
1544
- *
1545
- * @param documentId - The document identifier
1546
- * @param scope - Operation scope
1547
- * @param branch - Branch name
1548
- * @param targetRevision - Index of the last operation to apply, defaulting
1549
- * to latest. An operation index, never `header.revision[scope]`.
1550
- * @param signal - Optional abort signal to cancel the operation
1551
- * @returns The complete document at the specified revision
1552
- *
1553
- * @example
1554
- * ```typescript
1555
- * // Get latest document state
1556
- * const doc = await cache.getState(docId, 'global', 'main');
1557
- *
1558
- * // Get document at specific revision
1559
- * const doc = await cache.getState(docId, 'global', 'main', 42);
1560
- * ```
1561
- */
1562
- getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
1563
- /**
1564
- * Stores a document snapshot in the cache at the specified revision.
1565
- * Implementations may truncate the stored document (e.g. strip operation
1566
- * history beyond the last entry per scope, clear clipboard) to bound memory
1567
- * and copy cost. Callers must not assume that the document returned by a
1568
- * subsequent getState() call will have a complete operations array; the only
1569
- * guaranteed invariant is that operations[scope].at(-1) holds the latest
1570
- * operation index for each scope present in the cached document.
1571
- *
1572
- * @param documentId - The document identifier
1573
- * @param scope - Operation scope
1574
- * @param branch - Branch name
1575
- * @param revision - Index of the last operation this document reflects, so
1576
- * `header.revision[scope]` is one greater. -1 for an empty scope.
1577
- * @param document - The document to cache
1578
- * @param position - Whether `revision` is the stream's head. Nothing checks
1579
- * it: claiming `Head` for an earlier revision makes a getState() with no
1580
- * target return stale state.
1581
- *
1582
- * @example
1583
- * ```typescript
1584
- * cache.putState(docId, 'global', 'main', 42, document, SnapshotPosition.Head);
1585
- * ```
1586
- */
1587
- putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, position: SnapshotPosition): void;
1588
- /**
1589
- * Records a run of revisions written together, the last of which is the
1590
- * stream's head. Only the head is cached as state: an earlier revision in
1591
- * the run is not the head, and caching it as one would answer a later head
1592
- * read with state from the middle of the run. The earlier ones are still
1593
- * offered to whatever the implementation persists at intervals, because a
1594
- * run that writes past a boundary passed through it just the same.
1595
- *
1596
- * @param documentId - The document identifier
1597
- * @param scope - Operation scope
1598
- * @param branch - Branch name
1599
- * @param run - Each revision the run produced, in order, with the document
1600
- * as it stood at that revision. The last entry is the head.
1601
- *
1602
- * @example
1603
- * ```typescript
1604
- * cache.putRun(docId, 'global', 'main', [
1605
- * { revision: 9, document: at9 },
1606
- * { revision: 10, document: at10 },
1607
- * ]);
1608
- * ```
1609
- */
1610
- putRun(documentId: string, scope: string, branch: string, run: readonly {
1611
- revision: number;
1612
- document: PHDocument;
1613
- }[]): void;
1614
- /**
1615
- * Invalidates (removes) cached entries for a document stream.
1616
- *
1617
- * - If only documentId is provided: invalidates all scopes and branches for that document
1618
- * - If documentId + scope provided: invalidates all branches for that document and scope
1619
- * - If all parameters provided: invalidates the specific stream
1620
- *
1621
- * @param documentId - The document identifier
1622
- * @param scope - Optional scope to narrow invalidation
1623
- * @param branch - Optional branch to narrow invalidation
1624
- * @returns Number of ring buffers evicted
1625
- *
1626
- * @example
1627
- * ```typescript
1628
- * // Invalidate all streams for a document
1629
- * cache.invalidate(docId);
1630
- *
1631
- * // Invalidate all branches for a specific scope
1632
- * cache.invalidate(docId, 'global');
1633
- *
1634
- * // Invalidate specific stream
1635
- * cache.invalidate(docId, 'global', 'main');
1636
- * ```
1637
- */
1638
- invalidate(documentId: string, scope?: string, branch?: string): number;
1639
- /**
1640
- * Clears all cached data from the in-memory cache.
1641
- */
1642
- clear(): void;
1643
- /**
1644
- * Performs startup initialization.
1645
- */
1646
- startup(): Promise<void>;
1647
- /**
1648
- * Performs graceful shutdown.
1649
- */
1650
- shutdown(): Promise<void>;
1651
- }
1652
- //#endregion
1653
1673
  //#region src/cache/collection-membership-cache.d.ts
1654
1674
  interface ICollectionMembershipCache {
1655
1675
  getCollectionsForDocuments(documentIds: string[]): Promise<Record<string, string[]>>;
@@ -1674,7 +1694,10 @@ type CachedDocumentMeta = {
1674
1694
  * The document type (from header), cached for convenience.
1675
1695
  */
1676
1696
  documentType: string;
1677
- /** From the CREATE_DOCUMENT input, which fixes them for the document's life. */
1697
+ /**
1698
+ * From the CREATE_DOCUMENT input, which fixes them for the document's life;
1699
+ * derived, not stored, once the document is purged.
1700
+ */
1678
1701
  protocolVersions: {
1679
1702
  [protocol: string]: number;
1680
1703
  } | undefined;
@@ -1710,7 +1733,10 @@ interface IDocumentMetaCache {
1710
1733
  * @param signal - Optional abort signal to cancel the operation
1711
1734
  * @returns The cached or rebuilt document metadata
1712
1735
  * @throws {Error} "Operation aborted" if signal is aborted
1713
- * @throws {Error} If document not found (no CREATE_DOCUMENT operation)
1736
+ * @throws {DocumentNotFoundError} If the document has no operations
1737
+ *
1738
+ * A purged document, whose only operation is its marker, yields deleted
1739
+ * metadata built from the marker's input.
1714
1740
  */
1715
1741
  getDocumentMeta(documentId: string, branch: string, signal?: AbortSignal): Promise<CachedDocumentMeta>;
1716
1742
  /**
@@ -1872,6 +1898,22 @@ interface SyncHoldTable {
1872
1898
  version: number;
1873
1899
  held_at_utc_ms: ColumnType<string | number, number, number>;
1874
1900
  }
1901
+ /** A received purge marker awaiting its outcome (migration 025). */
1902
+ interface SyncReceivedMarkerTable {
1903
+ remote_name: string;
1904
+ marker_id: string;
1905
+ document_id: string;
1906
+ branch: string;
1907
+ operation: ColumnType<unknown, string, string>;
1908
+ received_at_utc_ms: ColumnType<string | number, number, number>;
1909
+ }
1910
+ /** A remote's refusal of a purge marker (migration 026). */
1911
+ interface SyncPurgeRefusalTable {
1912
+ remote_name: string;
1913
+ document_id: string;
1914
+ branch: string;
1915
+ refused_at_utc_ms: ColumnType<string | number, number, number>;
1916
+ }
1875
1917
  /**
1876
1918
  * One (document, group) reference ever discovered from an auth operation's
1877
1919
  * input. Rows are never updated or deleted (see migration 017).
@@ -1880,6 +1922,18 @@ interface GroupReferenceTable {
1880
1922
  documentId: string;
1881
1923
  groupId: string;
1882
1924
  }
1925
+ /** Rows a purge removed, per table. */
1926
+ type PurgeRemovedRows = {
1927
+ [table: string]: number;
1928
+ };
1929
+ /** The tombstone of a purged document (migration 024). */
1930
+ interface DocumentPurgeTable {
1931
+ documentId: string;
1932
+ ordinal: ColumnType<string | number, number, number>;
1933
+ removedRows: ColumnType<PurgeRemovedRows, string, string>;
1934
+ purgedAtUtc: ColumnType<Date, Date | string, Date | string>;
1935
+ requestId: string;
1936
+ }
1883
1937
  interface Database$1 {
1884
1938
  Operation: OperationTable;
1885
1939
  Keyframe: KeyframeTable;
@@ -1890,6 +1944,9 @@ interface Database$1 {
1890
1944
  sync_cursors: SyncCursorTable;
1891
1945
  sync_dead_letters: SyncDeadLetterTable;
1892
1946
  sync_holds: SyncHoldTable;
1947
+ sync_received_markers: SyncReceivedMarkerTable;
1948
+ sync_purge_refusals: SyncPurgeRefusalTable;
1949
+ document_purges: DocumentPurgeTable;
1893
1950
  }
1894
1951
  interface DocumentTable {
1895
1952
  id: string;
@@ -1915,6 +1972,7 @@ interface DocumentIndexerDatabase {
1915
1972
  DocumentRelationship: DocumentRelationshipTable;
1916
1973
  IndexerState: IndexerStateTable;
1917
1974
  }
1975
+ type DocumentPurgeRow = Selectable<DocumentPurgeTable>;
1918
1976
  //#endregion
1919
1977
  //#region src/core/model-sources.d.ts
1920
1978
  /** An importable file holding one or more document-model exports. */
@@ -2100,7 +2158,126 @@ declare class RingBuffer<T> {
2100
2158
  /**
2101
2159
  * Gets the current number of items in the buffer.
2102
2160
  */
2103
- get length(): number;
2161
+ get length(): number;
2162
+ }
2163
+ //#endregion
2164
+ //#region src/cache/write/interfaces.d.ts
2165
+ /**
2166
+ * IWriteCache is a write-side projection that optimizes document state retrieval
2167
+ * for the job executor. This is separate from IDocumentView (read-side projection) which optimizes
2168
+ * queries and searches.
2169
+ */
2170
+ interface IWriteCache {
2171
+ /**
2172
+ * Retrieves or builds the document at the specified revision.
2173
+ * If targetRevision is not provided, retrieves the latest state.
2174
+ *
2175
+ * @param documentId - The document identifier
2176
+ * @param scope - Operation scope
2177
+ * @param branch - Branch name
2178
+ * @param targetRevision - Index of the last operation to apply, defaulting
2179
+ * to latest. An operation index, never `header.revision[scope]`.
2180
+ * @param signal - Optional abort signal to cancel the operation
2181
+ * @returns The complete document at the specified revision
2182
+ *
2183
+ * @example
2184
+ * ```typescript
2185
+ * // Get latest document state
2186
+ * const doc = await cache.getState(docId, 'global', 'main');
2187
+ *
2188
+ * // Get document at specific revision
2189
+ * const doc = await cache.getState(docId, 'global', 'main', 42);
2190
+ * ```
2191
+ */
2192
+ getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
2193
+ /**
2194
+ * Stores a document snapshot in the cache at the specified revision.
2195
+ * Implementations may truncate the stored document (e.g. strip operation
2196
+ * history beyond the last entry per scope, clear clipboard) to bound memory
2197
+ * and copy cost. Callers must not assume that the document returned by a
2198
+ * subsequent getState() call will have a complete operations array; the only
2199
+ * guaranteed invariant is that operations[scope].at(-1) holds the latest
2200
+ * operation index for each scope present in the cached document.
2201
+ *
2202
+ * @param documentId - The document identifier
2203
+ * @param scope - Operation scope
2204
+ * @param branch - Branch name
2205
+ * @param revision - Index of the last operation this document reflects, so
2206
+ * `header.revision[scope]` is one greater. -1 for an empty scope.
2207
+ * @param document - The document to cache
2208
+ * @param position - Whether `revision` is the stream's head. Nothing checks
2209
+ * it: claiming `Head` for an earlier revision makes a getState() with no
2210
+ * target return stale state.
2211
+ *
2212
+ * @example
2213
+ * ```typescript
2214
+ * cache.putState(docId, 'global', 'main', 42, document, SnapshotPosition.Head);
2215
+ * ```
2216
+ */
2217
+ putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, position: SnapshotPosition): void;
2218
+ /**
2219
+ * Records a run of revisions written together, the last of which is the
2220
+ * stream's head. Only the head is cached as state: an earlier revision in
2221
+ * the run is not the head, and caching it as one would answer a later head
2222
+ * read with state from the middle of the run. The earlier ones are still
2223
+ * offered to whatever the implementation persists at intervals, because a
2224
+ * run that writes past a boundary passed through it just the same.
2225
+ *
2226
+ * @param documentId - The document identifier
2227
+ * @param scope - Operation scope
2228
+ * @param branch - Branch name
2229
+ * @param run - Each revision the run produced, in order, with the document
2230
+ * as it stood at that revision. The last entry is the head.
2231
+ *
2232
+ * @example
2233
+ * ```typescript
2234
+ * cache.putRun(docId, 'global', 'main', [
2235
+ * { revision: 9, document: at9 },
2236
+ * { revision: 10, document: at10 },
2237
+ * ]);
2238
+ * ```
2239
+ */
2240
+ putRun(documentId: string, scope: string, branch: string, run: readonly {
2241
+ revision: number;
2242
+ document: PHDocument;
2243
+ }[]): void;
2244
+ /**
2245
+ * Invalidates (removes) cached entries for a document stream.
2246
+ *
2247
+ * - If only documentId is provided: invalidates all scopes and branches for that document
2248
+ * - If documentId + scope provided: invalidates all branches for that document and scope
2249
+ * - If all parameters provided: invalidates the specific stream
2250
+ *
2251
+ * @param documentId - The document identifier
2252
+ * @param scope - Optional scope to narrow invalidation
2253
+ * @param branch - Optional branch to narrow invalidation
2254
+ * @returns Number of ring buffers evicted
2255
+ *
2256
+ * @example
2257
+ * ```typescript
2258
+ * // Invalidate all streams for a document
2259
+ * cache.invalidate(docId);
2260
+ *
2261
+ * // Invalidate all branches for a specific scope
2262
+ * cache.invalidate(docId, 'global');
2263
+ *
2264
+ * // Invalidate specific stream
2265
+ * cache.invalidate(docId, 'global', 'main');
2266
+ * ```
2267
+ */
2268
+ invalidate(documentId: string, scope?: string, branch?: string): number;
2269
+ /**
2270
+ * Clears all cached data from the in-memory cache.
2271
+ */
2272
+ clear(): void;
2273
+ /**
2274
+ * Performs startup initialization.
2275
+ */
2276
+ startup(): Promise<void>;
2277
+ /**
2278
+ * Performs graceful shutdown.
2279
+ */
2280
+ shutdown(): Promise<void>;
2104
2281
  }
2105
2282
  //#endregion
2106
2283
  //#region src/cache/kysely-write-cache.d.ts
@@ -2108,42 +2285,6 @@ type DocumentStream = {
2108
2285
  key: string;
2109
2286
  ringBuffer: RingBuffer<CachedSnapshot>;
2110
2287
  };
2111
- /**
2112
- * In-memory write cache with keyframe persistence for PHDocuments.
2113
- *
2114
- * Caches document snapshots in ring buffers with LRU eviction. On cache miss,
2115
- * rebuilds documents from nearest keyframe or full operation history.
2116
- *
2117
- * **Performance Characteristics:**
2118
- * - Cache hit: O(1) lookup in ring buffer
2119
- * - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe
2120
- * - Warm miss: O(m) where m is operations since cached revision
2121
- * - Eviction: O(1) for LRU tracking and removal
2122
- *
2123
- * **Thread Safety:**
2124
- * Not thread-safe. Designed for single-threaded job executor environment.
2125
- * External synchronization required for concurrent access across multiple executors.
2126
- *
2127
- * **Example:**
2128
- * ```typescript
2129
- * const cache = new KyselyWriteCache(
2130
- * keyframeStore,
2131
- * operationStore,
2132
- * registry,
2133
- * { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }
2134
- * );
2135
- *
2136
- * await cache.startup();
2137
- *
2138
- * // Retrieve or rebuild document
2139
- * const doc = await cache.getState(docId, docType, scope, branch, revision);
2140
- *
2141
- * // Cache result after job execution
2142
- * cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);
2143
- *
2144
- * await cache.shutdown();
2145
- * ```
2146
- */
2147
2288
  export declare class KyselyWriteCache implements IWriteCache {
2148
2289
  private streams;
2149
2290
  private lruTracker;
@@ -2151,6 +2292,7 @@ export declare class KyselyWriteCache implements IWriteCache {
2151
2292
  private operationStore;
2152
2293
  private registry;
2153
2294
  private config;
2295
+ private reads;
2154
2296
  constructor(keyframeStore: IKeyframeStore, operationStore: IOperationStore, registry: IDocumentModelRegistry, config: WriteCacheConfig);
2155
2297
  withScopedStores(operationStore: IOperationStore, keyframeStore: IKeyframeStore): KyselyWriteCache;
2156
2298
  /**
@@ -2180,11 +2322,13 @@ export declare class KyselyWriteCache implements IWriteCache {
2180
2322
  * @returns The document at the target revision
2181
2323
  * @throws {Error} "Operation aborted" if signal is aborted
2182
2324
  * @throws {ModuleNotFoundError} If document type not registered in registry
2325
+ * @throws {DocumentPurgedError} If the stream's only row is a purge marker
2183
2326
  * @throws {Error} "Failed to rebuild document" if operation store fails
2184
2327
  * @throws {Error} If reducer throws during operation application
2185
2328
  * @throws {Error} If document serialization fails
2186
2329
  */
2187
2330
  getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
2331
+ private readState;
2188
2332
  /**
2189
2333
  * Stores a document snapshot in the cache at a specific revision.
2190
2334
  *
@@ -2215,6 +2359,7 @@ export declare class KyselyWriteCache implements IWriteCache {
2215
2359
  revision: number;
2216
2360
  document: PHDocument;
2217
2361
  }[]): void;
2362
+ private storeUnlessEvicted;
2218
2363
  private store;
2219
2364
  /** Persists the snapshot if this revision is one the interval falls on. */
2220
2365
  private persistKeyframe;
@@ -2306,9 +2451,11 @@ export declare class KyselyWriteCache implements IWriteCache {
2306
2451
  export declare class KyselyOperationStore implements IOperationStore {
2307
2452
  private db;
2308
2453
  private trx?;
2454
+ private liveIds?;
2309
2455
  constructor(db: Kysely<Database$1>);
2310
2456
  private get queryExecutor();
2311
- withTransaction(trx: Transaction<Database$1>): KyselyOperationStore;
2457
+ /** `liveIds`: ids the transaction read untombstoned under its shared lock. */
2458
+ withTransaction(trx: Transaction<Database$1>, liveIds?: ReadonlySet<string>): KyselyOperationStore;
2312
2459
  apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal, condition?: AppendCondition): Promise<Operation[]>;
2313
2460
  private resolveUniqueConstraint;
2314
2461
  private executeApply;
@@ -2327,6 +2474,10 @@ export declare class KyselyOperationStore implements IOperationStore {
2327
2474
  */
2328
2475
  private insertGuarded;
2329
2476
  private findIdempotentReplay;
2477
+ /** A purged stream refuses appends; a marker gets the stored one back. */
2478
+ private refusePurgedAppend;
2479
+ private isMarker;
2480
+ private actionType;
2330
2481
  /** True when the staged write creates a document rather than appending to one. */
2331
2482
  private isCreate;
2332
2483
  /**
@@ -2375,13 +2526,71 @@ export declare class KyselyKeyframeStore implements IKeyframeStore {
2375
2526
  deleteKeyframes(documentId: string, scope?: string, branch?: string, signal?: AbortSignal): Promise<number>;
2376
2527
  }
2377
2528
  //#endregion
2529
+ //#region src/storage/kysely/document-purger.d.ts
2530
+ /** An `Operation` row whose DELETE_DOCUMENT applied: not errored, not denied. */
2531
+ export declare const appliedDelete: import("kysely").RawBuilder<boolean>;
2532
+ /** Rows removed per statement from the tables a document can fill. */
2533
+ export declare const DEFAULT_PURGE_DELETE_BATCH = 5000;
2534
+ type PurgeStream = {
2535
+ scope: string;
2536
+ branch: string;
2537
+ };
2538
+ /** A document of a drive's collection, and whether the drive's purge needs it gone. */
2539
+ type CollectionMember = {
2540
+ documentId: string;
2541
+ openElsewhere: boolean;
2542
+ /** Not open elsewhere, and still open here or deleted; a live former member lives on. */
2543
+ required: boolean;
2544
+ };
2545
+ /** A purge transaction's statements; bound to the job's transaction. */
2546
+ export declare class KyselyDocumentPurger {
2547
+ private readonly batchSize;
2548
+ private readonly db;
2549
+ constructor(db: Kysely<Database$1> | Transaction<Database$1>, batchSize?: number);
2550
+ /** Every stream the document holds operations in. */
2551
+ streams(documentId: string): Promise<PurgeStream[]>;
2552
+ operationCount(documentId: string): Promise<number>;
2553
+ /** Untombstoned documents group_references records as naming the group. */
2554
+ groupReferencers(groupId: string): Promise<string[]>;
2555
+ /** Survivors whose accepted auth history names the group; refusals do not. */
2556
+ groupReferencersInHistory(groupId: string): Promise<string[]>;
2557
+ /** The document's auth-scope operations, per branch, in index order. */
2558
+ authOperations(documentId: string): Promise<Map<string, Operation[]>>;
2559
+ /** Every document ever in the collection, but its owner and its own row. */
2560
+ collectionMembers(collectionId: string, ownerId: string, branch: string): Promise<CollectionMember[]>;
2561
+ remoteCollection(remoteName: string): Promise<string | undefined>;
2562
+ /** Deletes every row about the document; the counts are per table. */
2563
+ deleteRows(documentId: string): Promise<PurgeRemovedRows>;
2564
+ writeTombstone(tombstone: {
2565
+ documentId: string;
2566
+ ordinal: number;
2567
+ removedRows: PurgeRemovedRows;
2568
+ purgedAtUtc: Date | string;
2569
+ requestId: string;
2570
+ }): Promise<void>;
2571
+ /** Reopens every membership at the marker ordinal, plus `collectionIds`. */
2572
+ reopenMemberships(documentId: string, ordinal: number, collectionIds?: Iterable<string>): Promise<string[]>;
2573
+ private deleteBatched;
2574
+ private deleteWhere;
2575
+ }
2576
+ //#endregion
2378
2577
  //#region src/executor/execution-scope.d.ts
2578
+ /** Per-document purge locks, held until the job's transaction ends. */
2579
+ interface DocumentLocks {
2580
+ shared(ids: Iterable<string>): Promise<void>;
2581
+ exclusive(id: string): Promise<void>;
2582
+ /** The tombstoned ids among `ids`, read in the job's transaction. */
2583
+ purged(ids: Iterable<string>): Promise<Set<string>>;
2584
+ }
2379
2585
  interface ExecutionStores {
2380
2586
  operationStore: IOperationStore;
2381
2587
  operationIndex: IOperationIndex;
2382
2588
  writeCache: IWriteCache;
2383
2589
  documentMetaCache: IDocumentMetaCache;
2384
2590
  collectionMembershipCache: ICollectionMembershipCache;
2591
+ documentLocks: DocumentLocks;
2592
+ /** Absent without a transaction, which a purge cannot run outside of. */
2593
+ purger?: KyselyDocumentPurger;
2385
2594
  }
2386
2595
  interface IExecutionScope {
2387
2596
  run<T>(fn: (stores: ExecutionStores) => Promise<T>, signal?: AbortSignal): Promise<T>;
@@ -2443,6 +2652,8 @@ type ReactorFeatureFlags = {
2443
2652
  */
2444
2653
  authConditions: boolean;
2445
2654
  };
2655
+ /** 200k operations purge in 1.6 s on local Postgres; jobs time out at 30 s. */
2656
+ export declare const DEFAULT_MAX_PURGE_OPERATIONS = 200000;
2446
2657
  /**
2447
2658
  * Configuration options for the job executor
2448
2659
  */
@@ -2488,6 +2699,8 @@ type JobExecutorConfig = {
2488
2699
  signatureVerification?: SignatureVerificationMode;
2489
2700
  /** Versions run per registered protocol; defaults to the registry's. */
2490
2701
  protocolSupport?: ProtocolSupport;
2702
+ /** Index rows a purge may remove without allowLarge. */
2703
+ maxPurgeOperations?: number;
2491
2704
  };
2492
2705
  /** Cloneable, so a pooled worker refuses exactly what the host refuses. */
2493
2706
  type ProtocolSupport = {
@@ -2582,6 +2795,7 @@ type ErrorInfo = {
2582
2795
  message: string;
2583
2796
  stack?: string;
2584
2797
  cause?: ErrorInfo;
2798
+ documentId?: string;
2585
2799
  };
2586
2800
  /**
2587
2801
  * Reference to a module that the worker should `import()` at runtime,
@@ -2773,13 +2987,18 @@ type LoadModelMessage = {
2773
2987
  correlationId: string;
2774
2988
  model: ModelManifestEntry;
2775
2989
  };
2990
+ /** Evicts purged ids from the worker's caches; the worker does not reply. */
2991
+ type EvictPurgedMessage = {
2992
+ type: "evict-purged";
2993
+ documentIds: string[];
2994
+ };
2776
2995
  /**
2777
2996
  * Union of all messages the parent may send to a worker.
2778
2997
  *
2779
2998
  * @see Wire Protocol Reference wiki page
2780
2999
  * (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
2781
3000
  */
2782
- type ParentMessage = InitMessage | ExecuteMessage | AbortMessage | ShutdownMessage | LoadModelMessage;
3001
+ type ParentMessage = InitMessage | ExecuteMessage | AbortMessage | ShutdownMessage | LoadModelMessage | EvictPurgedMessage;
2783
3002
  /**
2784
3003
  * Announces that the worker has finished `init` and is ready to accept
2785
3004
  * `execute` messages.
@@ -3074,6 +3293,10 @@ type JobWriteReadyEvent = {
3074
3293
  */
3075
3294
  collectionMemberships?: Record<string, string[]>;
3076
3295
  };
3296
+ /** Set on a marker's context when its purge deleted a live document. */
3297
+ type PurgeMarkerContext = OperationContext$1 & {
3298
+ appliedDeletion?: true;
3299
+ };
3077
3300
  /**
3078
3301
  * Event emitted after all read models have finished processing operations.
3079
3302
  * This event fires after JOB_WRITE_READY and guarantees that:
@@ -3145,99 +3368,203 @@ type CatchUpSweptEvent = SweepResult & {
3145
3368
  thread: CatchUpThread;
3146
3369
  };
3147
3370
  //#endregion
3148
- //#region src/catch-up/types.d.ts
3149
- type WatermarkStatus = {
3150
- head: number;
3151
- settledThrough: number;
3152
- waitingOn: string[];
3153
- stalledSinceUtcMs?: number;
3154
- };
3155
- interface ISettledWatermark {
3156
- /** Every ordinal at or below this is visible or will never exist. */
3157
- readonly settledThrough: number;
3158
- /** Probes, coalesced with one in flight; resolves with settledThrough. */
3159
- refresh(signal?: AbortSignal): Promise<number>;
3160
- onAdvance(listener: (settledThrough: number) => void): Unsubscribe;
3161
- status(): WatermarkStatus;
3162
- }
3163
- type SweepBlockedAt = {
3164
- ordinal: number;
3165
- documentId: string;
3166
- scope: string;
3167
- branch: string;
3168
- type: string;
3169
- error: string;
3170
- };
3171
- type SweepResult = {
3172
- consumerId: string;
3173
- from: number;
3174
- to: number;
3175
- durationMs: number;
3176
- /** Late operations applied. */
3177
- replayed: number;
3178
- /** Later operations of their streams applied again. */
3179
- reapplied: number;
3180
- blockedAt?: SweepBlockedAt;
3181
- };
3182
- interface ICatchUpConsumer {
3183
- readonly consumerId: string;
3184
- readonly appliedThrough: number;
3185
- /** Ordinals above the cursor this consumer holds in memory. */
3186
- readonly trackedAbove: number;
3187
- sweep(settledThrough: number, present: readonly number[], signal?: AbortSignal): Promise<SweepResult>;
3188
- }
3189
- type CatchUpThread = "host" | "projection";
3190
- type CatchUpConsumerStatus = {
3191
- consumerId: string;
3192
- thread: CatchUpThread;
3193
- appliedThrough: number;
3194
- trackedAbove: number;
3195
- blockedAt?: SweepBlockedAt;
3196
- lastAdvanceUtcMs: number;
3197
- };
3198
- type CatchUpStatus = {
3199
- watermark: WatermarkStatus;
3200
- consumers: CatchUpConsumerStatus[];
3201
- };
3202
- type CatchUpConfig = {
3203
- intervalMs: number;
3204
- stuckWarnMs: number;
3205
- maxTrackedAboveCursor: number;
3206
- /** Present ordinals read per tick. */
3207
- sweepPageSize: number;
3208
- };
3209
- export declare const defaultCatchUpConfig: CatchUpConfig;
3210
- /** The catch-up surface a reactor module exposes. */
3211
- interface ICatchUp {
3212
- status(): CatchUpStatus;
3213
- sweepNow(): Promise<SweepResult[]>;
3214
- }
3215
- //#endregion
3216
3371
  //#region src/events/interfaces.d.ts
3217
3372
  /**
3218
3373
  * Describes an object that manages event subscriptions and emissions.
3219
3374
  */
3220
3375
  interface IEventBus {
3221
3376
  /**
3222
- * Register a new subscriber.
3223
- * Order is preserved by pushing to the end of the per-type array.
3224
- *
3225
- * @param type - The type of event to subscribe to.
3226
- * @param subscriber - The subscriber function to call when the event is emitted.
3227
- *
3228
- * @returns A function to unsubscribe from the event.
3377
+ * Register a new subscriber.
3378
+ * Order is preserved by pushing to the end of the per-type array.
3379
+ *
3380
+ * @param type - The type of event to subscribe to.
3381
+ * @param subscriber - The subscriber function to call when the event is emitted.
3382
+ *
3383
+ * @returns A function to unsubscribe from the event.
3384
+ */
3385
+ subscribe<K>(type: number, subscriber: (type: number, event: K) => void | Promise<void>): Unsubscribe;
3386
+ /**
3387
+ * Emits an event and waits until **all** subscribers finish.
3388
+ * - Every subscriber present at emit-start is called, in registration order.
3389
+ * - Calls are invoked and settled sequentially.
3390
+ * - If subscribers throw/reject, `emit` rejects with an aggregate error of all errors.
3391
+ *
3392
+ * @param type - The type of event to emit.
3393
+ * @param data - The data to pass to the subscribers.
3394
+ */
3395
+ emit(type: number, data: any): Promise<void>;
3396
+ }
3397
+ //#endregion
3398
+ //#region src/job-tracker/interfaces.d.ts
3399
+ /**
3400
+ * Interface for tracking job lifecycle status.
3401
+ * Maintains job state throughout execution: PENDING → RUNNING → COMPLETED/FAILED.
3402
+ */
3403
+ interface IJobTracker {
3404
+ /**
3405
+ * Register a new job with PENDING status.
3406
+ *
3407
+ * @param jobInfo - The job information to register
3408
+ */
3409
+ registerJob(jobInfo: JobInfo): void;
3410
+ /**
3411
+ * Update a job's status to RUNNING.
3412
+ *
3413
+ * @param jobId - The job ID to mark as running
3414
+ */
3415
+ markRunning(jobId: string): void;
3416
+ /**
3417
+ * Mark a job as failed.
3418
+ *
3419
+ * @param jobId - The job ID to mark as failed
3420
+ * @param error - Error information including message and stack trace
3421
+ * @param job - Optional full job object for debugging purposes
3422
+ */
3423
+ markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
3424
+ /**
3425
+ * Retrieve the current status of a job.
3426
+ *
3427
+ * @param jobId - The job ID to query
3428
+ * @returns The job information, or null if the job is not found
3429
+ */
3430
+ getJobStatus(jobId: string): JobInfo | null;
3431
+ /**
3432
+ * Shutdown the job tracker and clean up resources.
3433
+ * Unsubscribes from all event bus subscriptions.
3434
+ */
3435
+ shutdown(): void;
3436
+ }
3437
+ //#endregion
3438
+ //#region src/queue/interfaces.d.ts
3439
+ /**
3440
+ * Interface for a job queue that manages write operations.
3441
+ * Internally organizes jobs by documentId, scope, and branch to ensure proper ordering.
3442
+ * Emits events to the event bus when new jobs are available for consumption.
3443
+ */
3444
+ interface IQueue {
3445
+ /**
3446
+ * Add a new job to the queue.
3447
+ * Jobs are automatically organized by documentId, scope, and branch internally.
3448
+ * Emits a 'jobAvailable' event to the event bus when the job is queued.
3449
+ * @param job - The job to add to the queue
3450
+ * @returns Promise that resolves when the job is queued
3451
+ */
3452
+ enqueue(job: Job): Promise<void>;
3453
+ /**
3454
+ * Get the next job to execute for a specific document/scope/branch combination.
3455
+ * @param documentId - The document ID to get jobs for
3456
+ * @param scope - The scope to get jobs for
3457
+ * @param branch - The branch to get jobs for
3458
+ * @param signal - Optional abort signal to cancel the request
3459
+ * @returns Promise that resolves to the next job execution handle or null if no jobs available
3460
+ */
3461
+ dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
3462
+ /**
3463
+ * Get the next available job from any queue.
3464
+ * @param signal - Optional abort signal to cancel the request
3465
+ * @returns Promise that resolves to the next job execution handle or null if no jobs available
3466
+ */
3467
+ dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
3468
+ /**
3469
+ * Get the next available job whose routing metadata satisfies the predicate.
3470
+ * Walks ready sub-queue heads in queue insertion order, skips heads whose document
3471
+ * is currently executing (same isDocumentExecuting gate as dequeueNext), and returns
3472
+ * the first head for which predicate returns true.
3473
+ * Returns null when paused, when nothing matches, or when the queue is empty.
3474
+ * Rejects if signal is already aborted.
3475
+ * @param predicate - Filter applied to JobRoutingMeta of each candidate head
3476
+ * @param signal - Optional abort signal to cancel the request
3477
+ * @returns Promise that resolves to the first matching job execution handle or null
3478
+ */
3479
+ dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
3480
+ /**
3481
+ * Get the current size of the queue for a specific document/scope/branch.
3482
+ * @param documentId - The document ID
3483
+ * @param scope - The scope
3484
+ * @param branch - The branch
3485
+ * @returns Promise that resolves to the number of jobs in the queue
3486
+ */
3487
+ size(documentId: string, scope: string, branch: string): Promise<number>;
3488
+ /**
3489
+ * Get the total size of all queues.
3490
+ * @returns Promise that resolves to the total number of jobs across all queues
3491
+ */
3492
+ totalSize(): Promise<number>;
3493
+ /**
3494
+ * Remove a specific job from the queue.
3495
+ * @param jobId - The ID of the job to remove
3496
+ * @returns Promise that resolves to true if job was removed, false if not found
3497
+ */
3498
+ remove(jobId: string): Promise<boolean>;
3499
+ /**
3500
+ * Clear all jobs for a specific document/scope/branch combination.
3501
+ * @param documentId - The document ID
3502
+ * @param scope - The scope
3503
+ * @param branch - The branch
3504
+ * @returns Promise that resolves when the queue is cleared
3505
+ */
3506
+ clear(documentId: string, scope: string, branch: string): Promise<void>;
3507
+ /**
3508
+ * Clear all jobs from all queues.
3509
+ * @returns Promise that resolves when all queues are cleared
3510
+ */
3511
+ clearAll(): Promise<void>;
3512
+ /**
3513
+ * Check if there are any jobs in the queue.
3514
+ * @returns Promise that resolves to true if there are jobs, false otherwise
3515
+ */
3516
+ hasJobs(): Promise<boolean>;
3517
+ /**
3518
+ * Mark a job as completed.
3519
+ * @param jobId - The ID of the job to mark as completed
3520
+ * @returns Promise that resolves when the job is marked as completed
3521
+ */
3522
+ completeJob(jobId: string): Promise<void>;
3523
+ /**
3524
+ * Mark a job as failed.
3525
+ * @param jobId - The ID of the job to mark as failed
3526
+ * @param error - Optional error information
3527
+ * @returns Promise that resolves when the job is marked as failed
3528
+ */
3529
+ failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
3530
+ /**
3531
+ * Retry a failed job.
3532
+ * @param jobId - The ID of the job to retry
3533
+ * @param error - Optional error information from the failure
3534
+ * @param accounting - Whether the attempt counts against the job's retry
3535
+ * limit; defaults to {@link RetryAccounting.CountAgainstLimit}
3536
+ * @returns Promise that resolves when the job is requeued for retry
3537
+ */
3538
+ retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
3539
+ /**
3540
+ * Returns true if and only if all jobs have been resolved.
3541
+ */
3542
+ get isDrained(): boolean;
3543
+ /**
3544
+ * Blocks the queue from accepting new jobs.
3545
+ * @param onDrained - Optional callback to call when the queue is drained
3229
3546
  */
3230
- subscribe<K>(type: number, subscriber: (type: number, event: K) => void | Promise<void>): Unsubscribe;
3547
+ block(onDrained?: () => void): void;
3231
3548
  /**
3232
- * Emits an event and waits until **all** subscribers finish.
3233
- * - Every subscriber present at emit-start is called, in registration order.
3234
- * - Calls are invoked and settled sequentially.
3235
- * - If subscribers throw/reject, `emit` rejects with an aggregate error of all errors.
3236
- *
3237
- * @param type - The type of event to emit.
3238
- * @param data - The data to pass to the subscribers.
3549
+ * Unblocks the queue from accepting new jobs.
3239
3550
  */
3240
- emit(type: number, data: any): Promise<void>;
3551
+ unblock(): void;
3552
+ }
3553
+ //#endregion
3554
+ //#region src/admin/document-purge-service.d.ts
3555
+ type EnqueuePurgeOptions = {
3556
+ /** Lifts the executor's maxPurgeOperations cap for every id. */
3557
+ allowLarge?: boolean;
3558
+ };
3559
+ /** The only local origin of a purge: one purge job per erased document. */
3560
+ export declare class DocumentPurgeService {
3561
+ private readonly queue;
3562
+ private readonly jobTracker;
3563
+ private readonly eventBus;
3564
+ constructor(queue: IQueue, jobTracker: IJobTracker, eventBus: IEventBus);
3565
+ static fromModule(module: InProcessReactorModule): DocumentPurgeService;
3566
+ /** One purge job per id; resolves once enqueued, not once complete. */
3567
+ enqueuePurge(ids: string[], requestId: string, opts?: EnqueuePurgeOptions): Promise<JobInfo[]>;
3241
3568
  }
3242
3569
  //#endregion
3243
3570
  //#region src/shared/awaiter.d.ts
@@ -3297,6 +3624,10 @@ interface SubscriptionErrorContext {
3297
3624
  /** Optional additional data about the event */
3298
3625
  eventData?: unknown;
3299
3626
  }
3627
+ /** Set on a deletion notice when a purge marker applied the deletion. */
3628
+ type DocumentDeletedInfo = {
3629
+ purged?: true;
3630
+ };
3300
3631
  /**
3301
3632
  * Interface for subscribing to document events in the reactor.
3302
3633
  */
@@ -3317,7 +3648,7 @@ interface IReactorSubscriptionManager {
3317
3648
  * @param search - Optional search filter to limit which documents trigger events
3318
3649
  * @returns A function that unsubscribes from the events
3319
3650
  */
3320
- onDocumentDeleted(callback: (documentIds: string[]) => void, search?: SearchFilter): () => void;
3651
+ onDocumentDeleted(callback: (documentIds: string[], info?: DocumentDeletedInfo) => void, search?: SearchFilter): () => void;
3321
3652
  /**
3322
3653
  * Subscribes to document state updates
3323
3654
  *
@@ -3368,6 +3699,11 @@ export declare const RECOVERABLE_GRAPHQL_ERROR_CODES: {
3368
3699
  * those too.
3369
3700
  */
3370
3701
  readonly malformedStoredOperation: "MALFORMED_STORED_OPERATION";
3702
+ /**
3703
+ * The poll's marker refusals could not be recorded, so nothing was served.
3704
+ * The client keeps them pending and reports them on its next poll.
3705
+ */
3706
+ readonly refusalNotRecorded: "REFUSAL_NOT_RECORDED";
3371
3707
  };
3372
3708
  /**
3373
3709
  * True when every error the response carried named a recoverable code.
@@ -3464,6 +3800,7 @@ interface IMailbox {
3464
3800
  /**
3465
3801
  * The latest ordinal that has been acknowledged. Because acknowledged items
3466
3802
  * are removed from the mailbox, this is the last ordinal that has been removed.
3803
+ * With holdAckBelowMarkers, never at or past an unapplied marker entry.
3467
3804
  */
3468
3805
  get ackOrdinal(): number;
3469
3806
  /**
@@ -3484,8 +3821,15 @@ interface IMailbox {
3484
3821
  flush(): void;
3485
3822
  isPaused(): boolean;
3486
3823
  }
3824
+ type MailboxOptions = {
3825
+ /** An unapplied item carrying a purge marker keeps ackOrdinal below it. */
3826
+ holdAckBelowMarkers?: boolean;
3827
+ };
3487
3828
  export declare class Mailbox implements IMailbox {
3829
+ private readonly holdAckBelowMarkers;
3488
3830
  private itemsMap;
3831
+ /** Unapplied items carrying a marker, so the held ack reads only these. */
3832
+ private readonly heldMarkers;
3489
3833
  private addedCallbacks;
3490
3834
  private removedCallbacks;
3491
3835
  private paused;
@@ -3493,6 +3837,7 @@ export declare class Mailbox implements IMailbox {
3493
3837
  private removedBuffer;
3494
3838
  private _ack;
3495
3839
  private _latestOrdinal;
3840
+ constructor(options?: MailboxOptions);
3496
3841
  init(ackOrdinal: number): void;
3497
3842
  advanceOrdinal(ordinal: number): void;
3498
3843
  get items(): ReadonlyArray<SyncOperation>;
@@ -3619,6 +3964,8 @@ interface IChannel {
3619
3964
  * fires.
3620
3965
  */
3621
3966
  onPeerManifest?(callback: PeerManifestListener): () => void;
3967
+ /** Hears the remote's next report of this refused marker again. */
3968
+ forgetMarkerRefusal?(documentId: string, branch: string): void;
3622
3969
  }
3623
3970
  /**
3624
3971
  * `undelivered`: outbox items the channel sent that the peer never received,
@@ -3747,6 +4094,12 @@ interface ISyncManager {
3747
4094
  * @throws Error if the remote does not exist, or is bound to another address
3748
4095
  */
3749
4096
  bindRemote(id: string, boundAddress: string): Promise<void>;
4097
+ /**
4098
+ * Settles once the named remotes' received markers are stored, or every
4099
+ * remote's when none are named; rejects if a write failed. A push is
4100
+ * answered after it.
4101
+ */
4102
+ receiptsStored?(remoteNames?: Iterable<string>): Promise<void>;
3750
4103
  /**
3751
4104
  * Triggers a one-shot pull for the named remote. Useful for Manual poll-behavior
3752
4105
  * remotes, where the channel is registered but does not poll on a schedule.
@@ -3841,6 +4194,8 @@ type StreamQuery = {
3841
4194
  */
3842
4195
  interface IStreamStateReader {
3843
4196
  getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
4197
+ /** Readies the purge fence for ids about to be read, in one round trip. */
4198
+ fence?(documentIds: readonly string[]): Promise<void>;
3844
4199
  }
3845
4200
  /** The document and branch a decision model is built for. */
3846
4201
  type DecisionTarget = {
@@ -3951,6 +4306,8 @@ type DocumentChangeEvent = {
3951
4306
  context?: {
3952
4307
  parentId?: string;
3953
4308
  childId?: string;
4309
+ /** On a Deleted event: a purge marker applied the deletion. */
4310
+ purged?: true;
3954
4311
  };
3955
4312
  };
3956
4313
  /**
@@ -4260,6 +4617,17 @@ interface IReactorClient {
4260
4617
  * @returns The created document
4261
4618
  */
4262
4619
  create<TDocument extends PHDocument = PHDocument>(document: PHDocument, parentIdentifier?: string, signal?: AbortSignal): Promise<TDocument>;
4620
+ /**
4621
+ * Submits what {@link create} submits and returns without waiting. The
4622
+ * batch holds a `create` job and, with a parent, a `parent` job that
4623
+ * depends on it; a failed `create` still releases `parent`.
4624
+ *
4625
+ * @param document - Document with optional id, slug, parent, model type, and initial state
4626
+ * @param parentIdentifier - Optional "id" or "slug" of parent document
4627
+ * @param signal - Optional abort signal to cancel the request
4628
+ * @returns The submitted jobs, keyed `create` and `parent`
4629
+ */
4630
+ createAsync(document: PHDocument, parentIdentifier?: string, signal?: AbortSignal): Promise<BatchExecutionResult>;
4263
4631
  /**
4264
4632
  * Creates an empty document and waits for completion
4265
4633
  *
@@ -4268,6 +4636,16 @@ interface IReactorClient {
4268
4636
  * @param signal - Optional abort signal to cancel the request
4269
4637
  */
4270
4638
  createEmpty<TDocument extends PHDocument>(documentModelType: string, options?: CreateDocumentOptions, signal?: AbortSignal): Promise<TDocument>;
4639
+ /**
4640
+ * Submits what {@link createEmpty} submits and returns without waiting;
4641
+ * see {@link createAsync}. The new document's id is `jobs.create.documentId`.
4642
+ *
4643
+ * @param documentModelType - Type of document to create
4644
+ * @param options - Optional creation options (parentIdentifier, documentModelVersion)
4645
+ * @param signal - Optional abort signal to cancel the request
4646
+ * @returns The submitted jobs, keyed `create` and `parent`
4647
+ */
4648
+ createEmptyAsync(documentModelType: string, options?: CreateDocumentOptions, signal?: AbortSignal): Promise<BatchExecutionResult>;
4271
4649
  /**
4272
4650
  * Retrieves the document model module matching the version a document is
4273
4651
  * stamped with. Use this instead of {@link getDocumentModelModule}
@@ -4616,7 +4994,7 @@ export declare class SeededStateReader implements IStreamStateReader {
4616
4994
  * A stream this replica does not hold has to reach buildDecisionModel as the
4617
4995
  * absence it recognises, or the whole read fails instead of leaving the group
4618
4996
  * out of the model, where its principal does not match and the policy fails
4619
- * closed. The read side reports absence as a plain Error, so the absence is
4997
+ * closed. An error other than DocumentNotFoundError has its absence
4620
4998
  * confirmed rather than inferred from the message: a transient failure must
4621
4999
  * surface, not silently deny.
4622
5000
  */
@@ -4836,10 +5214,20 @@ export declare class ReactorClient implements IReactorClient {
4836
5214
  * Creates a document and waits for completion
4837
5215
  */
4838
5216
  create<TDocument extends PHDocument = PHDocument>(document: PHDocument, parentIdentifier?: string, signal?: AbortSignal): Promise<TDocument>;
5217
+ /**
5218
+ * Submits a document's create batch without waiting for it
5219
+ */
5220
+ createAsync(document: PHDocument, parentIdentifier?: string, signal?: AbortSignal): Promise<BatchExecutionResult>;
5221
+ private submitCreate;
4839
5222
  /**
4840
5223
  * Creates an empty document and waits for completion
4841
5224
  */
4842
5225
  createEmpty<TDocument extends PHDocument>(documentModelType: string, options?: CreateDocumentOptions, signal?: AbortSignal): Promise<TDocument>;
5226
+ /**
5227
+ * Submits an empty document's create batch without waiting for it
5228
+ */
5229
+ createEmptyAsync(documentModelType: string, options?: CreateDocumentOptions, signal?: AbortSignal): Promise<BatchExecutionResult>;
5230
+ private emptyDocument;
4843
5231
  /**
4844
5232
  * Upgrades a document to a newer document model version by dispatching an
4845
5233
  * UPGRADE_DOCUMENT action. When toVersion is omitted, upgrades to the
@@ -4989,10 +5377,15 @@ export declare class ReactorClient implements IReactorClient {
4989
5377
  private readRelationshipEdge;
4990
5378
  /**
4991
5379
  * The id a write on `identifier` is stored under, which its signatures bind.
4992
- * A create names its own id, and an id no slug maps to is taken as given, so
4993
- * a document still in flight resolves to itself.
5380
+ * A create names its own id.
4994
5381
  */
4995
5382
  private resolveWriteTarget;
5383
+ /**
5384
+ * The id a document reference names. An id no slug maps to is taken as
5385
+ * given, so a document still in flight resolves to itself; an id that is
5386
+ * another document's slug is refused as ambiguous.
5387
+ */
5388
+ private resolveReference;
4996
5389
  /**
4997
5390
  * The decision model for one target document, built at its stream heads.
4998
5391
  *
@@ -5014,7 +5407,8 @@ export declare class ReactorClient implements IReactorClient {
5014
5407
  * is why the answer is a prediction.
5015
5408
  */
5016
5409
  private buildEvaluationTarget;
5017
- private removeAllIncomingRelationships;
5410
+ private planDelete;
5411
+ private planRemoval;
5018
5412
  }
5019
5413
  //#endregion
5020
5414
  //#region src/executor/interfaces.d.ts
@@ -5084,6 +5478,8 @@ interface IExecutorWorker {
5084
5478
  * with `model-load-failed` or the worker exits before answering.
5085
5479
  */
5086
5480
  loadModel(entry: ModelManifestEntry, signal?: AbortSignal): Promise<void>;
5481
+ /** Evicts purged ids from the worker's caches; a worker not ready skips it. */
5482
+ evictPurged(documentIds: string[]): void;
5087
5483
  /** True when no job is currently in flight. */
5088
5484
  isIdle(): boolean;
5089
5485
  /** Snapshot of the in-flight slot, or null when idle. */
@@ -5136,162 +5532,6 @@ interface IJobExecutorManager {
5136
5532
  getStatus(): ExecutorManagerStatus;
5137
5533
  }
5138
5534
  //#endregion
5139
- //#region src/job-tracker/interfaces.d.ts
5140
- /**
5141
- * Interface for tracking job lifecycle status.
5142
- * Maintains job state throughout execution: PENDING → RUNNING → COMPLETED/FAILED.
5143
- */
5144
- interface IJobTracker {
5145
- /**
5146
- * Register a new job with PENDING status.
5147
- *
5148
- * @param jobInfo - The job information to register
5149
- */
5150
- registerJob(jobInfo: JobInfo): void;
5151
- /**
5152
- * Update a job's status to RUNNING.
5153
- *
5154
- * @param jobId - The job ID to mark as running
5155
- */
5156
- markRunning(jobId: string): void;
5157
- /**
5158
- * Mark a job as failed.
5159
- *
5160
- * @param jobId - The job ID to mark as failed
5161
- * @param error - Error information including message and stack trace
5162
- * @param job - Optional full job object for debugging purposes
5163
- */
5164
- markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
5165
- /**
5166
- * Retrieve the current status of a job.
5167
- *
5168
- * @param jobId - The job ID to query
5169
- * @returns The job information, or null if the job is not found
5170
- */
5171
- getJobStatus(jobId: string): JobInfo | null;
5172
- /**
5173
- * Shutdown the job tracker and clean up resources.
5174
- * Unsubscribes from all event bus subscriptions.
5175
- */
5176
- shutdown(): void;
5177
- }
5178
- //#endregion
5179
- //#region src/queue/interfaces.d.ts
5180
- /**
5181
- * Interface for a job queue that manages write operations.
5182
- * Internally organizes jobs by documentId, scope, and branch to ensure proper ordering.
5183
- * Emits events to the event bus when new jobs are available for consumption.
5184
- */
5185
- interface IQueue {
5186
- /**
5187
- * Add a new job to the queue.
5188
- * Jobs are automatically organized by documentId, scope, and branch internally.
5189
- * Emits a 'jobAvailable' event to the event bus when the job is queued.
5190
- * @param job - The job to add to the queue
5191
- * @returns Promise that resolves when the job is queued
5192
- */
5193
- enqueue(job: Job): Promise<void>;
5194
- /**
5195
- * Get the next job to execute for a specific document/scope/branch combination.
5196
- * @param documentId - The document ID to get jobs for
5197
- * @param scope - The scope to get jobs for
5198
- * @param branch - The branch to get jobs for
5199
- * @param signal - Optional abort signal to cancel the request
5200
- * @returns Promise that resolves to the next job execution handle or null if no jobs available
5201
- */
5202
- dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
5203
- /**
5204
- * Get the next available job from any queue.
5205
- * @param signal - Optional abort signal to cancel the request
5206
- * @returns Promise that resolves to the next job execution handle or null if no jobs available
5207
- */
5208
- dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
5209
- /**
5210
- * Get the next available job whose routing metadata satisfies the predicate.
5211
- * Walks ready sub-queue heads in queue insertion order, skips heads whose document
5212
- * is currently executing (same isDocumentExecuting gate as dequeueNext), and returns
5213
- * the first head for which predicate returns true.
5214
- * Returns null when paused, when nothing matches, or when the queue is empty.
5215
- * Rejects if signal is already aborted.
5216
- * @param predicate - Filter applied to JobRoutingMeta of each candidate head
5217
- * @param signal - Optional abort signal to cancel the request
5218
- * @returns Promise that resolves to the first matching job execution handle or null
5219
- */
5220
- dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
5221
- /**
5222
- * Get the current size of the queue for a specific document/scope/branch.
5223
- * @param documentId - The document ID
5224
- * @param scope - The scope
5225
- * @param branch - The branch
5226
- * @returns Promise that resolves to the number of jobs in the queue
5227
- */
5228
- size(documentId: string, scope: string, branch: string): Promise<number>;
5229
- /**
5230
- * Get the total size of all queues.
5231
- * @returns Promise that resolves to the total number of jobs across all queues
5232
- */
5233
- totalSize(): Promise<number>;
5234
- /**
5235
- * Remove a specific job from the queue.
5236
- * @param jobId - The ID of the job to remove
5237
- * @returns Promise that resolves to true if job was removed, false if not found
5238
- */
5239
- remove(jobId: string): Promise<boolean>;
5240
- /**
5241
- * Clear all jobs for a specific document/scope/branch combination.
5242
- * @param documentId - The document ID
5243
- * @param scope - The scope
5244
- * @param branch - The branch
5245
- * @returns Promise that resolves when the queue is cleared
5246
- */
5247
- clear(documentId: string, scope: string, branch: string): Promise<void>;
5248
- /**
5249
- * Clear all jobs from all queues.
5250
- * @returns Promise that resolves when all queues are cleared
5251
- */
5252
- clearAll(): Promise<void>;
5253
- /**
5254
- * Check if there are any jobs in the queue.
5255
- * @returns Promise that resolves to true if there are jobs, false otherwise
5256
- */
5257
- hasJobs(): Promise<boolean>;
5258
- /**
5259
- * Mark a job as completed.
5260
- * @param jobId - The ID of the job to mark as completed
5261
- * @returns Promise that resolves when the job is marked as completed
5262
- */
5263
- completeJob(jobId: string): Promise<void>;
5264
- /**
5265
- * Mark a job as failed.
5266
- * @param jobId - The ID of the job to mark as failed
5267
- * @param error - Optional error information
5268
- * @returns Promise that resolves when the job is marked as failed
5269
- */
5270
- failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
5271
- /**
5272
- * Retry a failed job.
5273
- * @param jobId - The ID of the job to retry
5274
- * @param error - Optional error information from the failure
5275
- * @param accounting - Whether the attempt counts against the job's retry
5276
- * limit; defaults to {@link RetryAccounting.CountAgainstLimit}
5277
- * @returns Promise that resolves when the job is requeued for retry
5278
- */
5279
- retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
5280
- /**
5281
- * Returns true if and only if all jobs have been resolved.
5282
- */
5283
- get isDrained(): boolean;
5284
- /**
5285
- * Blocks the queue from accepting new jobs.
5286
- * @param onDrained - Optional callback to call when the queue is drained
5287
- */
5288
- block(onDrained?: () => void): void;
5289
- /**
5290
- * Unblocks the queue from accepting new jobs.
5291
- */
5292
- unblock(): void;
5293
- }
5294
- //#endregion
5295
5535
  //#region src/shared/consistency-tracker.d.ts
5296
5536
  interface IConsistencyTracker {
5297
5537
  /**
@@ -5408,6 +5648,13 @@ export declare const DEFAULT_READ_MODEL_YIELD_DEADLINE_MS = 50;
5408
5648
  export declare const defaultReadModelIndexingConfig: ReadModelIndexingConfig;
5409
5649
  /** For read models whose callers can observe where a batch was split. */
5410
5650
  export declare const unchunkedReadModelIndexingConfig: ReadModelIndexingConfig;
5651
+ type PurgeFence =
5652
+ /** Commits in a purge-locked trx; see commitsInFenceTransaction. */
5653
+ "locked" |
5654
+ /** Drops tombstoned ids only, for rows that live on another database handle. */
5655
+ "skip" |
5656
+ /** No fence: ProcessorManager, and commits that open their own trx on this.db. */
5657
+ "none";
5411
5658
  type BaseReadModelConfig = {
5412
5659
  readModelId: string;
5413
5660
  /** Rebuilds resultingState for boot replay and sweeps. */
@@ -5418,6 +5665,8 @@ type BaseReadModelConfig = {
5418
5665
  startFrom?: "beginning" | "head";
5419
5666
  /** Re-applies the rest of a late operation's stream; defaults to true. */
5420
5667
  replayStreamSuffix?: boolean;
5668
+ /** Defaults to "locked"; see {@link PurgeFence} for the opt-outs. */
5669
+ purgeFence?: PurgeFence;
5421
5670
  };
5422
5671
  /** A read model whose cursor only sweeps and boot replay advance. */
5423
5672
  export declare class BaseReadModel implements IReadModel, ICatchUpConsumer {
@@ -5439,6 +5688,8 @@ export declare class BaseReadModel implements IReadModel, ICatchUpConsumer {
5439
5688
  private readonly liveInFlight;
5440
5689
  private readonly sweptListeners;
5441
5690
  constructor(db: Kysely<DocumentViewDatabase>, operationIndex: IOperationIndex, writeCache: IWriteCache, consistencyTracker: IConsistencyTracker, config: BaseReadModelConfig);
5691
+ /** Set by a subclass whose commitOperations writes through its trx argument. */
5692
+ static readonly commitsInFenceTransaction: boolean;
5442
5693
  get consumerId(): string;
5443
5694
  get appliedThrough(): number;
5444
5695
  get trackedAbove(): number;
@@ -5461,7 +5712,14 @@ export declare class BaseReadModel implements IReadModel, ICatchUpConsumer {
5461
5712
  protected get lastOrdinal(): number;
5462
5713
  /** Called after the cursor advances. */
5463
5714
  protected onCursorAdvanced(appliedThrough: number): void;
5464
- protected commitOperations(items: OperationWithContext$1[]): Promise<void>;
5715
+ /** Writes through `trx` when given: the purge fence's transaction. */
5716
+ protected commitOperations(items: OperationWithContext$1[], trx?: Transaction<DocumentViewDatabase>): Promise<void>;
5717
+ /** The handle document_purges is read through; `db` may be the fence trx. */
5718
+ protected purgeLookup(db: Kysely<any>): Kysely<any>;
5719
+ /** False when the batch writes no rows, so the fence opens no transaction. */
5720
+ protected writesRows(items: OperationWithContext$1[]): boolean;
5721
+ /** Every delivery commits through here. */
5722
+ protected commitFenced(items: OperationWithContext$1[]): Promise<void>;
5465
5723
  /** Rebuilds resultingState as the executor writes it: scopes plus header. */
5466
5724
  protected rebuildStateForOperations(operations: OperationWithContext$1[]): Promise<OperationWithContext$1[]>;
5467
5725
  /**
@@ -5495,8 +5753,10 @@ export declare class BaseReadModel implements IReadModel, ICatchUpConsumer {
5495
5753
  private replayPage;
5496
5754
  private replayOwned;
5497
5755
  private sweepStream;
5498
- /** A document gone from the write cache is absent, not a failure. */
5756
+ /** A document gone from the write cache, or purged, is absent. */
5499
5757
  private rebuildIfConfigured;
5758
+ /** A failed lookup is no answer: the caller's own error stands. */
5759
+ private isPurged;
5500
5760
  private block;
5501
5761
  private notifySwept;
5502
5762
  /** Compare-and-set against the value this process last wrote. */
@@ -5983,6 +6243,8 @@ interface InProcessReactorModule extends ReactorModule {
5983
6243
  catchUp: ICatchUp;
5984
6244
  /** The settled watermark this thread's catch-up sweeps up to. */
5985
6245
  settledWatermark: ISettledWatermark;
6246
+ /** Enqueues purge jobs; the erasure scheduler is its only caller. */
6247
+ documentPurgeService: DocumentPurgeService;
5986
6248
  }
5987
6249
  /**
5988
6250
  * Base reactor client contract — the client plus its reactor module. Satisfied
@@ -6014,11 +6276,12 @@ export declare class DriveClient implements IDriveClient {
6014
6276
  private readonly logger;
6015
6277
  private readonly reactor;
6016
6278
  private readonly signer;
6017
- constructor(client: IReactorClient, logger: ILogger, reactor: IReactor, signer: ISigner);
6279
+ private readonly resolveReference;
6280
+ constructor(client: IReactorClient, logger: ILogger, reactor: IReactor, signer: ISigner, resolveReference: (identifier: string, signal?: AbortSignal) => Promise<string>);
6018
6281
  create(input: DriveInput, signal?: AbortSignal): Promise<DocumentDriveDocument>;
6019
6282
  addFile<TDocument extends PHDocument = PHDocument>(driveIdentifier: string, document: PHDocument, parentFolder?: string, signal?: AbortSignal): Promise<TDocument>;
6020
6283
  addFolder(driveIdentifier: string, name: string, parentFolder?: string, signal?: AbortSignal): Promise<FolderNode>;
6021
- removeNode(driveIdentifier: string, nodeId: string, signal?: AbortSignal): Promise<void>;
6284
+ removeNode(driveIdentifier: string, nodeIdentifier: string, signal?: AbortSignal): Promise<void>;
6022
6285
  renameNode(driveIdentifier: string, nodeId: string, name: string, signal?: AbortSignal): Promise<Node>;
6023
6286
  setPreferredEditorOnNode(nodeId: string, preferredEditor: string | null, signal?: AbortSignal): Promise<PHDocument>;
6024
6287
  moveNode(driveIdentifier: string, srcNodeId: string, targetParentFolderId: string | undefined, signal?: AbortSignal): Promise<DocumentDriveDocument>;
@@ -6548,12 +6811,16 @@ export declare class SyncBuilder {
6548
6811
  private cursorStorage?;
6549
6812
  private deadLetterStorage?;
6550
6813
  private holdStorage?;
6814
+ private receivedMarkerStorage?;
6815
+ private purgeRefusalStorage?;
6551
6816
  private config;
6552
6817
  withChannelFactory(factory: IChannelFactory): this;
6553
6818
  withRemoteStorage(storage: ISyncRemoteStorage): this;
6554
6819
  withCursorStorage(storage: ISyncCursorStorage): this;
6555
6820
  withDeadLetterStorage(storage: ISyncDeadLetterStorage): this;
6556
6821
  withHoldStorage(storage: ISyncHoldStorage): this;
6822
+ withReceivedMarkerStorage(storage: ISyncReceivedMarkerStorage): this;
6823
+ withPurgeRefusalStorage(storage: ISyncPurgeRefusalStorage): this;
6557
6824
  withMaxDeadLettersPerRemote(limit: number): this;
6558
6825
  withMaxInboxBatchSize(limit: number): this;
6559
6826
  withMaxHeldOperationsPerRemote(limit: number): this;
@@ -7079,6 +7346,8 @@ export declare class CatchUpScheduler implements ICatchUp {
7079
7346
  * for the new Reactor architecture.
7080
7347
  */
7081
7348
  export declare class Reactor implements IReactor {
7349
+ private readonly disposers;
7350
+ private readonly closers;
7082
7351
  private logger;
7083
7352
  private documentModelRegistry;
7084
7353
  private shutdownStatus;
@@ -7094,7 +7363,7 @@ export declare class Reactor implements IReactor {
7094
7363
  private eventBus;
7095
7364
  private executorManager;
7096
7365
  private catchUp;
7097
- constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager, catchUp?: CatchUpScheduler);
7366
+ constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager, catchUp?: CatchUpScheduler, disposers?: Unsubscribe[], closers?: Array<() => Promise<void>>);
7098
7367
  kill(): ShutdownStatus;
7099
7368
  getDocumentModels(namespace?: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DocumentModelModule>>;
7100
7369
  get<TDocument extends PHDocument>(id: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
@@ -7151,6 +7420,55 @@ export declare class InvalidSignatureError extends Error {
7151
7420
  constructor(documentId: string, code: SignatureRefusalCode, reason: string);
7152
7421
  static isError(error: unknown): error is InvalidSignatureError;
7153
7422
  }
7423
+ /**
7424
+ * Error thrown when a document is not found (no operations exist for the document ID).
7425
+ */
7426
+ declare class DocumentNotFoundError extends Error {
7427
+ readonly documentId: string;
7428
+ /**
7429
+ * @param message Overrides the default text. A handler that knows which of
7430
+ * several documents an action reads - a relationship's source, say - says so
7431
+ * here rather than rewrapping in a bare Error, which would strip the name the
7432
+ * executor classifies by.
7433
+ */
7434
+ constructor(documentId: string, message?: string);
7435
+ /** Also true for DocumentPurgedError: only the name crosses the queue. */
7436
+ static isError(error: unknown): error is DocumentNotFoundError;
7437
+ }
7438
+ /** The document was purged; readers treat it as absent. Terminal. */
7439
+ export declare class DocumentPurgedError extends DocumentNotFoundError {
7440
+ readonly purged = true;
7441
+ constructor(documentId: string, message?: string);
7442
+ static isError(error: unknown): error is DocumentPurgedError;
7443
+ }
7444
+ /** A purge was asked for a document that is not deleted. Terminal. */
7445
+ export declare class DocumentNotDeletedError extends Error {
7446
+ readonly documentId: string;
7447
+ constructor(documentId: string, message?: string);
7448
+ static isError(error: unknown): error is DocumentNotDeletedError;
7449
+ }
7450
+ /** A surviving document's accepted auth history names the group. Terminal. */
7451
+ export declare class GroupInUseError extends Error {
7452
+ readonly groupId: string;
7453
+ readonly referencingDocumentIds: readonly string[];
7454
+ constructor(groupId: string, referencingDocumentIds: readonly string[]);
7455
+ static isError(error: unknown): error is GroupInUseError;
7456
+ }
7457
+ /** A purge above maxPurgeOperations without allowLarge. Terminal. */
7458
+ export declare class PurgeTooLargeError extends Error {
7459
+ readonly documentId: string;
7460
+ readonly operationCount: number;
7461
+ readonly maxPurgeOperations: number;
7462
+ constructor(documentId: string, operationCount: number, maxPurgeOperations: number);
7463
+ static isError(error: unknown): error is PurgeTooLargeError;
7464
+ }
7465
+ /** A regular write carried an action type only the reactor issues. Terminal. */
7466
+ export declare class ReservedActionError extends Error {
7467
+ readonly documentId: string;
7468
+ readonly actionType: string;
7469
+ constructor(documentId: string, actionType: string);
7470
+ static isError(error: unknown): error is ReservedActionError;
7471
+ }
7154
7472
  /**
7155
7473
  * An authorization preflight was asked for while the reactor's decision model
7156
7474
  * is off, so there is no model to answer from.
@@ -7249,7 +7567,7 @@ export declare class DefaultSubscriptionErrorHandler implements ISubscriptionErr
7249
7567
  //#endregion
7250
7568
  //#region src/subs/react-subscription-manager.d.ts
7251
7569
  type DocumentCreatedCallback = (result: PagedResults<string>) => void;
7252
- type DocumentDeletedCallback = (documentIds: string[]) => void;
7570
+ type DocumentDeletedCallback = (documentIds: string[], info?: DocumentDeletedInfo) => void;
7253
7571
  type DocumentStateUpdatedCallback = (result: PagedResults<PHDocument>) => void;
7254
7572
  type RelationshipChangedCallback = (parentId: string, childId: string, changeType: RelationshipChangeType) => void;
7255
7573
  export declare class ReactorSubscriptionManager implements IReactorSubscriptionManager {
@@ -7271,7 +7589,7 @@ export declare class ReactorSubscriptionManager implements IReactorSubscriptionM
7271
7589
  /**
7272
7590
  * Notify subscribers about deleted documents
7273
7591
  */
7274
- notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
7592
+ notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>, info?: DocumentDeletedInfo): void;
7275
7593
  /**
7276
7594
  * Notify subscribers about updated documents
7277
7595
  */
@@ -7514,6 +7832,21 @@ export declare class SimpleJobExecutor implements IJobExecutor {
7514
7832
  * has not committed yet has nothing to announce.
7515
7833
  */
7516
7834
  private executeInScope;
7835
+ /** A load names only its own id purged; a foreign one is ID_MISMATCH. */
7836
+ private purgedRefusal;
7837
+ /** A purge job or a marker load: the exclusive lock is the job's only lock. */
7838
+ private executePurge;
7839
+ /** Preconditions 1-5, then the marker this host signs. */
7840
+ private preparePurgeJob;
7841
+ /** A peer's marker, admitted alone; a receiver cannot refuse an erasure. */
7842
+ private preparePurgeLoad;
7843
+ /** Execution: delete, write the marker and its twin, tombstone, reopen. */
7844
+ private commitPurge;
7845
+ private heldStreams;
7846
+ /** Members a drive purge needs gone, and those living on elsewhere. */
7847
+ private driveMembers;
7848
+ /** The marker, signed by this executor's signer as any peer admits it. */
7849
+ private signMarker;
7517
7850
  /** A stored document at a version this reactor does not run is read-only here. */
7518
7851
  private unsupportedStoredProtocol;
7519
7852
  /**
@@ -7821,10 +8154,13 @@ export declare function firstOutOfOrderPair(operations: Operation[], options?: {
7821
8154
  //#region src/storage/kysely/document-indexer.d.ts
7822
8155
  type IndexerDatabase = Database$1 & DocumentIndexerDatabase & DocumentViewDatabase;
7823
8156
  export declare class KyselyDocumentIndexer extends BaseReadModel implements IDocumentIndexer {
8157
+ static readonly commitsInFenceTransaction = true;
7824
8158
  private _db;
7825
8159
  constructor(db: Kysely<IndexerDatabase>, operationIndex: IOperationIndex, writeCache: IWriteCache, consistencyTracker: IConsistencyTracker, indexing?: ReadModelIndexingConfig);
8160
+ protected writesRows(items: OperationWithContext$1[]): boolean;
7826
8161
  /** Opens no transaction for a batch carrying no relationship operation. */
7827
- protected commitOperations(items: OperationWithContext$1[]): Promise<void>;
8162
+ protected commitOperations(items: OperationWithContext$1[], fenced?: Transaction<DocumentViewDatabase>): Promise<void>;
8163
+ private writeRelationships;
7828
8164
  getOutgoing(documentId: string, types?: string[], paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<DocumentRelationship>>;
7829
8165
  getIncoming(documentId: string, types?: string[], paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<DocumentRelationship>>;
7830
8166
  getOrphanedChildren(parentIds: string[], types?: string[], signal?: AbortSignal): Promise<string[]>;
@@ -7900,6 +8236,7 @@ export declare enum DeletedDocumentRead {
7900
8236
  export declare class KyselyDocumentView extends BaseReadModel implements IDocumentView {
7901
8237
  private operationStore;
7902
8238
  private readonly deletedDocumentRead;
8239
+ static readonly commitsInFenceTransaction = true;
7903
8240
  private _db;
7904
8241
  constructor(db: Kysely<Database$2>, operationStore: IOperationStore, operationIndex: IOperationIndex, writeCache: IWriteCache, consistencyTracker: IConsistencyTracker, deletedDocumentRead: DeletedDocumentRead, indexing?: ReadModelIndexingConfig);
7905
8242
  /**
@@ -7916,7 +8253,7 @@ export declare class KyselyDocumentView extends BaseReadModel implements IDocume
7916
8253
  * at least the one the row already carries, so an older duplicate from a
7917
8254
  * sweep, boot replay or chunk interleave never rolls a scope back.
7918
8255
  */
7919
- protected commitOperations(items: OperationWithContext$1[]): Promise<void>;
8256
+ protected commitOperations(items: OperationWithContext$1[], fenced?: Transaction<DocumentViewDatabase>): Promise<void>;
7920
8257
  exists(documentIds: string[], existence: DocumentExistence, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<boolean[]>;
7921
8258
  get<TDocument extends PHDocument>(documentId: string, view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
7922
8259
  getMany<TDocument extends PHDocument>(documentIds: string[], view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument[]>;
@@ -8008,6 +8345,24 @@ export declare class KyselySyncHoldStorage implements ISyncHoldStorage {
8008
8345
  removeRemote(remoteName: string): Promise<void>;
8009
8346
  }
8010
8347
  //#endregion
8348
+ //#region src/storage/kysely/sync-purge-refusal-storage.d.ts
8349
+ export declare class KyselySyncPurgeRefusalStorage implements ISyncPurgeRefusalStorage {
8350
+ private readonly db;
8351
+ constructor(db: Kysely<Database$1>);
8352
+ list(documentId: string): Promise<PurgeRefusalRecord[]>;
8353
+ record(refusals: readonly PurgeRefusalRecord[]): Promise<void>;
8354
+ }
8355
+ //#endregion
8356
+ //#region src/storage/kysely/sync-received-marker-storage.d.ts
8357
+ export declare class KyselySyncReceivedMarkerStorage implements ISyncReceivedMarkerStorage {
8358
+ private readonly db;
8359
+ constructor(db: Kysely<Database$1>);
8360
+ list(remoteName: string): Promise<ReceivedMarkerRecord[]>;
8361
+ upsert(record: ReceivedMarkerRecord): Promise<void>;
8362
+ remove(remoteName: string, markerId: string): Promise<void>;
8363
+ removeRemote(remoteName: string): Promise<void>;
8364
+ }
8365
+ //#endregion
8011
8366
  //#region src/storage/kysely/sync-remote-storage.d.ts
8012
8367
  export declare class KyselySyncRemoteStorage implements ISyncRemoteStorage {
8013
8368
  private readonly db;
@@ -8135,6 +8490,10 @@ export declare class GqlRequestChannel implements IChannel {
8135
8490
  private manifestRefresh;
8136
8491
  /** Polled rows this reactor could not run, reported on the next poll. */
8137
8492
  private readonly pendingRefusals;
8493
+ /** When each pushed, unacknowledged marker entry was last pushed. */
8494
+ private readonly markerPushedAt;
8495
+ /** Documents whose marker the remote refused; its report repeats per poll. */
8496
+ private readonly refusedMarkers;
8138
8497
  private isRecovering;
8139
8498
  private connectionState;
8140
8499
  /** Latest unrecoverable error was an auth rejection; cleared on connect. */
@@ -8154,6 +8513,7 @@ export declare class GqlRequestChannel implements IChannel {
8154
8513
  lastHolderPollUtcMs(): number | undefined;
8155
8514
  setLocalManifest(provider: () => PeerManifest): void;
8156
8515
  onPeerManifest(callback: PeerManifestListener): () => void;
8516
+ forgetMarkerRefusal(documentId: string, branch: string): void;
8157
8517
  private hearPeer;
8158
8518
  /**
8159
8519
  * Re-touches once when either side's manifest moved; touching is idempotent.
@@ -8195,6 +8555,8 @@ export declare class GqlRequestChannel implements IChannel {
8195
8555
  * Queries the remote GraphQL endpoint for sync envelopes.
8196
8556
  */
8197
8557
  private pollSyncEnvelopes;
8558
+ /** A peer before the feature would reject the field; its refusals wait. */
8559
+ private peerTakesMarkerRefusals;
8198
8560
  private rejectsAgreementFields;
8199
8561
  private isAgreementRejection;
8200
8562
  /** Resolves once what the silent peer cannot run is held. */
@@ -8223,6 +8585,10 @@ export declare class GqlRequestChannel implements IChannel {
8223
8585
  * ops to deadLetter.
8224
8586
  */
8225
8587
  private attemptPush;
8588
+ /** Stops pushing a marker entry the remote refused; its wire has no op id. */
8589
+ private retireRefusedMarkers;
8590
+ /** Re-pushes markers unacked for retryMaxDelayMs: a restarted remote lost them. */
8591
+ private repushUnackedMarkers;
8226
8592
  /**
8227
8593
  * Schedules a retry of all current outbox items using exponential backoff.
8228
8594
  */
@@ -8382,6 +8748,31 @@ export declare class IntervalPollTimer implements IPollTimer {
8382
8748
  */
8383
8749
  export declare function envelopesToSyncOperations(envelope: SyncEnvelope, remoteName: string): SyncOperation[];
8384
8750
  //#endregion
8751
+ //#region src/sync/delivery-tracking.d.ts
8752
+ type PendingDelivery = {
8753
+ remote: string;
8754
+ state: ConnectionState | "held";
8755
+ };
8756
+ /** No sync manager while sync_remotes has rows means not converged. */
8757
+ interface IDeliveryTracking {
8758
+ /** Remotes that have not acknowledged ordinal for documentId's collections. */
8759
+ pendingDelivery(documentId: string, ordinal: number): Promise<PendingDelivery[]>;
8760
+ }
8761
+ export declare function supportsDeliveryTracking(x: unknown): x is IDeliveryTracking;
8762
+ type DeliveryMembership = {
8763
+ collectionId: string;
8764
+ joinedOrdinal: number;
8765
+ leftOrdinal: number | null;
8766
+ };
8767
+ type DeliveryRow = {
8768
+ entry: OperationIndexEntry;
8769
+ memberships: DeliveryMembership[];
8770
+ };
8771
+ /** The index row at an ordinal and every membership of its document. */
8772
+ type DeliveryLookup = {
8773
+ at(documentId: string, ordinal: number): Promise<DeliveryRow | undefined>;
8774
+ };
8775
+ //#endregion
8385
8776
  //#region src/sync/memory-hold-storage.d.ts
8386
8777
  /** For a sync manager built without a database. */
8387
8778
  export declare class InMemorySyncHoldStorage implements ISyncHoldStorage {
@@ -8395,6 +8786,44 @@ export declare class InMemorySyncHoldStorage implements ISyncHoldStorage {
8395
8786
  removeRemote(remoteName: string): Promise<void>;
8396
8787
  }
8397
8788
  //#endregion
8789
+ //#region src/sync/memory-purge-refusal-storage.d.ts
8790
+ /** For a sync manager built without a database. */
8791
+ export declare class InMemorySyncPurgeRefusalStorage implements ISyncPurgeRefusalStorage {
8792
+ private readonly records;
8793
+ list(documentId: string): Promise<PurgeRefusalRecord[]>;
8794
+ record(refusals: readonly PurgeRefusalRecord[]): Promise<void>;
8795
+ }
8796
+ //#endregion
8797
+ //#region src/sync/purge-refusals.d.ts
8798
+ /** The most refusals a poll reports; the rest wait for the next poll. */
8799
+ export declare const MAX_POLLED_REFUSALS = 100;
8800
+ type PolledMarkerRefusal = {
8801
+ documentId: string;
8802
+ branch: string;
8803
+ };
8804
+ /** Refusals are persisted before PURGE_REFUSED fires, so a restart keeps them. */
8805
+ interface IPurgeRefusalRecorder {
8806
+ /** Rejects when the refusal was not persisted; the caller reports it again. */
8807
+ recordPurgeRefusal(refusal: SyncPurgeRefusedEvent): Promise<void>;
8808
+ /**
8809
+ * A poller's marker refusals, at most {@link MAX_POLLED_REFUSALS}. Only a
8810
+ * tombstoned document in the remote's collection was owed its marker; any
8811
+ * other is dropped. Rejects when the refusals were not persisted.
8812
+ */
8813
+ recordPolledMarkerRefusals(remoteName: string, refusals: readonly PolledMarkerRefusal[]): Promise<void>;
8814
+ }
8815
+ export declare function supportsPurgeRefusals(x: unknown): x is IPurgeRefusalRecorder;
8816
+ //#endregion
8817
+ //#region src/sync/memory-received-marker-storage.d.ts
8818
+ /** For a sync manager built without a database. */
8819
+ export declare class InMemorySyncReceivedMarkerStorage implements ISyncReceivedMarkerStorage {
8820
+ private readonly records;
8821
+ list(remoteName: string): Promise<ReceivedMarkerRecord[]>;
8822
+ upsert(record: ReceivedMarkerRecord): Promise<void>;
8823
+ remove(remoteName: string, markerId: string): Promise<void>;
8824
+ removeRemote(remoteName: string): Promise<void>;
8825
+ }
8826
+ //#endregion
8398
8827
  //#region src/sync/utils.d.ts
8399
8828
  type OperationBatch = {
8400
8829
  documentId: string;
@@ -8541,6 +8970,8 @@ type PendingSlot = {
8541
8970
  settled: Promise<void> | undefined;
8542
8971
  };
8543
8972
  type FactoryRun = () => Promise<void>;
8973
+ /** Drives a batch deletes, each with its first deletion in the batch. */
8974
+ type DriveDeletions = ReadonlyMap<string, OperationWithContext$1>;
8544
8975
  type ProcessorManagerOptions = {
8545
8976
  legacyProcessorIds?: boolean;
8546
8977
  };
@@ -8555,6 +8986,14 @@ export declare class ProcessorManager extends BaseReadModel implements IProcesso
8555
8986
  private advancing;
8556
8987
  private cursorWrites;
8557
8988
  private draining;
8989
+ private deletedDrives;
8990
+ private erasing;
8991
+ private driveHeaders;
8992
+ private headerReads;
8993
+ private headerSlots;
8994
+ private headerWaiters;
8995
+ private stopped;
8996
+ private owedFailures;
8558
8997
  private logger;
8559
8998
  private driveContainerTypes;
8560
8999
  private legacyProcessorIds;
@@ -8563,6 +9002,8 @@ export declare class ProcessorManager extends BaseReadModel implements IProcesso
8563
9002
  protected commitOperations(items: OperationWithContext$1[]): Promise<void>;
8564
9003
  registerFactory(identifier: string, factory: ProcessorFactory$1): Promise<void>;
8565
9004
  unregisterFactory(identifier: string): Promise<void>;
9005
+ /** Closes every processor queue; the reactor's kill() calls it. */
9006
+ shutdown(): Promise<void>;
8566
9007
  get(processorId: string): TrackedProcessor$1 | undefined;
8567
9008
  getAll(): TrackedProcessor$1[];
8568
9009
  /** Synchronous: reserves a slot per registered factory for each new drive. */
@@ -8570,17 +9011,50 @@ export declare class ProcessorManager extends BaseReadModel implements IProcesso
8570
9011
  runs: FactoryRun[];
8571
9012
  reserved: Set<PendingSlot>;
8572
9013
  };
8573
- /** Synchronous: drops a deleted drive's processors from the tables. */
8574
- protected detectDeletedDrives(items: OperationWithContext$1[]): Promise<void>[];
9014
+ /** Synchronous: drops a deleted drive's processors; their rows stay owed. */
9015
+ protected detectDeletedDrives(items: OperationWithContext$1[]): void;
9016
+ /** Synchronous: a purged drive's header is erased data. */
9017
+ private forgetPurgedHeaders;
9018
+ /** A drive's creation header; minimal once the drive's stream is purged. */
9019
+ private headerOf;
9020
+ private readHeader;
9021
+ private takeHeaderSlot;
9022
+ private releaseHeaderSlot;
9023
+ /** Synchronous: the known drives this batch deletes. */
9024
+ protected findDriveDeletions(items: OperationWithContext$1[]): DriveDeletions;
8575
9025
  /** Synchronous: puts each processor's share of the batch on its queue. */
8576
- protected enqueueRouted(items: OperationWithContext$1[], reserved: ReadonlySet<PendingSlot>): Promise<void>[];
9026
+ protected enqueueRouted(items: OperationWithContext$1[], reserved: ReadonlySet<PendingSlot>, deletions?: DriveDeletions): Promise<void>[];
9027
+ private deliverDeletion;
9028
+ /** A delivered deletion deletes the row; a failed one keeps it, errored. */
9029
+ private settleErased;
9030
+ /** Keeps a failed deletion in getAll(); retry() delivers it again. */
9031
+ private trackOwedFailure;
9032
+ private retryOwed;
9033
+ /** Forgets a deleted drive once no cursor row owes its deletion. */
9034
+ private pruneDeletedDrive;
9035
+ /** Delivers each deleted drive's deletion its rows of `factoryId` still owe. */
9036
+ private eraseOwed;
9037
+ /** After any delivery of the pair's deletion in flight, if still owed. */
9038
+ private eraseOwedDrive;
9039
+ /** Marks the pair's deletion as being delivered until `erasure` settles. */
9040
+ private holdErasure;
9041
+ /** Runs `erase` unless the pair's deletion is already being delivered. */
9042
+ private claimErasure;
9043
+ private eraseDrive;
9044
+ /** The deletion to each record a row owes it to, then every disconnect. */
9045
+ private eraseRecords;
9046
+ /** Started at routing; takes no purge lock, since processors hold none. */
9047
+ private checkPurged;
8577
9048
  /** Synchronous: binds records, or discards them if the slot was cancelled. */
8578
9049
  protected bind(slot: PendingSlot, records: ProcessorRecord$1[] | undefined, creationOrdinal: number, creationItems: OperationWithContext$1[] | undefined): {
8579
9050
  persisted: Promise<void>;
8580
9051
  delivered: Promise<void>;
8581
9052
  };
8582
- /** Synchronous: removes a factory's slots, processors and cursor rows. */
9053
+ /** A cancelled slot's records; on a deleted drive they pay what rows owe. */
9054
+ private discardRecords;
9055
+ /** Synchronous: removes a factory's slots and processors; releases its rows. */
8583
9056
  protected removeFactory(identifier: string): Promise<void>[];
9057
+ private releaseCursors;
8584
9058
  private reserveSlot;
8585
9059
  private runFactory;
8586
9060
  private track;
@@ -8594,6 +9068,9 @@ export declare class ProcessorManager extends BaseReadModel implements IProcesso
8594
9068
  private allTrackedProcessors;
8595
9069
  private isDriveCreation;
8596
9070
  private discoverExistingDrives;
9071
+ /** Cursor rows of a drive that is gone: find the deletion they still owe. */
9072
+ private discoverDeletedDrives;
9073
+ private discoverDeletedDrive;
8597
9074
  private loadAllCursors;
8598
9075
  private lane;
8599
9076
  private writeCursor;
@@ -8628,6 +9105,18 @@ export declare class ContiguousCursor {
8628
9105
  advance(to: number): void;
8629
9106
  }
8630
9107
  //#endregion
8631
- export { type AbortMessage, type ActionCandidate, type ActionEvaluationConfig, type ActionEvaluations, type AdmissionDecision, type AdmissionPath, type AppendCondition, type AppendConditionStream, type AtomicTxn, type AttachmentHash, type AttachmentRef, type AuthDecisionModel, type BaseReadModelConfig, type BatchExecutionRequest, type BatchExecutionResult, type BatchLoadRequest, type BatchLoadResult, type BuiltDecisionModel, type BuiltInReadModelKind, type CachedSnapshot, type CatchUpConfig, type CatchUpConsumerStatus, type CatchUpStatus, type CatchUpSweptEvent, type CatchUpThread, type ChannelConfig, type ChannelHealth, type ChannelMeta, type ConnectionState, type ConnectionStateChangeCallback, type ConnectionStateChangedEvent, type ConnectionStateSnapshot, type ConsistencyCoordinate, type ConsistencyKey, type ConsistencyToken, type Database, type DbConfig, type DeadLetterAddedEvent, type DecisionContext, type DecisionModel, type DecisionTarget, type DegradedComponent, type DocumentChangeEvent, type DocumentDecisionModel, type DocumentGraphEdge, type DocumentIndexerDatabase, type DocumentModelSource, type DocumentModelSpec, type DocumentRelationship, type DocumentRevisions, type DocumentStreamKey, type DocumentViewDatabase, type Evaluation, type ExecuteMessage, type ExecutionJobPlan, type ExecutorStartedEvent, type ExecutorStoppedEvent, type FactorySpec, type FileModelSource, type GqlChannelConfig, type HeartbeatMessage, type HybridProjectionCoordinatorOptions, type HybridProjectionOptions, type ICatchUp, type ICatchUpConsumer, type IChannel, type IChannelFactory, type IConsistencyTracker, type IDocumentGraph, type IDocumentIndexer, type IDocumentIntegrityService, type IDocumentModelLoader, type IDocumentModelRegistry, type IDocumentModelResolver, type IDocumentView, type IDriveClient, type IEventBus, type IJobAwaiter, type IJobExecutor, type IJobExecutorManager, type IJobTracker, type IKeyframeStore, type ILiveReadModelCoordinator, type IMailbox, type IOperationIndex, type IOperationStore, type IPeerAgreement, type IPollTimer, type IProcessor, type IProcessorHostModuleBase, type IProcessorManager, type IProjectionTransport, type IQueue, type IReactor, type IReactorClient, type IReactorProcessorHostModuleBase, type IReactorSubscriptionManager, type IReadGate, type IReadModel, type IReadModelCoordinator, type IRelationalDb, type ISettledWatermark, type IStreamStateReader, type ISubscriptionErrorHandler, type ISyncCursorStorage, type ISyncHoldStorage, type ISyncManager, type ISyncRemoteStorage, type ISyncStatusTracker, type IWriteCache, SimpleJobExecutor as InMemoryJobExecutor, type InProcessReactorClientModule, type InProcessReactorModule, type InProcessSyncModule, type InitMessage, type InsertableDocumentSnapshot, type Job, type JobAvailableEvent, type JobCompletedEvent, type JobExecutorConfig, type JobExecutorFactory, type JobFailedEvent, type JobInfo, type JobPendingEvent, type JobReadReadyEvent, type JobResult, type JobResultSummary, type JobRunningEvent, type JobStartedEvent, type JobWriteReadyEvent, type JobWriteReadyPayload, type JwtHandler, type KeyframeSnapshot, type KeyframeValidationIssue, type LoadJobPlan, type LoadModelMessage, type LocalPeer, type LogMessage, type MetricsMessage, type ModelLoadFailedMessage, type ModelLoadedEvent, type ModelLoadedMessage, type ModelManifestEntry, type ModuleRef, type OperationBatch, type OperationContext, type OperationFilter, type OperationIndexEntry, type OperationTable, type OperationWithContext, type OutOfOrderPair, type PackageModelSource, type PagedResults, type PagingOptions, type ParentMessage, type ParsedDriveUrl, type ParsedPaging, type ParsedSnapshot, type PeerAgreementBasis, type PoolInstrumentation, type PoolStats, type ProbeReading, type ProcessorApp, type ProcessorFactory, type ProcessorFactoryBuilder, type ProcessorFilter, type ProcessorRecord, type ProcessorStatus, type Projection, type ProjectionShardBuilderConfig, type ProjectionShardHooks, type ProjectionShardManagerConfig, type ProjectionWorkerFactory, type ProtocolSelection, type ReactorClientModule, type ReactorFeatureFlags, type ReactorFeatures, type ReactorHostModuleBaseOptions, type JobFailedEvent$1 as ReactorJobFailedEvent, type ReactorModule, type ReactorReadModels, type ReadGateOptions, type ReadModelBatchCompletedEvent, type ReadModelCoordinatorFactory, type ReadModelCoordinatorFactoryDeps, type ReadModelFactory, type ReadModelFactoryDeps, type ReadModelIndexedEvent, type ReadModelIndexingConfig, type ReadModelIndexingStage, type ReadModelRegistrationStage, type ReadModelStage, type ReadyMessage, type RebuildResult, type RegisteredDecisionModel, RelationalDbProcessor, type Remote, type RemoteCursor, type RemoteFilter, type RemoteMeta, type RemoteOptions, type RemotePeer, type RemoteRecord, type RemoteStatus, type ResultMessage, type SanitizedArg, type SearchFilter, type ShutdownMessage, type ShutdownStatus, type SignatureRefusalCode, type SignatureRefusedEvent, type SignatureScheme, type SignatureTrustPolicy, type SignatureVerificationHandler, type SignatureVerificationMode, type SignerConfig, type SnapshotFunctions, type SnapshotValidationIssue, type Database$1 as StorageDatabase, type StreamOrderIssue, type StreamQuery, type SubjectScopePredicate, type SubmittedActionResult, type SubscriptionErrorContext, type SweepBlockedAt, type SweepResult, type SyncEnvelope, type SyncEnvelopeType, type SyncFailedEvent, type SyncHeldEvent, type SyncHold, type SyncHoldRecord, type SyncModule, type SyncOperationErrorType, type SyncPendingEvent, type SyncReleasedEvent, type SyncStatusChangeCallback, type SyncSucceededEvent, type TrackedProcessor, type Unsubscribe, type UnsupportedStoredDocuments, type ValidationResult, type VerificationTarget, type ViewFilter, type WatermarkProbe, type WatermarkStatus, type ErrorInfo as WorkerErrorInfo, type WorkerMessage, type WorkerPoolConfig, type WorkerPoolOptions, type WriteCacheConfig, createRelationalDb, documentActions };
9108
+ //#region src/storage/kysely/document-purges.d.ts
9109
+ /** Class key of every purge lock; the stream locks use the single-key space. */
9110
+ export declare const PURGE_NS = 1347571013;
9111
+ /** Ids share this many lock keys, so a job's lock count stays bounded. */
9112
+ export declare const PURGE_LOCK_BUCKETS = 1024;
9113
+ type PurgeLockMode = "shared" | "exclusive";
9114
+ export declare function acquirePurgeLocks(trx: Transaction<any>, ids: Iterable<string>, mode: PurgeLockMode): Promise<void>;
9115
+ /** The ids among `ids` that have a tombstone, read in the handle's schema. */
9116
+ export declare function findPurged(db: Kysely<any>, ids: Iterable<string>): Promise<Set<string>>;
9117
+ /** Every tombstoned id, read in the handle's schema. */
9118
+ export declare function listPurged(db: Kysely<any>): Promise<string[]>;
9119
+ //#endregion
9120
+ export { type AbortMessage, type ActionCandidate, type ActionEvaluationConfig, type ActionEvaluations, type AdmissionDecision, type AdmissionPath, type AppendCondition, type AppendConditionStream, type AtomicTxn, type AttachmentHash, type AttachmentRef, type AuthDecisionModel, type BaseReadModelConfig, type BatchExecutionRequest, type BatchExecutionResult, type BatchLoadRequest, type BatchLoadResult, type BuiltDecisionModel, type BuiltInReadModelKind, type CachedSnapshot, type CatchUpConfig, type CatchUpConsumerStatus, type CatchUpStatus, type CatchUpSweptEvent, type CatchUpThread, type ChannelConfig, type ChannelHealth, type ChannelMeta, type CollectionMember, type ConnectionState, type ConnectionStateChangeCallback, type ConnectionStateChangedEvent, type ConnectionStateSnapshot, type ConsistencyCoordinate, type ConsistencyKey, type ConsistencyToken, type Database, type DbConfig, type DeadLetterAddedEvent, type DecisionContext, type DecisionModel, type DecisionTarget, type DegradedComponent, type DeliveryLookup, type DeliveryMembership, type DeliveryRow, type DocumentChangeEvent, type DocumentDecisionModel, type DocumentDeletedInfo, type DocumentGraphEdge, type DocumentIndexerDatabase, type DocumentModelSource, type DocumentModelSpec, type DocumentPurgeRow, type DocumentRelationship, type DocumentRevisions, type DocumentStreamKey, type DocumentViewDatabase, type EnqueuePurgeOptions, type Evaluation, type ExecuteMessage, type ExecutionJobPlan, type ExecutorStartedEvent, type ExecutorStoppedEvent, type FactorySpec, type FileModelSource, type GqlChannelConfig, type HeartbeatMessage, type HybridProjectionCoordinatorOptions, type HybridProjectionOptions, type ICatchUp, type ICatchUpConsumer, type IChannel, type IChannelFactory, type IConsistencyTracker, type IDeliveryTracking, type IDocumentGraph, type IDocumentIndexer, type IDocumentIntegrityService, type IDocumentModelLoader, type IDocumentModelRegistry, type IDocumentModelResolver, type IDocumentView, type IDriveClient, type IEventBus, type IJobAwaiter, type IJobExecutor, type IJobExecutorManager, type IJobTracker, type IKeyframeStore, type ILiveReadModelCoordinator, type IMailbox, type IOperationIndex, type IOperationStore, type IPeerAgreement, type IPollTimer, type IProcessor, type IProcessorHostModuleBase, type IProcessorManager, type IProjectionTransport, type IPurgeRefusalRecorder, type IQueue, type IReactor, type IReactorClient, type IReactorProcessorHostModuleBase, type IReactorSubscriptionManager, type IReadGate, type IReadModel, type IReadModelCoordinator, type IRelationalDb, type ISettledWatermark, type IStreamStateReader, type ISubscriptionErrorHandler, type ISyncCursorStorage, type ISyncHoldStorage, type ISyncManager, type ISyncPurgeRefusalStorage, type ISyncReceivedMarkerStorage, type ISyncRemoteStorage, type ISyncStatusTracker, type IWriteCache, SimpleJobExecutor as InMemoryJobExecutor, type InProcessReactorClientModule, type InProcessReactorModule, type InProcessSyncModule, type InitMessage, type InsertableDocumentSnapshot, type Job, type JobAvailableEvent, type JobCompletedEvent, type JobExecutorConfig, type JobExecutorFactory, type JobFailedEvent, type JobInfo, type JobKind, type JobPendingEvent, type JobReadReadyEvent, type JobResult, type JobResultSummary, type JobRunningEvent, type JobStartedEvent, type JobWriteReadyEvent, type JobWriteReadyPayload, type JwtHandler, type KeyframeSnapshot, type KeyframeValidationIssue, type LoadJobPlan, type LoadModelMessage, type LocalPeer, type LogMessage, type MetricsMessage, type ModelLoadFailedMessage, type ModelLoadedEvent, type ModelLoadedMessage, type ModelManifestEntry, type ModuleRef, type OperationBatch, type OperationContext, type OperationFilter, type OperationIndexEntry, type OperationTable, type OperationWithContext, type OutOfOrderPair, PURGE_DOCUMENT, type PackageModelSource, type PagedResults, type PagingOptions, type ParentMessage, type ParsedDriveUrl, type ParsedPaging, type ParsedSnapshot, type PeerAgreementBasis, type PendingDelivery, type PolledMarkerRefusal, type PoolInstrumentation, type PoolStats, type ProbeReading, type ProcessorApp, type ProcessorFactory, type ProcessorFactoryBuilder, type ProcessorFilter, type ProcessorRecord, type ProcessorStatus, type Projection, type ProjectionShardBuilderConfig, type ProjectionShardHooks, type ProjectionShardManagerConfig, type ProjectionWorkerFactory, type ProtocolSelection, type PurgeDocumentAction, type PurgeDocumentActionInput, type PurgeFence, type PurgeJobOptions, type PurgeLockMode, type PurgeLookup, type PurgeMarkerContext, type PurgeMarkerOperation, type PurgeRefusalRecord, type PurgeRemovedRows, type PurgeStream, type ReactorClientModule, type ReactorFeatureFlags, type ReactorFeatures, type ReactorHostModuleBaseOptions, type JobFailedEvent$1 as ReactorJobFailedEvent, type ReactorModule, type ReactorReadModels, type ReadGateOptions, type ReadModelBatchCompletedEvent, type ReadModelCoordinatorFactory, type ReadModelCoordinatorFactoryDeps, type ReadModelFactory, type ReadModelFactoryDeps, type ReadModelIndexedEvent, type ReadModelIndexingConfig, type ReadModelIndexingStage, type ReadModelRegistrationStage, type ReadModelStage, type ReadyMessage, type RebuildResult, type ReceivedMarkerRecord, type RegisteredDecisionModel, RelationalDbProcessor, type Remote, type RemoteCursor, type RemoteFilter, type RemoteMeta, type RemoteOptions, type RemotePeer, type RemoteRecord, type RemoteStatus, type ResultMessage, type SanitizedArg, type SearchFilter, type ShutdownMessage, type ShutdownStatus, type SignatureRefusalCode, type SignatureRefusedEvent, type SignatureScheme, type SignatureTrustPolicy, type SignatureVerificationHandler, type SignatureVerificationMode, type SignerConfig, type SnapshotFunctions, type SnapshotValidationIssue, type Database$1 as StorageDatabase, type StreamOrderIssue, type StreamQuery, type SubjectScopePredicate, type SubmittedActionResult, type SubscriptionErrorContext, type SweepBlockedAt, type SweepResult, type SyncEnvelope, type SyncEnvelopeType, type SyncFailedEvent, type SyncHeldEvent, type SyncHold, type SyncHoldRecord, type SyncModule, type SyncOperationErrorType, type SyncPendingEvent, type SyncPurgeRefusedEvent, type SyncReleasedEvent, type SyncStatusChangeCallback, type SyncSucceededEvent, type TrackedProcessor, type Unsubscribe, type UnsupportedStoredDocuments, type ValidationResult, type VerificationTarget, type ViewFilter, type WatermarkProbe, type WatermarkStatus, type ErrorInfo as WorkerErrorInfo, type WorkerMessage, type WorkerPoolConfig, type WorkerPoolOptions, type WriteCacheConfig, createRelationalDb, documentActions, isPurgeMarker };
8632
9121
  export {};
8633
9122
  //# sourceMappingURL=index.d.ts.map