@powerhousedao/reactor 6.2.2-dev.4 → 6.2.2-dev.40
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/{build-worker-executor--nhFRF47.js → build-worker-executor-CAEZD_yJ.js} +2 -2
- package/dist/{build-worker-executor--nhFRF47.js.map → build-worker-executor-CAEZD_yJ.js.map} +1 -1
- package/dist/{document-indexer-FGJmRAdX.js → document-indexer-C0GB0b8Q.js} +20 -7
- package/dist/document-indexer-C0GB0b8Q.js.map +1 -0
- package/dist/{drive-container-types-DpJp2AmE.js → drive-container-types-BJCKXJwH.js} +1498 -206
- package/dist/drive-container-types-BJCKXJwH.js.map +1 -0
- package/dist/entry.js +3 -2
- package/dist/entry.js.map +1 -1
- package/dist/index.d.ts +2045 -1637
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +319 -66
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +4 -4
- package/dist/projection-entry.js.map +1 -1
- package/dist/{worker-handle-B1w03nRA.js → worker-handle-CrERzl8s.js} +3 -2
- package/dist/worker-handle-CrERzl8s.js.map +1 -0
- package/dist/{worker-DBJOv8Gp.js → worker-jEJW6_j7.js} +2 -2
- package/dist/{worker-DBJOv8Gp.js.map → worker-jEJW6_j7.js.map} +1 -1
- package/package.json +5 -4
- package/dist/document-indexer-FGJmRAdX.js.map +0 -1
- package/dist/drive-container-types-DpJp2AmE.js.map +0 -1
- package/dist/worker-handle-B1w03nRA.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Action, CreateDocumentActionInput, DocumentModelModule, ISigner, Operation, OperationContext, OperationWithContext, OperationWithContext as OperationWithContext$1, PHDocument, PHDocumentState, SignatureVerificationHandler, UpgradeDocumentActionInput, UpgradeManifest, UpgradeReducer, UpgradeTransition, actions as documentActions } from "@powerhousedao/shared/document-model";
|
|
1
|
+
import { Action, AuthRequest, AuthSubject, CreateDocumentActionInput, DocumentModelModule, ISigner, Operation, OperationContext, OperationWithContext, OperationWithContext as OperationWithContext$1, PHAuthState, PHDocument, PHDocumentState, SignatureVerificationHandler, UpgradeDocumentActionInput, UpgradeManifest, UpgradeReducer, UpgradeTransition, actions as documentActions } 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
4
|
import * as kysely from "kysely";
|
|
@@ -69,6 +69,17 @@ declare enum JobQueueState {
|
|
|
69
69
|
RUNNING = 3,
|
|
70
70
|
RESOLVED = 4
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* How a retry is accounted against the job's retry limit.
|
|
74
|
+
* - `CountAgainstLimit` (default): a fault; the job eventually exhausts its
|
|
75
|
+
* retries and fails terminally.
|
|
76
|
+
* - `ExemptFromLimit`: not a fault, so the attempt is not charged to the job.
|
|
77
|
+
* Used for concurrency conflicts, where the retry does new work.
|
|
78
|
+
*/
|
|
79
|
+
declare enum RetryAccounting {
|
|
80
|
+
CountAgainstLimit = "count-against-limit",
|
|
81
|
+
ExemptFromLimit = "exempt-from-limit"
|
|
82
|
+
}
|
|
72
83
|
/**
|
|
73
84
|
* Interface for a job execution handle
|
|
74
85
|
*/
|
|
@@ -127,9 +138,14 @@ type JobAvailableEvent = {
|
|
|
127
138
|
//#endregion
|
|
128
139
|
//#region src/shared/types.d.ts
|
|
129
140
|
/**
|
|
130
|
-
* Information about an error including message and stack trace.
|
|
141
|
+
* Information about an error including its name, message and stack trace.
|
|
142
|
+
*
|
|
143
|
+
* The name is what survives the crossing out of the executor: a consumer that
|
|
144
|
+
* has to tell a terminal failure from a retryable one, or classify a dead
|
|
145
|
+
* letter, only ever sees this record rather than the thrown error.
|
|
131
146
|
*/
|
|
132
147
|
type ErrorInfo$1 = {
|
|
148
|
+
name: string;
|
|
133
149
|
message: string;
|
|
134
150
|
stack: string;
|
|
135
151
|
};
|
|
@@ -230,6 +246,11 @@ type ViewFilter = {
|
|
|
230
246
|
branch?: string;
|
|
231
247
|
scopes?: string[];
|
|
232
248
|
revision?: number;
|
|
249
|
+
/**
|
|
250
|
+
* Read subject for the IReactorClient read gate; defaults to the client's
|
|
251
|
+
* signer. Set per request when serving many principals. Ignored by IReactor.
|
|
252
|
+
*/
|
|
253
|
+
subject?: AuthSubject;
|
|
233
254
|
};
|
|
234
255
|
/**
|
|
235
256
|
* Describes filter options for searching documents.
|
|
@@ -328,6 +349,16 @@ interface IReadModelCoordinator {
|
|
|
328
349
|
*/
|
|
329
350
|
getChainDepth(): number;
|
|
330
351
|
}
|
|
352
|
+
type ReadModelRegistrationStage = "pre_ready" | "post_ready";
|
|
353
|
+
/**
|
|
354
|
+
* Optional capability exposed by coordinators that support adding read models
|
|
355
|
+
* after construction. Custom and remote coordinators are not required to
|
|
356
|
+
* implement it.
|
|
357
|
+
*/
|
|
358
|
+
interface ILiveReadModelCoordinator extends IReadModelCoordinator {
|
|
359
|
+
addReadModel(readModel: IReadModel, stage: ReadModelRegistrationStage): void;
|
|
360
|
+
}
|
|
361
|
+
declare function supportsLiveReadModelRegistration(coordinator: IReadModelCoordinator): coordinator is ILiveReadModelCoordinator;
|
|
331
362
|
//#endregion
|
|
332
363
|
//#region src/sync/types.d.ts
|
|
333
364
|
declare enum ChannelScheme {
|
|
@@ -398,7 +429,13 @@ declare enum ChannelErrorSource {
|
|
|
398
429
|
Inbox = "inbox",
|
|
399
430
|
Outbox = "outbox"
|
|
400
431
|
}
|
|
401
|
-
type SyncOperationErrorType = "SIGNATURE_INVALID" | "HASH_MISMATCH" | "LIBRARY_ERROR" | "MISSING_OPERATIONS" | "EXCESSIVE_SHUFFLE" | "GRACEFUL_ABORT"
|
|
432
|
+
type SyncOperationErrorType = "SIGNATURE_INVALID" | "HASH_MISMATCH" | "LIBRARY_ERROR" | "MISSING_OPERATIONS" | "EXCESSIVE_SHUFFLE" | "GRACEFUL_ABORT"
|
|
433
|
+
/**
|
|
434
|
+
* An arriving auth operation did not exceed the local auth head. Exempt from
|
|
435
|
+
* quarantine, because reconciling the two policies needs the traffic a
|
|
436
|
+
* quarantine would stop.
|
|
437
|
+
*/
|
|
438
|
+
| "AUTH_TIMESTAMP_NOT_MONOTONIC" /** An arriving operation carried a timestamp that is not an ISO-8601 instant. */ | "INVALID_TIMESTAMP" /** No classification applies, including rows written before the field. */ | "UNCLASSIFIED";
|
|
402
439
|
type ChannelHealth = {
|
|
403
440
|
state: "idle" | "running" | "error";
|
|
404
441
|
lastSuccessUtcMs?: number;
|
|
@@ -491,6 +528,7 @@ type DeadLetterAddedEvent = {
|
|
|
491
528
|
remoteName: string;
|
|
492
529
|
documentId: string;
|
|
493
530
|
errorSource: ChannelErrorSource;
|
|
531
|
+
errorType: SyncOperationErrorType;
|
|
494
532
|
};
|
|
495
533
|
/**
|
|
496
534
|
* Status of a sync operation result.
|
|
@@ -537,6 +575,36 @@ declare class OptimisticLockError extends Error {
|
|
|
537
575
|
declare class RevisionMismatchError extends Error {
|
|
538
576
|
constructor(expected: number, actual: number);
|
|
539
577
|
}
|
|
578
|
+
/**
|
|
579
|
+
* One read-set stream and the highest operation index observed on it, or -1
|
|
580
|
+
* if it was observed empty.
|
|
581
|
+
*/
|
|
582
|
+
type AppendConditionStream = {
|
|
583
|
+
documentId: string;
|
|
584
|
+
scope: string;
|
|
585
|
+
branch: string;
|
|
586
|
+
revision: number;
|
|
587
|
+
};
|
|
588
|
+
/**
|
|
589
|
+
* A read-set enforced by {@link IOperationStore.apply}: the append fails if
|
|
590
|
+
* any stream has operations past its recorded revision.
|
|
591
|
+
*/
|
|
592
|
+
type AppendCondition = {
|
|
593
|
+
streams: AppendConditionStream[];
|
|
594
|
+
};
|
|
595
|
+
/** Error history keeps messages, not classes, so failures match by prefix. */
|
|
596
|
+
declare const APPEND_CONDITION_FAILED_PREFIX = "Append condition failed: ";
|
|
597
|
+
/**
|
|
598
|
+
* A read-set stream grew before the append committed. A concurrency
|
|
599
|
+
* conflict, not a fault: the caller retries against the new stream heads.
|
|
600
|
+
*/
|
|
601
|
+
declare class AppendConditionFailedError extends Error {
|
|
602
|
+
readonly condition: AppendCondition;
|
|
603
|
+
constructor(condition: AppendCondition);
|
|
604
|
+
static isError(error: unknown): error is AppendConditionFailedError;
|
|
605
|
+
/** True when a recorded error message is an append-condition failure. */
|
|
606
|
+
static isFailureMessage(message: string): boolean;
|
|
607
|
+
}
|
|
540
608
|
/**
|
|
541
609
|
* A write transaction passed to {@link IOperationStore.apply}. Accumulates
|
|
542
610
|
* operations that are committed atomically when the callback returns.
|
|
@@ -550,7 +618,7 @@ interface AtomicTxn {
|
|
|
550
618
|
* revision field and lastModified timestamp.
|
|
551
619
|
*/
|
|
552
620
|
type DocumentRevisions = {
|
|
553
|
-
/** Map of scope to operation index for that scope */revision: Record<string, number>; /**
|
|
621
|
+
/** Map of scope to operation index for that scope */revision: Record<string, number>; /** The largest operation timestamp in the document, across every scope. */
|
|
554
622
|
latestTimestamp: string;
|
|
555
623
|
};
|
|
556
624
|
/**
|
|
@@ -571,6 +639,12 @@ interface IOperationStore {
|
|
|
571
639
|
* returned instead of throwing. If no matching stored row is found, the
|
|
572
640
|
* original error is propagated unchanged.
|
|
573
641
|
*
|
|
642
|
+
* With an {@link AppendCondition}, the append additionally fails with
|
|
643
|
+
* {@link AppendConditionFailedError} — writing nothing — if any read-set
|
|
644
|
+
* stream has operations past its recorded revision. The written and
|
|
645
|
+
* read-set streams are advisory-locked in sorted key order, so concurrent
|
|
646
|
+
* conditional appends on overlapping streams serialize.
|
|
647
|
+
*
|
|
574
648
|
* @param documentId - The document id
|
|
575
649
|
* @param documentType - The document type identifier
|
|
576
650
|
* @param scope - The operation scope (e.g. "global", "local")
|
|
@@ -578,9 +652,10 @@ interface IOperationStore {
|
|
|
578
652
|
* @param revision - Expected current revision (optimistic lock)
|
|
579
653
|
* @param fn - Callback that stages operations via {@link AtomicTxn}
|
|
580
654
|
* @param signal - Optional abort signal to cancel the request
|
|
655
|
+
* @param condition - Optional read-set to enforce at write time
|
|
581
656
|
* @returns The stored operations; empty array when no operations were staged
|
|
582
657
|
*/
|
|
583
|
-
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal): Promise<Operation[]>;
|
|
658
|
+
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal, condition?: AppendCondition): Promise<Operation[]>;
|
|
584
659
|
/**
|
|
585
660
|
* Returns operations for a document/scope/branch whose index is greater
|
|
586
661
|
* than the given revision.
|
|
@@ -627,6 +702,16 @@ interface IOperationStore {
|
|
|
627
702
|
* @returns Object containing revision map and latest timestamp
|
|
628
703
|
*/
|
|
629
704
|
getRevisions(documentId: string, branch: string, signal?: AbortSignal): Promise<DocumentRevisions>;
|
|
705
|
+
/**
|
|
706
|
+
* The largest operation timestamp in one stream, or undefined when it is empty.
|
|
707
|
+
* Distinct from {@link DocumentRevisions.latestTimestamp}, which maxes over
|
|
708
|
+
* every scope.
|
|
709
|
+
*
|
|
710
|
+
* Must be a real maximum, not the last-indexed operation's timestamp: a
|
|
711
|
+
* re-evaluation pass re-appends at a fresh index while keeping the original
|
|
712
|
+
* timestamp, so a later timestamp can sit behind the last row.
|
|
713
|
+
*/
|
|
714
|
+
getStreamLatestTimestamp(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<string | undefined>;
|
|
630
715
|
}
|
|
631
716
|
/**
|
|
632
717
|
* Stores periodic document snapshots (keyframes) so that document state
|
|
@@ -1045,7 +1130,8 @@ type DeadLetterRecord = {
|
|
|
1045
1130
|
branch: string;
|
|
1046
1131
|
operations: OperationWithContext$1[];
|
|
1047
1132
|
errorSource: ChannelErrorSource;
|
|
1048
|
-
errorMessage: string;
|
|
1133
|
+
errorMessage: string; /** Why it failed, in the closed set sync classifies failures into. */
|
|
1134
|
+
errorType: SyncOperationErrorType;
|
|
1049
1135
|
};
|
|
1050
1136
|
/**
|
|
1051
1137
|
* Persists dead-lettered sync operations so they survive reactor restarts.
|
|
@@ -1152,6 +1238,51 @@ declare class DriveCollectionId {
|
|
|
1152
1238
|
equals(other: DriveCollectionId): boolean;
|
|
1153
1239
|
}
|
|
1154
1240
|
//#endregion
|
|
1241
|
+
//#region src/cache/write-cache-types.d.ts
|
|
1242
|
+
/**
|
|
1243
|
+
* Configuration options for the write cache
|
|
1244
|
+
*/
|
|
1245
|
+
type WriteCacheConfig = {
|
|
1246
|
+
/** Maximum number of document streams to cache (LRU eviction). Default: 1000 */maxDocuments: number; /** Number of snapshots to keep in each document's ring buffer. Default: 10 */
|
|
1247
|
+
ringBufferSize: number; /** Persist a keyframe snapshot every N revisions. Default: 10 */
|
|
1248
|
+
keyframeInterval: number;
|
|
1249
|
+
};
|
|
1250
|
+
/**
|
|
1251
|
+
* Unique identifier for a document stream
|
|
1252
|
+
*/
|
|
1253
|
+
type DocumentStreamKey = {
|
|
1254
|
+
/** Document identifier */documentId: string; /** Operation scope */
|
|
1255
|
+
scope: string; /** Branch name */
|
|
1256
|
+
branch: string;
|
|
1257
|
+
};
|
|
1258
|
+
/**
|
|
1259
|
+
* Where a snapshot sits in its stream.
|
|
1260
|
+
*
|
|
1261
|
+
* - `Head`: the newest revision of the stream when it was stored. Only these
|
|
1262
|
+
* can answer a read that asks for the head.
|
|
1263
|
+
* - `Historical`: state at an earlier revision. Usable as a starting point to
|
|
1264
|
+
* replay forward from, and as an answer to a read for that same revision.
|
|
1265
|
+
*/
|
|
1266
|
+
declare enum SnapshotPosition {
|
|
1267
|
+
Head = "head",
|
|
1268
|
+
Historical = "historical"
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* A cached document snapshot at a specific revision
|
|
1272
|
+
*/
|
|
1273
|
+
type CachedSnapshot = {
|
|
1274
|
+
/** The revision number of this snapshot */revision: number; /** The document state at this revision */
|
|
1275
|
+
document: PHDocument; /** Where this snapshot sat in the stream when it was stored */
|
|
1276
|
+
position: SnapshotPosition;
|
|
1277
|
+
};
|
|
1278
|
+
/**
|
|
1279
|
+
* Serialized keyframe snapshot for K/V store persistence
|
|
1280
|
+
*/
|
|
1281
|
+
type KeyframeSnapshot = {
|
|
1282
|
+
/** The revision number of this keyframe */revision: number; /** Serialized document state */
|
|
1283
|
+
document: string;
|
|
1284
|
+
};
|
|
1285
|
+
//#endregion
|
|
1155
1286
|
//#region src/cache/write/interfaces.d.ts
|
|
1156
1287
|
/**
|
|
1157
1288
|
* IWriteCache is a write-side projection that optimizes document state retrieval
|
|
@@ -1166,7 +1297,8 @@ interface IWriteCache {
|
|
|
1166
1297
|
* @param documentId - The document identifier
|
|
1167
1298
|
* @param scope - Operation scope
|
|
1168
1299
|
* @param branch - Branch name
|
|
1169
|
-
* @param targetRevision -
|
|
1300
|
+
* @param targetRevision - Index of the last operation to apply, defaulting
|
|
1301
|
+
* to latest. An operation index, never `header.revision[scope]`.
|
|
1170
1302
|
* @param signal - Optional abort signal to cancel the operation
|
|
1171
1303
|
* @returns The complete document at the specified revision
|
|
1172
1304
|
*
|
|
@@ -1192,15 +1324,19 @@ interface IWriteCache {
|
|
|
1192
1324
|
* @param documentId - The document identifier
|
|
1193
1325
|
* @param scope - Operation scope
|
|
1194
1326
|
* @param branch - Branch name
|
|
1195
|
-
* @param revision -
|
|
1327
|
+
* @param revision - Index of the last operation this document reflects, so
|
|
1328
|
+
* `header.revision[scope]` is one greater. -1 for an empty scope.
|
|
1196
1329
|
* @param document - The document to cache
|
|
1330
|
+
* @param position - Whether `revision` is the stream's head. Nothing checks
|
|
1331
|
+
* it: claiming `Head` for an earlier revision makes a getState() with no
|
|
1332
|
+
* target return stale state.
|
|
1197
1333
|
*
|
|
1198
1334
|
* @example
|
|
1199
1335
|
* ```typescript
|
|
1200
|
-
* cache.putState(docId, 'global', 'main', 42, document);
|
|
1336
|
+
* cache.putState(docId, 'global', 'main', 42, document, SnapshotPosition.Head);
|
|
1201
1337
|
* ```
|
|
1202
1338
|
*/
|
|
1203
|
-
putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument): void;
|
|
1339
|
+
putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, position: SnapshotPosition): void;
|
|
1204
1340
|
/**
|
|
1205
1341
|
* Invalidates (removes) cached entries for a document stream.
|
|
1206
1342
|
*
|
|
@@ -1646,7 +1782,7 @@ interface IReactorClient {
|
|
|
1646
1782
|
* @param signal - Optional abort signal to cancel the request
|
|
1647
1783
|
* @returns The canonical document id
|
|
1648
1784
|
*/
|
|
1649
|
-
resolveIdOrSlug(identifier: string, signal?: AbortSignal): Promise<string>;
|
|
1785
|
+
resolveIdOrSlug(identifier: string, view?: ViewFilter, signal?: AbortSignal): Promise<string>;
|
|
1650
1786
|
/**
|
|
1651
1787
|
* Retrieves operations for a document.
|
|
1652
1788
|
*
|
|
@@ -1884,6 +2020,7 @@ declare class ReactorClient implements IReactorClient {
|
|
|
1884
2020
|
private documentView;
|
|
1885
2021
|
readonly drives: IDriveClient;
|
|
1886
2022
|
constructor(logger: ILogger, reactor: IReactor, signer: ISigner, subscriptionManager: IReactorSubscriptionManager, jobAwaiter: IJobAwaiter, documentIndexer: IDocumentIndexer, documentView: IDocumentView);
|
|
2023
|
+
private readSubject;
|
|
1887
2024
|
/**
|
|
1888
2025
|
* Retrieves a list of document model modules.
|
|
1889
2026
|
*/
|
|
@@ -1904,7 +2041,7 @@ declare class ReactorClient implements IReactorClient {
|
|
|
1904
2041
|
* same lookup as the data path. Resolves against the "main" branch. Throws if
|
|
1905
2042
|
* the identifier cannot be resolved or is ambiguous.
|
|
1906
2043
|
*/
|
|
1907
|
-
resolveIdOrSlug(identifier: string, signal?: AbortSignal): Promise<string>;
|
|
2044
|
+
resolveIdOrSlug(identifier: string, view?: ViewFilter, signal?: AbortSignal): Promise<string>;
|
|
1908
2045
|
/**
|
|
1909
2046
|
* Retrieves operations for a document
|
|
1910
2047
|
*/
|
|
@@ -1995,244 +2132,400 @@ declare class ReactorClient implements IReactorClient {
|
|
|
1995
2132
|
private removeAllIncomingRelationships;
|
|
1996
2133
|
}
|
|
1997
2134
|
//#endregion
|
|
1998
|
-
//#region src/
|
|
2135
|
+
//#region src/cache/collection-membership-cache.d.ts
|
|
2136
|
+
interface ICollectionMembershipCache {
|
|
2137
|
+
getCollectionsForDocuments(documentIds: string[]): Promise<Record<string, string[]>>;
|
|
2138
|
+
invalidate(documentId: string): void;
|
|
2139
|
+
}
|
|
2140
|
+
//#endregion
|
|
2141
|
+
//#region src/cache/document-meta-cache-types.d.ts
|
|
1999
2142
|
/**
|
|
2000
|
-
*
|
|
2143
|
+
* Cached document metadata from the "document" scope.
|
|
2144
|
+
*
|
|
2145
|
+
* This lightweight structure holds essential document information needed by
|
|
2146
|
+
* the job executor without fetching full scope state. It provides an explicit
|
|
2147
|
+
* cross-scope contract for accessing document scope metadata.
|
|
2001
2148
|
*/
|
|
2002
|
-
type
|
|
2003
|
-
/** The job that was executed */job: Job; /** Whether the job executed successfully */
|
|
2004
|
-
success: boolean; /** Error if the job failed */
|
|
2005
|
-
error?: Error; /** The operations generated from the actions (if successful) */
|
|
2006
|
-
operations?: Operation[];
|
|
2149
|
+
type CachedDocumentMeta = {
|
|
2007
2150
|
/**
|
|
2008
|
-
*
|
|
2009
|
-
*
|
|
2151
|
+
* The full PHDocumentState from document.state.document.
|
|
2152
|
+
* Contains version, hash, isDeleted, deletedAtUtcIso, etc.
|
|
2010
2153
|
*/
|
|
2011
|
-
|
|
2012
|
-
completedAt?: string; /** Duration of job execution in milliseconds */
|
|
2013
|
-
duration?: number; /** Any additional metadata from the execution */
|
|
2014
|
-
metadata?: Record<string, any>;
|
|
2015
|
-
};
|
|
2016
|
-
/**
|
|
2017
|
-
* Configuration options for the job executor
|
|
2018
|
-
*/
|
|
2019
|
-
type JobExecutorConfig = {
|
|
2020
|
-
/** Maximum number of conflicting operations to skip when reshuffling. */maxSkipThreshold?: number; /** Maximum number of concurrent jobs to execute */
|
|
2021
|
-
maxConcurrency?: number; /** Maximum time in milliseconds a job can run before being considered timed out */
|
|
2022
|
-
jobTimeoutMs?: number; /** Base delay in milliseconds for exponential backoff retries */
|
|
2023
|
-
retryBaseDelayMs?: number; /** Maximum delay in milliseconds for exponential backoff retries */
|
|
2024
|
-
retryMaxDelayMs?: number;
|
|
2025
|
-
/** Maximum elapsed milliseconds before yielding to the main thread between actions.
|
|
2026
|
-
* Keeps the UI responsive when processing large batches. */
|
|
2027
|
-
yieldDeadlineMs?: number;
|
|
2028
|
-
};
|
|
2029
|
-
/**
|
|
2030
|
-
* Event types for the job executor
|
|
2031
|
-
*/
|
|
2032
|
-
declare const JobExecutorEventTypes: {
|
|
2033
|
-
readonly JOB_STARTED: 20000;
|
|
2034
|
-
readonly JOB_COMPLETED: 20001;
|
|
2035
|
-
readonly JOB_FAILED: 20002;
|
|
2036
|
-
readonly EXECUTOR_STARTED: 20003;
|
|
2037
|
-
readonly EXECUTOR_STOPPED: 20004;
|
|
2038
|
-
};
|
|
2039
|
-
/**
|
|
2040
|
-
* Event data for job execution events
|
|
2041
|
-
*/
|
|
2042
|
-
type JobStartedEvent = {
|
|
2043
|
-
job: Job;
|
|
2044
|
-
startedAt: string;
|
|
2154
|
+
state: PHDocumentState;
|
|
2045
2155
|
/**
|
|
2046
|
-
*
|
|
2047
|
-
* the thread-worker id (e.g. "reactor-worker-3"); for the in-process simple
|
|
2048
|
-
* manager it is "in-process-<index>". Optional for backwards compatibility
|
|
2049
|
-
* with consumers built before the field was added.
|
|
2156
|
+
* The document type (from header), cached for convenience.
|
|
2050
2157
|
*/
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
};
|
|
2058
|
-
type JobFailedEvent = {
|
|
2059
|
-
job: Job;
|
|
2060
|
-
error: string;
|
|
2061
|
-
willRetry: boolean;
|
|
2062
|
-
retryCount: number; /** See {@link JobStartedEvent.workerId}. */
|
|
2063
|
-
workerId?: string;
|
|
2064
|
-
};
|
|
2065
|
-
type ExecutorStartedEvent = {
|
|
2066
|
-
config: JobExecutorConfig;
|
|
2067
|
-
startedAt: string;
|
|
2068
|
-
};
|
|
2069
|
-
type ExecutorStoppedEvent = {
|
|
2070
|
-
stoppedAt: string;
|
|
2071
|
-
graceful: boolean;
|
|
2072
|
-
};
|
|
2073
|
-
/**
|
|
2074
|
-
* Status information for the job executor manager
|
|
2075
|
-
*/
|
|
2076
|
-
type ExecutorManagerStatus = {
|
|
2077
|
-
/** Whether the manager is currently running */isRunning: boolean; /** Number of executor instances managed */
|
|
2078
|
-
numExecutors: number; /** Number of jobs currently being processed */
|
|
2079
|
-
activeJobs: number; /** Total number of jobs processed since start */
|
|
2080
|
-
totalJobsProcessed: number;
|
|
2081
|
-
};
|
|
2082
|
-
//#endregion
|
|
2083
|
-
//#region src/executor/worker/protocol.d.ts
|
|
2084
|
-
/**
|
|
2085
|
-
* A JSON-clonable value safe to send across the worker IPC boundary.
|
|
2086
|
-
*
|
|
2087
|
-
* The shape mirrors the structured-clone subset used by the parent's
|
|
2088
|
-
* sanitizer: primitives, arrays, plain objects, plus the explicit
|
|
2089
|
-
* {@link ErrorInfo} shape for marshalled Errors.
|
|
2090
|
-
*
|
|
2091
|
-
* @see Wire Protocol Reference wiki page
|
|
2092
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2093
|
-
*/
|
|
2094
|
-
type SanitizedArg = null | boolean | number | string | ErrorInfo | SanitizedArg[] | {
|
|
2095
|
-
[key: string]: SanitizedArg;
|
|
2096
|
-
};
|
|
2097
|
-
/**
|
|
2098
|
-
* Structured representation of an Error for IPC transport.
|
|
2099
|
-
*
|
|
2100
|
-
* Class instances cannot be structured-cloned across worker boundaries,
|
|
2101
|
-
* so Errors are flattened into this shape on the worker side and
|
|
2102
|
-
* reconstructed on the parent side.
|
|
2103
|
-
*
|
|
2104
|
-
* @see Wire Protocol Reference wiki page
|
|
2105
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2106
|
-
*/
|
|
2107
|
-
type ErrorInfo = {
|
|
2108
|
-
name: string;
|
|
2109
|
-
message: string;
|
|
2110
|
-
stack?: string;
|
|
2111
|
-
cause?: ErrorInfo;
|
|
2112
|
-
};
|
|
2113
|
-
/**
|
|
2114
|
-
* Reference to a module that the worker should `import()` at runtime,
|
|
2115
|
-
* along with the named export to pluck out as the factory.
|
|
2116
|
-
*
|
|
2117
|
-
* Exactly one of `packageName` or `filePath` is provided.
|
|
2118
|
-
*
|
|
2119
|
-
* @see Wire Protocol Reference wiki page
|
|
2120
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2121
|
-
*/
|
|
2122
|
-
type ModuleRef = {
|
|
2123
|
-
/** Bare-specifier package name (resolved by the worker's module loader). */packageName: string; /** Named export within the module to invoke as the factory. */
|
|
2124
|
-
exportName: string;
|
|
2125
|
-
} | {
|
|
2126
|
-
/** Absolute or worker-resolvable file path to import. */filePath: string; /** Named export within the module to invoke as the factory. */
|
|
2127
|
-
exportName: string;
|
|
2128
|
-
};
|
|
2129
|
-
/**
|
|
2130
|
-
* Factory specification shared by the signature verifier and document
|
|
2131
|
-
* model spec channels. The worker imports `module.exportName` and invokes
|
|
2132
|
-
* it with `initArgs` to obtain the actual instance.
|
|
2133
|
-
*
|
|
2134
|
-
* `initArgs` must be JSON-clonable.
|
|
2135
|
-
*
|
|
2136
|
-
* @see Wire Protocol Reference wiki page
|
|
2137
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2138
|
-
*/
|
|
2139
|
-
type FactorySpec = {
|
|
2140
|
-
module: ModuleRef;
|
|
2141
|
-
initArgs?: SanitizedArg;
|
|
2158
|
+
documentType: string;
|
|
2159
|
+
/**
|
|
2160
|
+
* The revision of the document scope when this metadata was captured.
|
|
2161
|
+
* Used for cache invalidation and consistency checks.
|
|
2162
|
+
*/
|
|
2163
|
+
documentScopeRevision: number;
|
|
2142
2164
|
};
|
|
2143
2165
|
/**
|
|
2144
|
-
*
|
|
2145
|
-
*
|
|
2146
|
-
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2147
|
-
* sites read intent-fully.
|
|
2148
|
-
*
|
|
2149
|
-
* @see Wire Protocol Reference wiki page
|
|
2150
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2151
|
-
*/
|
|
2152
|
-
type SignatureVerifierSpec = FactorySpec;
|
|
2153
|
-
/**
|
|
2154
|
-
* Factory spec for a document model module the worker should instantiate.
|
|
2155
|
-
*
|
|
2156
|
-
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2157
|
-
* sites read intent-fully.
|
|
2166
|
+
* Interface for the document metadata cache.
|
|
2158
2167
|
*
|
|
2159
|
-
*
|
|
2160
|
-
*
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
/**
|
|
2164
|
-
* One entry in the document model manifest the worker materializes on
|
|
2165
|
-
* startup (or extends lazily via `load-model`).
|
|
2168
|
+
* This cache provides an explicit cross-scope contract for accessing document
|
|
2169
|
+
* scope metadata. It solves the problem where job execution in one scope (e.g.,
|
|
2170
|
+
* "global") needs access to document scope state (version, isDeleted, etc.)
|
|
2171
|
+
* which may be stale in scope-specific caches or keyframes.
|
|
2166
2172
|
*
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
2173
|
+
* The cache supports:
|
|
2174
|
+
* - Latest metadata retrieval with LRU caching
|
|
2175
|
+
* - Historical metadata reconstruction for reshuffling scenarios
|
|
2176
|
+
* - Eager updates after document scope operations
|
|
2169
2177
|
*/
|
|
2170
|
-
|
|
2171
|
-
/** Document type identifier (e.g. "ph/account"). */documentType: string; /** Document model version this entry registers. */
|
|
2172
|
-
version: string; /** Factory spec the worker imports and invokes to obtain the model. */
|
|
2173
|
-
spec: DocumentModelSpec;
|
|
2174
|
-
};
|
|
2175
|
-
/**
|
|
2176
|
-
* JSON-clonable Postgres connection info passed to the worker so it can
|
|
2177
|
-
* open its own pool. Storage-specific wiring may extend this shape in
|
|
2178
|
-
* later phases.
|
|
2179
|
-
*
|
|
2180
|
-
* @see Wire Protocol Reference wiki page
|
|
2181
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2182
|
-
*/
|
|
2183
|
-
type DbConfig = {
|
|
2184
|
-
host: string;
|
|
2185
|
-
port: number;
|
|
2186
|
-
database: string;
|
|
2187
|
-
user: string;
|
|
2188
|
-
password: string;
|
|
2189
|
-
ssl?: boolean;
|
|
2190
|
-
applicationName?: string;
|
|
2191
|
-
poolSize?: number;
|
|
2178
|
+
interface IDocumentMetaCache {
|
|
2192
2179
|
/**
|
|
2193
|
-
*
|
|
2194
|
-
*
|
|
2195
|
-
*
|
|
2180
|
+
* Retrieves the LATEST document metadata from cache or rebuilds from operations.
|
|
2181
|
+
*
|
|
2182
|
+
* On cache miss, fetches all document scope operations and reconstructs the
|
|
2183
|
+
* current PHDocumentState by applying UPGRADE_DOCUMENT and DELETE_DOCUMENT
|
|
2184
|
+
* operations.
|
|
2185
|
+
*
|
|
2186
|
+
* @param documentId - The document identifier
|
|
2187
|
+
* @param branch - Branch name
|
|
2188
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2189
|
+
* @returns The cached or rebuilt document metadata
|
|
2190
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2191
|
+
* @throws {Error} If document not found (no CREATE_DOCUMENT operation)
|
|
2196
2192
|
*/
|
|
2197
|
-
|
|
2193
|
+
getDocumentMeta(documentId: string, branch: string, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
2198
2194
|
/**
|
|
2199
|
-
*
|
|
2200
|
-
*
|
|
2195
|
+
* Rebuilds document metadata at a SPECIFIC revision (always rebuilds, no caching).
|
|
2196
|
+
*
|
|
2197
|
+
* Used during reshuffling when operations need to be inserted at a previous
|
|
2198
|
+
* revision and we need the document scope state as of that point in time.
|
|
2199
|
+
*
|
|
2200
|
+
* @param documentId - The document identifier
|
|
2201
|
+
* @param branch - Branch name
|
|
2202
|
+
* @param targetRevision - The document scope revision to reconstruct up to
|
|
2203
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2204
|
+
* @returns Document metadata as of the target revision
|
|
2205
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2206
|
+
* @throws {Error} If document not found
|
|
2201
2207
|
*/
|
|
2202
|
-
|
|
2203
|
-
|
|
2208
|
+
rebuildAtRevision(documentId: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
2209
|
+
/**
|
|
2210
|
+
* Eagerly updates cached metadata after document scope operations.
|
|
2211
|
+
*
|
|
2212
|
+
* Called by the job executor after CREATE_DOCUMENT, UPGRADE_DOCUMENT, or
|
|
2213
|
+
* DELETE_DOCUMENT operations to keep the cache current.
|
|
2214
|
+
*
|
|
2215
|
+
* @param documentId - The document identifier
|
|
2216
|
+
* @param branch - Branch name
|
|
2217
|
+
* @param meta - The new metadata to cache
|
|
2218
|
+
*/
|
|
2219
|
+
putDocumentMeta(documentId: string, branch: string, meta: CachedDocumentMeta): void;
|
|
2220
|
+
/**
|
|
2221
|
+
* Invalidates cached document metadata.
|
|
2222
|
+
*
|
|
2223
|
+
* Call before reshuffling operations that modify the document scope, or
|
|
2224
|
+
* when document state may have changed externally.
|
|
2225
|
+
*
|
|
2226
|
+
* @param documentId - The document identifier
|
|
2227
|
+
* @param branch - Optional branch to narrow invalidation (if omitted, all branches)
|
|
2228
|
+
* @returns Number of entries invalidated
|
|
2229
|
+
*/
|
|
2230
|
+
invalidate(documentId: string, branch?: string): number;
|
|
2231
|
+
/**
|
|
2232
|
+
* Clears all cached document metadata.
|
|
2233
|
+
*/
|
|
2234
|
+
clear(): void;
|
|
2235
|
+
/**
|
|
2236
|
+
* Performs startup initialization.
|
|
2237
|
+
*/
|
|
2238
|
+
startup(): Promise<void>;
|
|
2239
|
+
/**
|
|
2240
|
+
* Performs graceful shutdown.
|
|
2241
|
+
*/
|
|
2242
|
+
shutdown(): Promise<void>;
|
|
2243
|
+
}
|
|
2244
|
+
//#endregion
|
|
2245
|
+
//#region src/storage/kysely/types.d.ts
|
|
2246
|
+
interface OperationTable {
|
|
2247
|
+
id: Generated<number>;
|
|
2248
|
+
jobId: string;
|
|
2249
|
+
opId: string;
|
|
2250
|
+
prevOpId: string;
|
|
2251
|
+
writeTimestampUtcMs: Generated<Date>;
|
|
2252
|
+
documentId: string;
|
|
2253
|
+
documentType: string;
|
|
2254
|
+
scope: string;
|
|
2255
|
+
branch: string;
|
|
2256
|
+
timestampUtcMs: Date;
|
|
2257
|
+
index: number;
|
|
2258
|
+
action: unknown;
|
|
2259
|
+
skip: number;
|
|
2260
|
+
error?: string | null;
|
|
2261
|
+
deniedReason?: string | null;
|
|
2262
|
+
hash: string;
|
|
2263
|
+
}
|
|
2264
|
+
interface KeyframeTable {
|
|
2265
|
+
id: Generated<number>;
|
|
2266
|
+
documentId: string;
|
|
2267
|
+
documentType: string;
|
|
2268
|
+
scope: string;
|
|
2269
|
+
branch: string;
|
|
2270
|
+
revision: number;
|
|
2271
|
+
document: unknown;
|
|
2272
|
+
createdAt: Generated<Date>;
|
|
2273
|
+
}
|
|
2274
|
+
interface DocumentCollectionTable {
|
|
2275
|
+
documentId: string;
|
|
2276
|
+
collectionId: string;
|
|
2277
|
+
joinedOrdinal: bigint;
|
|
2278
|
+
leftOrdinal: bigint | null;
|
|
2279
|
+
}
|
|
2280
|
+
interface OperationIndexOperationTable {
|
|
2281
|
+
ordinal: Generated<number>;
|
|
2282
|
+
opId: string;
|
|
2283
|
+
documentId: string;
|
|
2284
|
+
documentType: string;
|
|
2285
|
+
scope: string;
|
|
2286
|
+
branch: string;
|
|
2287
|
+
timestampUtcMs: string;
|
|
2288
|
+
writeTimestampUtcMs: Generated<Date>;
|
|
2289
|
+
index: number;
|
|
2290
|
+
skip: number;
|
|
2291
|
+
hash: string;
|
|
2292
|
+
action: unknown;
|
|
2293
|
+
deniedReason?: string | null;
|
|
2294
|
+
sourceRemote: Generated<string>;
|
|
2295
|
+
}
|
|
2296
|
+
interface SyncRemoteTable {
|
|
2297
|
+
name: string;
|
|
2298
|
+
collection_id: string;
|
|
2299
|
+
channel_type: string;
|
|
2300
|
+
channel_id: string;
|
|
2301
|
+
remote_name: string;
|
|
2302
|
+
channel_parameters: unknown;
|
|
2303
|
+
filter_document_ids: unknown;
|
|
2304
|
+
filter_scopes: unknown;
|
|
2305
|
+
filter_branch: string;
|
|
2306
|
+
push_state: string;
|
|
2307
|
+
push_last_success_utc_ms: string | null;
|
|
2308
|
+
push_last_failure_utc_ms: string | null;
|
|
2309
|
+
push_failure_count: number;
|
|
2310
|
+
pull_state: string;
|
|
2311
|
+
pull_last_success_utc_ms: string | null;
|
|
2312
|
+
pull_last_failure_utc_ms: string | null;
|
|
2313
|
+
pull_failure_count: number;
|
|
2314
|
+
created_at: Generated<Date>;
|
|
2315
|
+
updated_at: Generated<Date>;
|
|
2316
|
+
}
|
|
2317
|
+
interface SyncCursorTable {
|
|
2318
|
+
remote_name: string;
|
|
2319
|
+
cursor_type: string;
|
|
2320
|
+
cursor_ordinal: bigint;
|
|
2321
|
+
last_synced_at_utc_ms: string | null;
|
|
2322
|
+
updated_at: Generated<Date>;
|
|
2323
|
+
}
|
|
2204
2324
|
/**
|
|
2205
|
-
*
|
|
2325
|
+
* Kysely table definition for the `sync_dead_letters` table.
|
|
2326
|
+
*/
|
|
2327
|
+
interface SyncDeadLetterTable {
|
|
2328
|
+
ordinal: Generated<number>;
|
|
2329
|
+
id: string;
|
|
2330
|
+
job_id: string;
|
|
2331
|
+
job_dependencies: unknown;
|
|
2332
|
+
remote_name: string;
|
|
2333
|
+
document_id: string;
|
|
2334
|
+
scopes: unknown;
|
|
2335
|
+
branch: string;
|
|
2336
|
+
operations: unknown;
|
|
2337
|
+
error_source: string;
|
|
2338
|
+
error_message: string;
|
|
2339
|
+
error_type: Generated<string>;
|
|
2340
|
+
created_at: Generated<Date>;
|
|
2341
|
+
}
|
|
2342
|
+
interface Database$1 {
|
|
2343
|
+
Operation: OperationTable;
|
|
2344
|
+
Keyframe: KeyframeTable;
|
|
2345
|
+
document_collections: DocumentCollectionTable;
|
|
2346
|
+
operation_index_operations: OperationIndexOperationTable;
|
|
2347
|
+
sync_remotes: SyncRemoteTable;
|
|
2348
|
+
sync_cursors: SyncCursorTable;
|
|
2349
|
+
sync_dead_letters: SyncDeadLetterTable;
|
|
2350
|
+
}
|
|
2351
|
+
interface DocumentTable {
|
|
2352
|
+
id: string;
|
|
2353
|
+
createdAt: Generated<Date>;
|
|
2354
|
+
updatedAt: Generated<Date>;
|
|
2355
|
+
}
|
|
2356
|
+
interface DocumentRelationshipTable {
|
|
2357
|
+
id: Generated<string>;
|
|
2358
|
+
sourceId: string;
|
|
2359
|
+
targetId: string;
|
|
2360
|
+
relationshipType: string;
|
|
2361
|
+
metadata: unknown;
|
|
2362
|
+
createdAt: Generated<Date>;
|
|
2363
|
+
updatedAt: Generated<Date>;
|
|
2364
|
+
}
|
|
2365
|
+
interface IndexerStateTable {
|
|
2366
|
+
id: Generated<number>;
|
|
2367
|
+
lastOperationId: number;
|
|
2368
|
+
lastOperationTimestamp: Generated<Date>;
|
|
2369
|
+
}
|
|
2370
|
+
interface DocumentIndexerDatabase {
|
|
2371
|
+
Document: DocumentTable;
|
|
2372
|
+
DocumentRelationship: DocumentRelationshipTable;
|
|
2373
|
+
IndexerState: IndexerStateTable;
|
|
2374
|
+
}
|
|
2375
|
+
//#endregion
|
|
2376
|
+
//#region src/executor/worker/protocol.d.ts
|
|
2377
|
+
/**
|
|
2378
|
+
* A JSON-clonable value safe to send across the worker IPC boundary.
|
|
2206
2379
|
*
|
|
2207
|
-
*
|
|
2208
|
-
*
|
|
2380
|
+
* The shape mirrors the structured-clone subset used by the parent's
|
|
2381
|
+
* sanitizer: primitives, arrays, plain objects, plus the explicit
|
|
2382
|
+
* {@link ErrorInfo} shape for marshalled Errors.
|
|
2209
2383
|
*
|
|
2210
2384
|
* @see Wire Protocol Reference wiki page
|
|
2211
2385
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2212
2386
|
*/
|
|
2213
|
-
type
|
|
2214
|
-
|
|
2215
|
-
numWorkers: number; /** Worker isolation mode. */
|
|
2216
|
-
workerType: "thread" | "process"; /** Optional heartbeat interval in milliseconds. */
|
|
2217
|
-
heartbeatMs?: number; /** Optional per-worker Postgres pool size override. */
|
|
2218
|
-
workerPgPoolSize?: number;
|
|
2387
|
+
type SanitizedArg = null | boolean | number | string | ErrorInfo | SanitizedArg[] | {
|
|
2388
|
+
[key: string]: SanitizedArg;
|
|
2219
2389
|
};
|
|
2220
2390
|
/**
|
|
2221
|
-
*
|
|
2391
|
+
* Structured representation of an Error for IPC transport.
|
|
2222
2392
|
*
|
|
2223
|
-
*
|
|
2224
|
-
*
|
|
2393
|
+
* Class instances cannot be structured-cloned across worker boundaries,
|
|
2394
|
+
* so Errors are flattened into this shape on the worker side and
|
|
2395
|
+
* reconstructed on the parent side.
|
|
2225
2396
|
*
|
|
2226
2397
|
* @see Wire Protocol Reference wiki page
|
|
2227
2398
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2228
2399
|
*/
|
|
2229
|
-
type
|
|
2230
|
-
|
|
2231
|
-
|
|
2400
|
+
type ErrorInfo = {
|
|
2401
|
+
name: string;
|
|
2402
|
+
message: string;
|
|
2403
|
+
stack?: string;
|
|
2404
|
+
cause?: ErrorInfo;
|
|
2232
2405
|
};
|
|
2233
2406
|
/**
|
|
2234
|
-
*
|
|
2235
|
-
*
|
|
2407
|
+
* Reference to a module that the worker should `import()` at runtime,
|
|
2408
|
+
* along with the named export to pluck out as the factory.
|
|
2409
|
+
*
|
|
2410
|
+
* Exactly one of `packageName` or `filePath` is provided.
|
|
2411
|
+
*
|
|
2412
|
+
* @see Wire Protocol Reference wiki page
|
|
2413
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2414
|
+
*/
|
|
2415
|
+
type ModuleRef = {
|
|
2416
|
+
/** Bare-specifier package name (resolved by the worker's module loader). */packageName: string; /** Named export within the module to invoke as the factory. */
|
|
2417
|
+
exportName: string;
|
|
2418
|
+
} | {
|
|
2419
|
+
/** Absolute or worker-resolvable file path to import. */filePath: string; /** Named export within the module to invoke as the factory. */
|
|
2420
|
+
exportName: string;
|
|
2421
|
+
};
|
|
2422
|
+
/**
|
|
2423
|
+
* Factory specification shared by the signature verifier and document
|
|
2424
|
+
* model spec channels. The worker imports `module.exportName` and invokes
|
|
2425
|
+
* it with `initArgs` to obtain the actual instance.
|
|
2426
|
+
*
|
|
2427
|
+
* `initArgs` must be JSON-clonable.
|
|
2428
|
+
*
|
|
2429
|
+
* @see Wire Protocol Reference wiki page
|
|
2430
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2431
|
+
*/
|
|
2432
|
+
type FactorySpec = {
|
|
2433
|
+
module: ModuleRef;
|
|
2434
|
+
initArgs?: SanitizedArg;
|
|
2435
|
+
};
|
|
2436
|
+
/**
|
|
2437
|
+
* Factory spec for the signature verifier the worker should instantiate.
|
|
2438
|
+
*
|
|
2439
|
+
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2440
|
+
* sites read intent-fully.
|
|
2441
|
+
*
|
|
2442
|
+
* @see Wire Protocol Reference wiki page
|
|
2443
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2444
|
+
*/
|
|
2445
|
+
type SignatureVerifierSpec = FactorySpec;
|
|
2446
|
+
/**
|
|
2447
|
+
* Factory spec for a document model module the worker should instantiate.
|
|
2448
|
+
*
|
|
2449
|
+
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2450
|
+
* sites read intent-fully.
|
|
2451
|
+
*
|
|
2452
|
+
* @see Wire Protocol Reference wiki page
|
|
2453
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2454
|
+
*/
|
|
2455
|
+
type DocumentModelSpec = FactorySpec;
|
|
2456
|
+
/**
|
|
2457
|
+
* One entry in the document model manifest the worker materializes on
|
|
2458
|
+
* startup (or extends lazily via `load-model`).
|
|
2459
|
+
*
|
|
2460
|
+
* @see Wire Protocol Reference wiki page
|
|
2461
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2462
|
+
*/
|
|
2463
|
+
type ModelManifestEntry = {
|
|
2464
|
+
/** Document type identifier (e.g. "ph/account"). */documentType: string; /** Document model version this entry registers. */
|
|
2465
|
+
version: string; /** Factory spec the worker imports and invokes to obtain the model. */
|
|
2466
|
+
spec: DocumentModelSpec;
|
|
2467
|
+
};
|
|
2468
|
+
/**
|
|
2469
|
+
* JSON-clonable Postgres connection info passed to the worker so it can
|
|
2470
|
+
* open its own pool. Storage-specific wiring may extend this shape in
|
|
2471
|
+
* later phases.
|
|
2472
|
+
*
|
|
2473
|
+
* @see Wire Protocol Reference wiki page
|
|
2474
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2475
|
+
*/
|
|
2476
|
+
type DbConfig = {
|
|
2477
|
+
host: string;
|
|
2478
|
+
port: number;
|
|
2479
|
+
database: string;
|
|
2480
|
+
user: string;
|
|
2481
|
+
password: string;
|
|
2482
|
+
ssl?: boolean;
|
|
2483
|
+
applicationName?: string;
|
|
2484
|
+
poolSize?: number;
|
|
2485
|
+
/**
|
|
2486
|
+
* Maximum time (ms) a caller will wait to acquire a connection from the
|
|
2487
|
+
* pool before pg.Pool throws. When omitted, pg defaults to 0 (unlimited
|
|
2488
|
+
* wait), which hides acquire-starvation as silent latency.
|
|
2489
|
+
*/
|
|
2490
|
+
connectionTimeoutMillis?: number;
|
|
2491
|
+
/**
|
|
2492
|
+
* How long (ms) an idle connection stays open before pg closes it. When
|
|
2493
|
+
* omitted, pg defaults to 10000.
|
|
2494
|
+
*/
|
|
2495
|
+
idleTimeoutMillis?: number;
|
|
2496
|
+
};
|
|
2497
|
+
/**
|
|
2498
|
+
* Configuration for the executor worker pool.
|
|
2499
|
+
*
|
|
2500
|
+
* Mirrors the `workerPool` sub-config on {@link JobExecutorConfig};
|
|
2501
|
+
* a later card wires this into the executor config.
|
|
2502
|
+
*
|
|
2503
|
+
* @see Wire Protocol Reference wiki page
|
|
2504
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2505
|
+
*/
|
|
2506
|
+
type WorkerPoolConfig = {
|
|
2507
|
+
/** Whether the worker pool is active; when false the executor runs in-process. */enabled: boolean; /** Number of worker instances to spawn. */
|
|
2508
|
+
numWorkers: number; /** Worker isolation mode. */
|
|
2509
|
+
workerType: "thread" | "process"; /** Optional heartbeat interval in milliseconds. */
|
|
2510
|
+
heartbeatMs?: number; /** Optional per-worker Postgres pool size override. */
|
|
2511
|
+
workerPgPoolSize?: number;
|
|
2512
|
+
};
|
|
2513
|
+
/**
|
|
2514
|
+
* Payload the worker reports back when a job's write phase is complete.
|
|
2515
|
+
*
|
|
2516
|
+
* Parent fills `collectionMemberships` at emission time, so it is
|
|
2517
|
+
* intentionally absent from the worker -> parent message.
|
|
2518
|
+
*
|
|
2519
|
+
* @see Wire Protocol Reference wiki page
|
|
2520
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2521
|
+
*/
|
|
2522
|
+
type JobWriteReadyPayload = {
|
|
2523
|
+
operations: OperationWithContext$1[];
|
|
2524
|
+
jobMeta: JobMeta;
|
|
2525
|
+
};
|
|
2526
|
+
/**
|
|
2527
|
+
* Initializes a freshly spawned worker with the configuration and
|
|
2528
|
+
* factories it needs to start executing jobs.
|
|
2236
2529
|
*
|
|
2237
2530
|
* @see Wire Protocol Reference wiki page
|
|
2238
2531
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
@@ -2244,7 +2537,8 @@ type InitMessage = {
|
|
|
2244
2537
|
poolConfig: WorkerPoolConfig;
|
|
2245
2538
|
db: DbConfig; /** Omitted = the worker performs no executor-side signature verification. */
|
|
2246
2539
|
signatureVerifier?: SignatureVerifierSpec;
|
|
2247
|
-
models: ModelManifestEntry[];
|
|
2540
|
+
models: ModelManifestEntry[]; /** Omitted = the worker builds its executor with the built-in defaults. */
|
|
2541
|
+
executorConfig?: JobExecutorConfig;
|
|
2248
2542
|
};
|
|
2249
2543
|
/**
|
|
2250
2544
|
* Dispatches a job to the worker for execution.
|
|
@@ -2425,504 +2719,873 @@ type PoolAcquireSamplesMessage = {
|
|
|
2425
2719
|
*/
|
|
2426
2720
|
type WorkerMessage = ReadyMessage | ResultMessage | ModelLoadedMessage | ModelLoadFailedMessage | LogMessage | HeartbeatMessage | MetricsMessage | PoolAcquireSamplesMessage;
|
|
2427
2721
|
//#endregion
|
|
2428
|
-
//#region src/
|
|
2722
|
+
//#region src/core/model-sources.d.ts
|
|
2723
|
+
/** An importable file holding one or more document-model exports. */
|
|
2724
|
+
type FileModelSource = {
|
|
2725
|
+
filePath: string;
|
|
2726
|
+
exportName?: string;
|
|
2727
|
+
};
|
|
2728
|
+
/** An importable package specifier holding one or more document-model exports. */
|
|
2729
|
+
type PackageModelSource = {
|
|
2730
|
+
packageName: string;
|
|
2731
|
+
subpath?: string;
|
|
2732
|
+
exportName?: string;
|
|
2733
|
+
};
|
|
2429
2734
|
/**
|
|
2430
|
-
*
|
|
2735
|
+
* A source of document models: a live module, an importable file, or an
|
|
2736
|
+
* importable package. File and package sources can cross a worker-thread
|
|
2737
|
+
* boundary (workers re-import them); a live module cannot.
|
|
2431
2738
|
*/
|
|
2432
|
-
type
|
|
2433
|
-
|
|
2434
|
-
|
|
2739
|
+
type DocumentModelSource = DocumentModelModule<any> | FileModelSource | PackageModelSource;
|
|
2740
|
+
//#endregion
|
|
2741
|
+
//#region src/registry/interfaces.d.ts
|
|
2742
|
+
type RegistrationResult<T> = {
|
|
2743
|
+
status: "success";
|
|
2744
|
+
item: T;
|
|
2745
|
+
} | {
|
|
2746
|
+
status: "error";
|
|
2747
|
+
item: T;
|
|
2748
|
+
error: Error;
|
|
2435
2749
|
};
|
|
2436
2750
|
/**
|
|
2437
|
-
*
|
|
2751
|
+
* Loader that asynchronously resolves a document type to a
|
|
2752
|
+
* {@link DocumentModelSource}. Used by the queue to gate CREATE_DOCUMENT
|
|
2753
|
+
* jobs until the required model is available in the registry.
|
|
2438
2754
|
*
|
|
2439
|
-
*
|
|
2440
|
-
* the
|
|
2441
|
-
*
|
|
2442
|
-
*
|
|
2755
|
+
* Return an importable source ({ filePath } or { packageName }) whenever
|
|
2756
|
+
* possible: the resolver registers the resolved models on the host registry
|
|
2757
|
+
* and broadcasts importable sources to executor workers. A live
|
|
2758
|
+
* DocumentModelModule is also valid but host-only — it cannot cross a
|
|
2759
|
+
* worker-thread boundary, so worker pools will not receive it.
|
|
2443
2760
|
*/
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
};
|
|
2761
|
+
interface IDocumentModelLoader {
|
|
2762
|
+
load(documentType: string): Promise<DocumentModelSource>;
|
|
2763
|
+
}
|
|
2448
2764
|
/**
|
|
2449
|
-
*
|
|
2450
|
-
*
|
|
2451
|
-
*
|
|
2452
|
-
* test fake) and expose a transport-agnostic surface that the worker-pool
|
|
2453
|
-
* manager uses to dispatch jobs. The handle owns one worker's lifecycle
|
|
2454
|
-
* (`start` -> `execute`* -> `shutdown`) and bounds its in-flight map to a
|
|
2455
|
-
* single entry; `SimpleJobExecutor` is single-threaded inside the worker, so
|
|
2456
|
-
* concurrent dispatches would race its caches.
|
|
2765
|
+
* Registry for managing document model modules.
|
|
2766
|
+
* Provides centralized access to document models' reducers, utils, and specifications.
|
|
2767
|
+
* Supports version-aware module storage and upgrade manifest management.
|
|
2457
2768
|
*/
|
|
2458
|
-
interface
|
|
2459
|
-
/** Stable identifier of the worker (mirrors `InitMessage.workerId`). */
|
|
2460
|
-
readonly workerId: string;
|
|
2461
|
-
/** Zero-based index within the pool, used for sticky routing. */
|
|
2462
|
-
readonly index: number;
|
|
2769
|
+
interface IDocumentModelRegistry {
|
|
2463
2770
|
/**
|
|
2464
|
-
*
|
|
2465
|
-
*
|
|
2771
|
+
* Register multiple modules at once.
|
|
2772
|
+
* Modules without a version field default to version 1.
|
|
2773
|
+
* Invalid or duplicate modules are skipped without breaking registration of the remaining modules.
|
|
2774
|
+
*
|
|
2775
|
+
* @param modules Document model modules to register
|
|
2776
|
+
* @returns Array of results, one per module, indicating success or failure
|
|
2466
2777
|
*/
|
|
2467
|
-
|
|
2778
|
+
registerModules(...modules: DocumentModelModule<any>[]): RegistrationResult<DocumentModelModule<any>>[];
|
|
2468
2779
|
/**
|
|
2469
|
-
*
|
|
2470
|
-
*
|
|
2471
|
-
*
|
|
2472
|
-
*
|
|
2473
|
-
* result.
|
|
2780
|
+
* Unregister all versions of the specified document types.
|
|
2781
|
+
*
|
|
2782
|
+
* @param documentTypes The document types to unregister
|
|
2783
|
+
* @returns true if all modules were unregistered, false if any were not found
|
|
2474
2784
|
*/
|
|
2475
|
-
|
|
2785
|
+
unregisterModules(...documentTypes: string[]): boolean;
|
|
2476
2786
|
/**
|
|
2477
|
-
*
|
|
2478
|
-
*
|
|
2479
|
-
*
|
|
2787
|
+
* Get a specific document model module by document type and optional version.
|
|
2788
|
+
* If version is not specified, returns the latest version.
|
|
2789
|
+
*
|
|
2790
|
+
* @param documentType The document type identifier
|
|
2791
|
+
* @param version Optional version number to retrieve
|
|
2792
|
+
* @returns The document model module
|
|
2793
|
+
* @throws ModuleNotFoundError if the document type or version is not registered
|
|
2480
2794
|
*/
|
|
2481
|
-
|
|
2795
|
+
getModule(documentType: string, version?: number): DocumentModelModule<any>;
|
|
2482
2796
|
/**
|
|
2483
|
-
*
|
|
2484
|
-
*
|
|
2485
|
-
*
|
|
2797
|
+
* Get all registered document model modules.
|
|
2798
|
+
*
|
|
2799
|
+
* @returns Array of all registered modules
|
|
2486
2800
|
*/
|
|
2487
|
-
|
|
2801
|
+
getAllModules(): DocumentModelModule<any>[];
|
|
2488
2802
|
/**
|
|
2489
|
-
*
|
|
2490
|
-
* when the worker replies with `model-loaded`; rejects when it replies
|
|
2491
|
-
* with `model-load-failed` or the worker exits before answering.
|
|
2803
|
+
* Clear all registered modules and upgrade manifests.
|
|
2492
2804
|
*/
|
|
2493
|
-
|
|
2494
|
-
/** True when no job is currently in flight. */
|
|
2495
|
-
isIdle(): boolean;
|
|
2496
|
-
/** Snapshot of the in-flight slot, or null when idle. */
|
|
2497
|
-
getInFlight(): WorkerInFlightSnapshot | null;
|
|
2498
|
-
}
|
|
2499
|
-
/**
|
|
2500
|
-
* Simple interface for executing a job.
|
|
2501
|
-
* A JobExecutor simply takes a job and executes it - nothing more.
|
|
2502
|
-
*/
|
|
2503
|
-
interface IJobExecutor {
|
|
2805
|
+
clear(): void;
|
|
2504
2806
|
/**
|
|
2505
|
-
*
|
|
2506
|
-
*
|
|
2507
|
-
* @
|
|
2807
|
+
* Get all supported versions for a document type, sorted in ascending order.
|
|
2808
|
+
*
|
|
2809
|
+
* @param documentType The document type identifier
|
|
2810
|
+
* @returns Array of version numbers sorted ascending
|
|
2811
|
+
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
2508
2812
|
*/
|
|
2509
|
-
|
|
2510
|
-
}
|
|
2511
|
-
/**
|
|
2512
|
-
* Interface for managing multiple job executors.
|
|
2513
|
-
* Listens for 'jobAvailable' events from the event bus, pulls jobs from the queue,
|
|
2514
|
-
* and coordinates the distribution of jobs across multiple executor instances.
|
|
2515
|
-
*/
|
|
2516
|
-
interface IJobExecutorManager {
|
|
2813
|
+
getSupportedVersions(documentType: string): number[];
|
|
2517
2814
|
/**
|
|
2518
|
-
*
|
|
2519
|
-
* Begins listening for 'jobAvailable' events and dispatching to executors.
|
|
2815
|
+
* Get the latest (highest) version number for a document type.
|
|
2520
2816
|
*
|
|
2521
|
-
* @param
|
|
2522
|
-
* @returns
|
|
2817
|
+
* @param documentType The document type identifier
|
|
2818
|
+
* @returns The highest version number registered for this document type
|
|
2819
|
+
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
2523
2820
|
*/
|
|
2524
|
-
|
|
2821
|
+
getLatestVersion(documentType: string): number;
|
|
2525
2822
|
/**
|
|
2526
|
-
*
|
|
2823
|
+
* Register upgrade manifests that define upgrade paths between versions.
|
|
2824
|
+
* Invalid or duplicate manifests are skipped without breaking registration of the remaining manifests.
|
|
2527
2825
|
*
|
|
2528
|
-
* @param
|
|
2529
|
-
* @returns
|
|
2826
|
+
* @param manifests Upgrade manifests to register
|
|
2827
|
+
* @returns Array of results, one per manifest, indicating success or failure
|
|
2530
2828
|
*/
|
|
2531
|
-
|
|
2829
|
+
registerUpgradeManifests(...manifests: UpgradeManifest<readonly number[]>[]): RegistrationResult<UpgradeManifest<readonly number[]>>[];
|
|
2532
2830
|
/**
|
|
2533
|
-
*
|
|
2831
|
+
* Unregister upgrade manifests for the specified document types.
|
|
2832
|
+
* @param documentTypes The document types whose upgrade manifests should be unregistered
|
|
2833
|
+
* @returns true if all modules were unregistered, false if any were not found
|
|
2834
|
+
**/
|
|
2835
|
+
unregisterUpgradeManifests(...documentTypes: string[]): boolean;
|
|
2836
|
+
/**
|
|
2837
|
+
* Get the upgrade manifest for a document type.
|
|
2534
2838
|
*
|
|
2535
|
-
* @
|
|
2839
|
+
* @param documentType The document type identifier
|
|
2840
|
+
* @returns The upgrade manifest
|
|
2841
|
+
* @throws ManifestNotFoundError if no manifest is registered for the document type
|
|
2536
2842
|
*/
|
|
2537
|
-
|
|
2843
|
+
getUpgradeManifest(documentType: string): UpgradeManifest<readonly number[]>;
|
|
2538
2844
|
/**
|
|
2539
|
-
*
|
|
2845
|
+
* Compute the upgrade path from one version to another.
|
|
2846
|
+
* Returns the sequence of upgrade transitions needed.
|
|
2540
2847
|
*
|
|
2541
|
-
* @
|
|
2848
|
+
* @param documentType The document type identifier
|
|
2849
|
+
* @param fromVersion The starting version
|
|
2850
|
+
* @param toVersion The target version
|
|
2851
|
+
* @returns Array of upgrade transitions in order
|
|
2852
|
+
* @throws DowngradeNotSupportedError if toVersion is less than fromVersion
|
|
2853
|
+
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2854
|
+
* @throws MissingUpgradeTransitionError if any transition in the path is missing
|
|
2542
2855
|
*/
|
|
2543
|
-
|
|
2856
|
+
computeUpgradePath(documentType: string, fromVersion: number, toVersion: number): UpgradeTransition[];
|
|
2857
|
+
/**
|
|
2858
|
+
* Get the upgrade reducer for a single-step version transition.
|
|
2859
|
+
*
|
|
2860
|
+
* @param documentType The document type identifier
|
|
2861
|
+
* @param fromVersion The starting version
|
|
2862
|
+
* @param toVersion The target version (must be fromVersion + 1)
|
|
2863
|
+
* @returns The upgrade reducer function
|
|
2864
|
+
* @throws InvalidUpgradeStepError if toVersion is not fromVersion + 1
|
|
2865
|
+
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2866
|
+
* @throws MissingUpgradeTransitionError if the transition is not found
|
|
2867
|
+
*/
|
|
2868
|
+
getUpgradeReducer(documentType: string, fromVersion: number, toVersion: number): UpgradeReducer<any, any>;
|
|
2544
2869
|
}
|
|
2545
2870
|
//#endregion
|
|
2546
|
-
//#region src/
|
|
2871
|
+
//#region src/cache/buffer/ring-buffer.d.ts
|
|
2547
2872
|
/**
|
|
2548
|
-
*
|
|
2549
|
-
*
|
|
2873
|
+
* RingBuffer is a generic circular buffer implementation that stores a fixed number
|
|
2874
|
+
* of items. When the buffer is full, new items overwrite the oldest items.
|
|
2875
|
+
*
|
|
2876
|
+
* This implementation maintains O(1) time complexity for push operations and provides
|
|
2877
|
+
* items in chronological order (oldest to newest) via getAll().
|
|
2878
|
+
*
|
|
2879
|
+
* @template T - The type of items stored in the buffer
|
|
2550
2880
|
*/
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
registerJob(jobInfo: JobInfo): void;
|
|
2881
|
+
declare class RingBuffer<T> {
|
|
2882
|
+
private buffer;
|
|
2883
|
+
private head;
|
|
2884
|
+
private size;
|
|
2885
|
+
private capacity;
|
|
2886
|
+
constructor(capacity: number);
|
|
2558
2887
|
/**
|
|
2559
|
-
*
|
|
2888
|
+
* Adds an item to the buffer. If the buffer is full, overwrites the oldest item.
|
|
2560
2889
|
*
|
|
2561
|
-
* @param
|
|
2890
|
+
* @param item - The item to add
|
|
2562
2891
|
*/
|
|
2563
|
-
|
|
2892
|
+
push(item: T): void;
|
|
2564
2893
|
/**
|
|
2565
|
-
*
|
|
2894
|
+
* Returns all items in the buffer in chronological order (oldest to newest).
|
|
2566
2895
|
*
|
|
2567
|
-
* @
|
|
2568
|
-
* @param error - Error information including message and stack trace
|
|
2569
|
-
* @param job - Optional full job object for debugging purposes
|
|
2896
|
+
* @returns Array of items in insertion order
|
|
2570
2897
|
*/
|
|
2571
|
-
|
|
2898
|
+
getAll(): T[];
|
|
2572
2899
|
/**
|
|
2573
|
-
*
|
|
2574
|
-
*
|
|
2575
|
-
* @param jobId - The job ID to query
|
|
2576
|
-
* @returns The job information, or null if the job is not found
|
|
2900
|
+
* Clears all items from the buffer.
|
|
2577
2901
|
*/
|
|
2578
|
-
|
|
2902
|
+
clear(): void;
|
|
2579
2903
|
/**
|
|
2580
|
-
*
|
|
2581
|
-
* Unsubscribes from all event bus subscriptions.
|
|
2904
|
+
* Gets the current number of items in the buffer.
|
|
2582
2905
|
*/
|
|
2583
|
-
|
|
2906
|
+
get length(): number;
|
|
2584
2907
|
}
|
|
2585
2908
|
//#endregion
|
|
2586
|
-
//#region src/
|
|
2909
|
+
//#region src/cache/kysely-write-cache.d.ts
|
|
2910
|
+
type DocumentStream = {
|
|
2911
|
+
key: string;
|
|
2912
|
+
ringBuffer: RingBuffer<CachedSnapshot>;
|
|
2913
|
+
};
|
|
2587
2914
|
/**
|
|
2588
|
-
*
|
|
2589
|
-
*
|
|
2590
|
-
*
|
|
2915
|
+
* In-memory write cache with keyframe persistence for PHDocuments.
|
|
2916
|
+
*
|
|
2917
|
+
* Caches document snapshots in ring buffers with LRU eviction. On cache miss,
|
|
2918
|
+
* rebuilds documents from nearest keyframe or full operation history.
|
|
2919
|
+
*
|
|
2920
|
+
* **Performance Characteristics:**
|
|
2921
|
+
* - Cache hit: O(1) lookup in ring buffer
|
|
2922
|
+
* - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe
|
|
2923
|
+
* - Warm miss: O(m) where m is operations since cached revision
|
|
2924
|
+
* - Eviction: O(1) for LRU tracking and removal
|
|
2925
|
+
*
|
|
2926
|
+
* **Thread Safety:**
|
|
2927
|
+
* Not thread-safe. Designed for single-threaded job executor environment.
|
|
2928
|
+
* External synchronization required for concurrent access across multiple executors.
|
|
2929
|
+
*
|
|
2930
|
+
* **Example:**
|
|
2931
|
+
* ```typescript
|
|
2932
|
+
* const cache = new KyselyWriteCache(
|
|
2933
|
+
* keyframeStore,
|
|
2934
|
+
* operationStore,
|
|
2935
|
+
* registry,
|
|
2936
|
+
* { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }
|
|
2937
|
+
* );
|
|
2938
|
+
*
|
|
2939
|
+
* await cache.startup();
|
|
2940
|
+
*
|
|
2941
|
+
* // Retrieve or rebuild document
|
|
2942
|
+
* const doc = await cache.getState(docId, docType, scope, branch, revision);
|
|
2943
|
+
*
|
|
2944
|
+
* // Cache result after job execution
|
|
2945
|
+
* cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);
|
|
2946
|
+
*
|
|
2947
|
+
* await cache.shutdown();
|
|
2948
|
+
* ```
|
|
2591
2949
|
*/
|
|
2592
|
-
|
|
2950
|
+
declare class KyselyWriteCache implements IWriteCache {
|
|
2951
|
+
private streams;
|
|
2952
|
+
private lruTracker;
|
|
2953
|
+
private keyframeStore;
|
|
2954
|
+
private operationStore;
|
|
2955
|
+
private registry;
|
|
2956
|
+
private config;
|
|
2957
|
+
constructor(keyframeStore: IKeyframeStore, operationStore: IOperationStore, registry: IDocumentModelRegistry, config: WriteCacheConfig);
|
|
2958
|
+
withScopedStores(operationStore: IOperationStore, keyframeStore: IKeyframeStore): KyselyWriteCache;
|
|
2593
2959
|
/**
|
|
2594
|
-
*
|
|
2595
|
-
*
|
|
2596
|
-
* Emits a 'jobAvailable' event to the event bus when the job is queued.
|
|
2597
|
-
* @param job - The job to add to the queue
|
|
2598
|
-
* @returns Promise that resolves when the job is queued
|
|
2960
|
+
* Initializes the write cache.
|
|
2961
|
+
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
2599
2962
|
*/
|
|
2600
|
-
|
|
2963
|
+
startup(): Promise<void>;
|
|
2601
2964
|
/**
|
|
2602
|
-
*
|
|
2603
|
-
*
|
|
2604
|
-
* @param scope - The scope to get jobs for
|
|
2605
|
-
* @param branch - The branch to get jobs for
|
|
2606
|
-
* @param signal - Optional abort signal to cancel the request
|
|
2607
|
-
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
2965
|
+
* Shuts down the write cache.
|
|
2966
|
+
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
2608
2967
|
*/
|
|
2609
|
-
|
|
2968
|
+
shutdown(): Promise<void>;
|
|
2610
2969
|
/**
|
|
2611
|
-
*
|
|
2612
|
-
*
|
|
2613
|
-
*
|
|
2970
|
+
* Retrieves document state at a specific revision from cache or rebuilds it.
|
|
2971
|
+
*
|
|
2972
|
+
* Note: this returns a _shallow_ copy of the document.
|
|
2973
|
+
*
|
|
2974
|
+
* Cache hit path: Returns cached snapshot if available (O(1))
|
|
2975
|
+
* Warm miss path: Rebuilds from cached base revision + incremental ops
|
|
2976
|
+
* Cold miss path: Rebuilds from keyframe or from scratch using all operations
|
|
2977
|
+
*
|
|
2978
|
+
* @param documentId - The document identifier
|
|
2979
|
+
* @param scope - The operation scope
|
|
2980
|
+
* @param branch - The operation branch
|
|
2981
|
+
* @param targetRevision - The target revision, or undefined for newest
|
|
2982
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2983
|
+
* @returns The document at the target revision
|
|
2984
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2985
|
+
* @throws {ModuleNotFoundError} If document type not registered in registry
|
|
2986
|
+
* @throws {Error} "Failed to rebuild document" if operation store fails
|
|
2987
|
+
* @throws {Error} If reducer throws during operation application
|
|
2988
|
+
* @throws {Error} If document serialization fails
|
|
2614
2989
|
*/
|
|
2615
|
-
|
|
2990
|
+
getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
|
|
2616
2991
|
/**
|
|
2617
|
-
*
|
|
2618
|
-
*
|
|
2619
|
-
* is
|
|
2620
|
-
* the
|
|
2621
|
-
*
|
|
2622
|
-
*
|
|
2623
|
-
*
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2992
|
+
* Stores a document snapshot in the cache at a specific revision.
|
|
2993
|
+
*
|
|
2994
|
+
* The cached document is a shallow copy of the input with its operation history
|
|
2995
|
+
* truncated to the last operation per scope and its clipboard cleared. This keeps
|
|
2996
|
+
* memory use and copy costs constant regardless of operation count. Consumers of
|
|
2997
|
+
* getState() must not rely on the full operation history being present; the only
|
|
2998
|
+
* guaranteed invariant is that operations[scope].at(-1) reflects the latest
|
|
2999
|
+
* operation index for each scope.
|
|
3000
|
+
*
|
|
3001
|
+
* Updates LRU tracker and may evict least recently used stream if at capacity.
|
|
3002
|
+
* Asynchronously persists keyframes at configured intervals (fire-and-forget).
|
|
3003
|
+
*
|
|
3004
|
+
* @param documentId - The document identifier
|
|
3005
|
+
* @param scope - The operation scope
|
|
3006
|
+
* @param branch - The operation branch
|
|
3007
|
+
* @param revision - The revision number
|
|
3008
|
+
* @param document - The document to cache
|
|
3009
|
+
* @throws {Error} If document serialization fails
|
|
2626
3010
|
*/
|
|
2627
|
-
|
|
3011
|
+
putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, position: SnapshotPosition): void;
|
|
3012
|
+
private store;
|
|
2628
3013
|
/**
|
|
2629
|
-
*
|
|
2630
|
-
*
|
|
2631
|
-
*
|
|
2632
|
-
*
|
|
2633
|
-
*
|
|
3014
|
+
* Invalidates cached document streams.
|
|
3015
|
+
*
|
|
3016
|
+
* Supports three invalidation scopes:
|
|
3017
|
+
* - Document-level: invalidate(documentId) - removes all streams for document
|
|
3018
|
+
* - Scope-level: invalidate(documentId, scope) - removes all branches for scope
|
|
3019
|
+
* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream
|
|
3020
|
+
*
|
|
3021
|
+
* @param documentId - The document identifier
|
|
3022
|
+
* @param scope - Optional scope to narrow invalidation
|
|
3023
|
+
* @param branch - Optional branch to narrow invalidation (requires scope)
|
|
3024
|
+
* @returns The number of streams evicted
|
|
2634
3025
|
*/
|
|
2635
|
-
|
|
3026
|
+
invalidate(documentId: string, scope?: string, branch?: string): number;
|
|
2636
3027
|
/**
|
|
2637
|
-
*
|
|
2638
|
-
*
|
|
2639
|
-
*/
|
|
2640
|
-
totalSize(): Promise<number>;
|
|
2641
|
-
/**
|
|
2642
|
-
* Remove a specific job from the queue.
|
|
2643
|
-
* @param jobId - The ID of the job to remove
|
|
2644
|
-
* @returns Promise that resolves to true if job was removed, false if not found
|
|
2645
|
-
*/
|
|
2646
|
-
remove(jobId: string): Promise<boolean>;
|
|
2647
|
-
/**
|
|
2648
|
-
* Clear all jobs for a specific document/scope/branch combination.
|
|
2649
|
-
* @param documentId - The document ID
|
|
2650
|
-
* @param scope - The scope
|
|
2651
|
-
* @param branch - The branch
|
|
2652
|
-
* @returns Promise that resolves when the queue is cleared
|
|
2653
|
-
*/
|
|
2654
|
-
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
2655
|
-
/**
|
|
2656
|
-
* Clear all jobs from all queues.
|
|
2657
|
-
* @returns Promise that resolves when all queues are cleared
|
|
2658
|
-
*/
|
|
2659
|
-
clearAll(): Promise<void>;
|
|
2660
|
-
/**
|
|
2661
|
-
* Check if there are any jobs in the queue.
|
|
2662
|
-
* @returns Promise that resolves to true if there are jobs, false otherwise
|
|
2663
|
-
*/
|
|
2664
|
-
hasJobs(): Promise<boolean>;
|
|
2665
|
-
/**
|
|
2666
|
-
* Mark a job as completed.
|
|
2667
|
-
* @param jobId - The ID of the job to mark as completed
|
|
2668
|
-
* @returns Promise that resolves when the job is marked as completed
|
|
3028
|
+
* Clears the entire cache, removing all cached document streams.
|
|
3029
|
+
* Resets LRU tracking state. This operation always succeeds.
|
|
2669
3030
|
*/
|
|
2670
|
-
|
|
3031
|
+
clear(): void;
|
|
2671
3032
|
/**
|
|
2672
|
-
*
|
|
2673
|
-
*
|
|
2674
|
-
*
|
|
2675
|
-
* @
|
|
3033
|
+
* Retrieves a specific stream for a document. Exposed on the implementation
|
|
3034
|
+
* for testing, but not on the interface.
|
|
3035
|
+
*
|
|
3036
|
+
* @internal
|
|
2676
3037
|
*/
|
|
2677
|
-
|
|
3038
|
+
getStream(documentId: string, scope: string, branch: string): DocumentStream | undefined;
|
|
3039
|
+
private findNearestKeyframe;
|
|
3040
|
+
private coldMissRebuild;
|
|
2678
3041
|
/**
|
|
2679
|
-
*
|
|
2680
|
-
*
|
|
2681
|
-
* @param error - Optional error information from the failure
|
|
2682
|
-
* @returns Promise that resolves when the job is requeued for retry
|
|
3042
|
+
* Copies the current document revisions onto the document. Overwrites the
|
|
3043
|
+
* requested scope revision with the target revision, if provided.
|
|
2683
3044
|
*/
|
|
2684
|
-
|
|
3045
|
+
private stampRevisions;
|
|
3046
|
+
/** The stored operation at `index`, or undefined if it is no longer there. */
|
|
3047
|
+
private operationAt;
|
|
2685
3048
|
/**
|
|
2686
|
-
*
|
|
3049
|
+
* Resolves which module version to use for a given operation in phase 2.
|
|
3050
|
+
*
|
|
3051
|
+
* Uses the validated-upgrade boundary rules from D7:
|
|
3052
|
+
* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary
|
|
3053
|
+
* - Otherwise: timestamp fallback
|
|
3054
|
+
* - Falls back to final module version when neither is decidable
|
|
2687
3055
|
*/
|
|
2688
|
-
|
|
3056
|
+
private resolveModuleVersionForOp;
|
|
3057
|
+
private warmMissRebuild;
|
|
3058
|
+
private findNearestOlderSnapshot;
|
|
3059
|
+
private makeStreamKey;
|
|
3060
|
+
private getOrCreateStream;
|
|
3061
|
+
private isKeyframeRevision;
|
|
3062
|
+
}
|
|
3063
|
+
//#endregion
|
|
3064
|
+
//#region src/storage/kysely/store.d.ts
|
|
3065
|
+
declare class KyselyOperationStore implements IOperationStore {
|
|
3066
|
+
private db;
|
|
3067
|
+
private trx?;
|
|
3068
|
+
constructor(db: Kysely<Database$1>);
|
|
3069
|
+
private get queryExecutor();
|
|
3070
|
+
withTransaction(trx: Transaction<Database$1>): KyselyOperationStore;
|
|
3071
|
+
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal, condition?: AppendCondition): Promise<Operation[]>;
|
|
3072
|
+
private resolveUniqueConstraint;
|
|
3073
|
+
private executeApply;
|
|
2689
3074
|
/**
|
|
2690
|
-
*
|
|
2691
|
-
*
|
|
3075
|
+
* Locks the written stream and every read-set stream, in sorted key order
|
|
3076
|
+
* so that overlapping concurrent appends serialize rather than deadlock.
|
|
3077
|
+
* The locks are still taken one row at a time, so the query preserves that
|
|
3078
|
+
* order. It must stay separate from the guarded insert, which would
|
|
3079
|
+
* otherwise read a snapshot taken before the locks were held.
|
|
2692
3080
|
*/
|
|
2693
|
-
|
|
3081
|
+
private acquireStreamLocks;
|
|
2694
3082
|
/**
|
|
2695
|
-
*
|
|
3083
|
+
* Inserts the staged operations with the condition compiled in as a WHERE
|
|
3084
|
+
* NOT EXISTS guard, making the check and the append one statement. Returns
|
|
3085
|
+
* the rows inserted; zero means the guard failed and nothing was written.
|
|
2696
3086
|
*/
|
|
2697
|
-
|
|
3087
|
+
private insertGuarded;
|
|
3088
|
+
private findIdempotentReplay;
|
|
3089
|
+
getSince(documentId: string, scope: string, branch: string, revision: number, filter?: OperationFilter, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
3090
|
+
getSinceId(id: number, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<OperationWithContext$1>>;
|
|
3091
|
+
getConflicting(documentId: string, scope: string, branch: string, minTimestamp: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
3092
|
+
getRevisions(documentId: string, branch: string, signal?: AbortSignal): Promise<DocumentRevisions>;
|
|
3093
|
+
getStreamLatestTimestamp(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<string | undefined>;
|
|
3094
|
+
private rowToOperation;
|
|
3095
|
+
private rowToOperationWithContext;
|
|
2698
3096
|
}
|
|
2699
3097
|
//#endregion
|
|
2700
|
-
//#region src/
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
documentId: string
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
branch:
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
identifiers: unknown;
|
|
2720
|
-
metadata: unknown;
|
|
2721
|
-
isDeleted: Generated<boolean>;
|
|
2722
|
-
deletedAt: Date | null;
|
|
2723
|
-
}
|
|
2724
|
-
interface SlugMappingTable {
|
|
2725
|
-
slug: string;
|
|
2726
|
-
documentId: string;
|
|
2727
|
-
scope: string;
|
|
2728
|
-
branch: string;
|
|
2729
|
-
createdAt: Generated<Date>;
|
|
2730
|
-
updatedAt: Generated<Date>;
|
|
3098
|
+
//#region src/storage/kysely/keyframe-store.d.ts
|
|
3099
|
+
declare class KyselyKeyframeStore implements IKeyframeStore {
|
|
3100
|
+
private db;
|
|
3101
|
+
private trx?;
|
|
3102
|
+
constructor(db: Kysely<Database$1>);
|
|
3103
|
+
private get queryExecutor();
|
|
3104
|
+
withTransaction(trx: Transaction<Database$1>): KyselyKeyframeStore;
|
|
3105
|
+
putKeyframe(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, signal?: AbortSignal): Promise<void>;
|
|
3106
|
+
findNearestKeyframe(documentId: string, scope: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<{
|
|
3107
|
+
revision: number;
|
|
3108
|
+
document: PHDocument;
|
|
3109
|
+
} | undefined>;
|
|
3110
|
+
listKeyframes(documentId: string, scope?: string, branch?: string, signal?: AbortSignal): Promise<Array<{
|
|
3111
|
+
scope: string;
|
|
3112
|
+
branch: string;
|
|
3113
|
+
revision: number;
|
|
3114
|
+
document: PHDocument;
|
|
3115
|
+
}>>;
|
|
3116
|
+
deleteKeyframes(documentId: string, scope?: string, branch?: string, signal?: AbortSignal): Promise<number>;
|
|
2731
3117
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
lastErrorTimestamp: Date | null;
|
|
2741
|
-
createdAt: Generated<Date>;
|
|
2742
|
-
updatedAt: Generated<Date>;
|
|
3118
|
+
//#endregion
|
|
3119
|
+
//#region src/executor/execution-scope.d.ts
|
|
3120
|
+
interface ExecutionStores {
|
|
3121
|
+
operationStore: IOperationStore;
|
|
3122
|
+
operationIndex: IOperationIndex;
|
|
3123
|
+
writeCache: IWriteCache;
|
|
3124
|
+
documentMetaCache: IDocumentMetaCache;
|
|
3125
|
+
collectionMembershipCache: ICollectionMembershipCache;
|
|
2743
3126
|
}
|
|
2744
|
-
interface
|
|
2745
|
-
|
|
2746
|
-
DocumentSnapshot: DocumentSnapshotTable;
|
|
2747
|
-
SlugMapping: SlugMappingTable;
|
|
2748
|
-
ProcessorCursor: ProcessorCursorTable;
|
|
3127
|
+
interface IExecutionScope {
|
|
3128
|
+
run<T>(fn: (stores: ExecutionStores) => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
2749
3129
|
}
|
|
2750
|
-
type InsertableDocumentSnapshot = Insertable<DocumentSnapshotTable>;
|
|
2751
3130
|
//#endregion
|
|
2752
|
-
//#region src/
|
|
2753
|
-
/** An importable file holding one or more document-model exports. */
|
|
2754
|
-
type FileModelSource = {
|
|
2755
|
-
filePath: string;
|
|
2756
|
-
exportName?: string;
|
|
2757
|
-
};
|
|
2758
|
-
/** An importable package specifier holding one or more document-model exports. */
|
|
2759
|
-
type PackageModelSource = {
|
|
2760
|
-
packageName: string;
|
|
2761
|
-
subpath?: string;
|
|
2762
|
-
exportName?: string;
|
|
2763
|
-
};
|
|
3131
|
+
//#region src/executor/types.d.ts
|
|
2764
3132
|
/**
|
|
2765
|
-
*
|
|
2766
|
-
* importable package. File and package sources can cross a worker-thread
|
|
2767
|
-
* boundary (workers re-import them); a live module cannot.
|
|
3133
|
+
* Represents the result of a job execution
|
|
2768
3134
|
*/
|
|
2769
|
-
type
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
3135
|
+
type JobResult = {
|
|
3136
|
+
/** The job that was executed */job: Job; /** Whether the job executed successfully */
|
|
3137
|
+
success: boolean; /** Error if the job failed */
|
|
3138
|
+
error?: Error; /** The operations generated from the actions (if successful) */
|
|
3139
|
+
operations?: Operation[];
|
|
3140
|
+
/**
|
|
3141
|
+
* Operations with context (includes ephemeral resultingState).
|
|
3142
|
+
* Used for emitting to IDocumentView via event bus.
|
|
3143
|
+
*/
|
|
3144
|
+
operationsWithContext?: OperationWithContext$1[]; /** Timestamp when the job execution completed */
|
|
3145
|
+
completedAt?: string; /** Duration of job execution in milliseconds */
|
|
3146
|
+
duration?: number; /** Any additional metadata from the execution */
|
|
3147
|
+
metadata?: Record<string, any>;
|
|
2779
3148
|
};
|
|
2780
3149
|
/**
|
|
2781
|
-
*
|
|
2782
|
-
* {@link DocumentModelSource}. Used by the queue to gate CREATE_DOCUMENT
|
|
2783
|
-
* jobs until the required model is available in the registry.
|
|
3150
|
+
* Enforcement the reactor performs, each off by default.
|
|
2784
3151
|
*
|
|
2785
|
-
*
|
|
2786
|
-
*
|
|
2787
|
-
*
|
|
2788
|
-
* DocumentModelModule is also valid but host-only — it cannot cross a
|
|
2789
|
-
* worker-thread boundary, so worker pools will not receive it.
|
|
2790
|
-
*/
|
|
2791
|
-
interface IDocumentModelLoader {
|
|
2792
|
-
load(documentType: string): Promise<DocumentModelSource>;
|
|
2793
|
-
}
|
|
2794
|
-
/**
|
|
2795
|
-
* Registry for managing document model modules.
|
|
2796
|
-
* Provides centralized access to document models' reducers, utils, and specifications.
|
|
2797
|
-
* Supports version-aware module storage and upgrade manifest management.
|
|
3152
|
+
* An evaluation made while replaying is part of the document's history, so two
|
|
3153
|
+
* reactors that share documents and disagree on these diverge. A flag is turned
|
|
3154
|
+
* on for a set of reactors that sync with each other, not for one node.
|
|
2798
3155
|
*/
|
|
2799
|
-
|
|
2800
|
-
/**
|
|
2801
|
-
* Register multiple modules at once.
|
|
2802
|
-
* Modules without a version field default to version 1.
|
|
2803
|
-
* Invalid or duplicate modules are skipped without breaking registration of the remaining modules.
|
|
2804
|
-
*
|
|
2805
|
-
* @param modules Document model modules to register
|
|
2806
|
-
* @returns Array of results, one per module, indicating success or failure
|
|
2807
|
-
*/
|
|
2808
|
-
registerModules(...modules: DocumentModelModule<any>[]): RegistrationResult<DocumentModelModule<any>>[];
|
|
2809
|
-
/**
|
|
2810
|
-
* Unregister all versions of the specified document types.
|
|
2811
|
-
*
|
|
2812
|
-
* @param documentTypes The document types to unregister
|
|
2813
|
-
* @returns true if all modules were unregistered, false if any were not found
|
|
2814
|
-
*/
|
|
2815
|
-
unregisterModules(...documentTypes: string[]): boolean;
|
|
2816
|
-
/**
|
|
2817
|
-
* Get a specific document model module by document type and optional version.
|
|
2818
|
-
* If version is not specified, returns the latest version.
|
|
2819
|
-
*
|
|
2820
|
-
* @param documentType The document type identifier
|
|
2821
|
-
* @param version Optional version number to retrieve
|
|
2822
|
-
* @returns The document model module
|
|
2823
|
-
* @throws ModuleNotFoundError if the document type or version is not registered
|
|
2824
|
-
*/
|
|
2825
|
-
getModule(documentType: string, version?: number): DocumentModelModule<any>;
|
|
3156
|
+
type ReactorFeatureFlags = {
|
|
2826
3157
|
/**
|
|
2827
|
-
*
|
|
2828
|
-
*
|
|
2829
|
-
*
|
|
3158
|
+
* Decide whether an operation may be admitted by building a decision model
|
|
3159
|
+
* over the document stream, rather than reading the deleted flag from the
|
|
3160
|
+
* document meta cache. Deletion then takes effect from the deleting
|
|
3161
|
+
* operation's position rather than for the whole document.
|
|
2830
3162
|
*/
|
|
2831
|
-
|
|
3163
|
+
documentDecisions: boolean;
|
|
2832
3164
|
/**
|
|
2833
|
-
*
|
|
3165
|
+
* Evaluate the auth policy by reading the auth scope as a second projection.
|
|
3166
|
+
* Requires documentDecisions.
|
|
2834
3167
|
*/
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
3168
|
+
authEnforcement: boolean;
|
|
3169
|
+
};
|
|
3170
|
+
/**
|
|
3171
|
+
* Configuration options for the job executor
|
|
3172
|
+
*/
|
|
3173
|
+
type JobExecutorConfig = {
|
|
3174
|
+
/** Feature flags; anything unset is off. */featureFlags?: Partial<ReactorFeatureFlags>; /** Maximum number of conflicting operations to skip when reshuffling. */
|
|
3175
|
+
maxSkipThreshold?: number; /** Maximum number of concurrent jobs to execute */
|
|
3176
|
+
maxConcurrency?: number; /** Maximum time in milliseconds a job can run before being considered timed out */
|
|
3177
|
+
jobTimeoutMs?: number; /** Base delay in milliseconds for exponential backoff retries */
|
|
3178
|
+
retryBaseDelayMs?: number; /** Maximum delay in milliseconds for exponential backoff retries */
|
|
3179
|
+
retryMaxDelayMs?: number;
|
|
3180
|
+
/** Maximum elapsed milliseconds before yielding to the main thread between actions.
|
|
3181
|
+
* Keeps the UI responsive when processing large batches. */
|
|
3182
|
+
yieldDeadlineMs?: number;
|
|
3183
|
+
};
|
|
3184
|
+
/**
|
|
3185
|
+
* Event types for the job executor
|
|
3186
|
+
*/
|
|
3187
|
+
declare const JobExecutorEventTypes: {
|
|
3188
|
+
readonly JOB_STARTED: 20000;
|
|
3189
|
+
readonly JOB_COMPLETED: 20001;
|
|
3190
|
+
readonly JOB_FAILED: 20002;
|
|
3191
|
+
readonly EXECUTOR_STARTED: 20003;
|
|
3192
|
+
readonly EXECUTOR_STOPPED: 20004;
|
|
3193
|
+
};
|
|
3194
|
+
/**
|
|
3195
|
+
* Event data for job execution events
|
|
3196
|
+
*/
|
|
3197
|
+
type JobStartedEvent = {
|
|
3198
|
+
job: Job;
|
|
3199
|
+
startedAt: string;
|
|
3200
|
+
/**
|
|
3201
|
+
* Identifier of the executor that took the job. For the worker pool this is
|
|
3202
|
+
* the thread-worker id (e.g. "reactor-worker-3"); for the in-process simple
|
|
3203
|
+
* manager it is "in-process-<index>". Optional for backwards compatibility
|
|
3204
|
+
* with consumers built before the field was added.
|
|
2842
3205
|
*/
|
|
2843
|
-
|
|
3206
|
+
workerId?: string;
|
|
3207
|
+
};
|
|
3208
|
+
type JobCompletedEvent = {
|
|
3209
|
+
job: Job;
|
|
3210
|
+
result: JobResult; /** See {@link JobStartedEvent.workerId}. */
|
|
3211
|
+
workerId?: string;
|
|
3212
|
+
};
|
|
3213
|
+
type JobFailedEvent = {
|
|
3214
|
+
job: Job;
|
|
3215
|
+
error: string;
|
|
3216
|
+
willRetry: boolean;
|
|
3217
|
+
retryCount: number; /** See {@link JobStartedEvent.workerId}. */
|
|
3218
|
+
workerId?: string;
|
|
3219
|
+
};
|
|
3220
|
+
type ExecutorStartedEvent = {
|
|
3221
|
+
config: JobExecutorConfig;
|
|
3222
|
+
startedAt: string;
|
|
3223
|
+
};
|
|
3224
|
+
type ExecutorStoppedEvent = {
|
|
3225
|
+
stoppedAt: string;
|
|
3226
|
+
graceful: boolean;
|
|
3227
|
+
};
|
|
3228
|
+
/**
|
|
3229
|
+
* Status information for the job executor manager
|
|
3230
|
+
*/
|
|
3231
|
+
type ExecutorManagerStatus = {
|
|
3232
|
+
/** Whether the manager is currently running */isRunning: boolean; /** Number of executor instances managed */
|
|
3233
|
+
numExecutors: number; /** Number of jobs currently being processed */
|
|
3234
|
+
activeJobs: number; /** Total number of jobs processed since start */
|
|
3235
|
+
totalJobsProcessed: number;
|
|
3236
|
+
};
|
|
3237
|
+
//#endregion
|
|
3238
|
+
//#region src/executor/interfaces.d.ts
|
|
3239
|
+
/**
|
|
3240
|
+
* Snapshot of the single in-flight slot maintained by an {@link IExecutorWorker}.
|
|
3241
|
+
*/
|
|
3242
|
+
type WorkerInFlightSnapshot = {
|
|
3243
|
+
correlationId: string;
|
|
3244
|
+
jobId: string;
|
|
3245
|
+
};
|
|
3246
|
+
/**
|
|
3247
|
+
* Outcome of a worker-side job execution.
|
|
3248
|
+
*
|
|
3249
|
+
* `result` mirrors the in-process `JobResult` exactly. `writeReady` carries
|
|
3250
|
+
* the operations + jobMeta the parent needs to emit `JOB_WRITE_READY`, and is
|
|
3251
|
+
* present only when the worker produced operations. It is absent on failure
|
|
3252
|
+
* and on success-with-no-operations.
|
|
3253
|
+
*/
|
|
3254
|
+
type WorkerExecutionOutcome = {
|
|
3255
|
+
result: JobResult;
|
|
3256
|
+
writeReady?: JobWriteReadyPayload;
|
|
3257
|
+
};
|
|
3258
|
+
/**
|
|
3259
|
+
* Parent-side handle for a single executor worker.
|
|
3260
|
+
*
|
|
3261
|
+
* Implementations wrap an IPC transport (worker_threads, child_process, or a
|
|
3262
|
+
* test fake) and expose a transport-agnostic surface that the worker-pool
|
|
3263
|
+
* manager uses to dispatch jobs. The handle owns one worker's lifecycle
|
|
3264
|
+
* (`start` -> `execute`* -> `shutdown`) and bounds its in-flight map to a
|
|
3265
|
+
* single entry; `SimpleJobExecutor` is single-threaded inside the worker, so
|
|
3266
|
+
* concurrent dispatches would race its caches.
|
|
3267
|
+
*/
|
|
3268
|
+
interface IExecutorWorker {
|
|
3269
|
+
/** Stable identifier of the worker (mirrors `InitMessage.workerId`). */
|
|
3270
|
+
readonly workerId: string;
|
|
3271
|
+
/** Zero-based index within the pool, used for sticky routing. */
|
|
3272
|
+
readonly index: number;
|
|
2844
3273
|
/**
|
|
2845
|
-
*
|
|
2846
|
-
*
|
|
2847
|
-
* @param documentType The document type identifier
|
|
2848
|
-
* @returns The highest version number registered for this document type
|
|
2849
|
-
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
3274
|
+
* Spawn the worker (if not already started), send the `init` payload and
|
|
3275
|
+
* resolve when the worker replies with `ready`.
|
|
2850
3276
|
*/
|
|
2851
|
-
|
|
3277
|
+
start(): Promise<void>;
|
|
2852
3278
|
/**
|
|
2853
|
-
*
|
|
2854
|
-
*
|
|
2855
|
-
*
|
|
2856
|
-
*
|
|
2857
|
-
*
|
|
3279
|
+
* Dispatch a job to the worker and resolve with its outcome — the
|
|
3280
|
+
* `JobResult` and, on success-with-operations, a `writeReady` payload
|
|
3281
|
+
* the parent will enrich and re-emit. Rejects with a transport-level
|
|
3282
|
+
* error if the worker exits, aborts, or times out before producing a
|
|
3283
|
+
* result.
|
|
2858
3284
|
*/
|
|
2859
|
-
|
|
3285
|
+
execute(job: Job, signal?: AbortSignal): Promise<WorkerExecutionOutcome>;
|
|
2860
3286
|
/**
|
|
2861
|
-
*
|
|
2862
|
-
*
|
|
2863
|
-
*
|
|
2864
|
-
|
|
2865
|
-
|
|
3287
|
+
* Request cancellation of the in-flight job (if any). The handle posts an
|
|
3288
|
+
* `abort` message; if the worker fails to reply within its grace window it
|
|
3289
|
+
* is force-terminated.
|
|
3290
|
+
*/
|
|
3291
|
+
abort(correlationId: string, reason?: string): void;
|
|
2866
3292
|
/**
|
|
2867
|
-
*
|
|
3293
|
+
* Stop the worker. When `graceful` is true the handle waits for the
|
|
3294
|
+
* in-flight job to settle (up to `graceMs`) before terminating; otherwise
|
|
3295
|
+
* the worker is terminated immediately.
|
|
3296
|
+
*/
|
|
3297
|
+
shutdown(graceful: boolean, graceMs?: number): Promise<void>;
|
|
3298
|
+
/**
|
|
3299
|
+
* Register an additional document model on the running worker. Resolves
|
|
3300
|
+
* when the worker replies with `model-loaded`; rejects when it replies
|
|
3301
|
+
* with `model-load-failed` or the worker exits before answering.
|
|
3302
|
+
*/
|
|
3303
|
+
loadModel(entry: ModelManifestEntry, signal?: AbortSignal): Promise<void>;
|
|
3304
|
+
/** True when no job is currently in flight. */
|
|
3305
|
+
isIdle(): boolean;
|
|
3306
|
+
/** Snapshot of the in-flight slot, or null when idle. */
|
|
3307
|
+
getInFlight(): WorkerInFlightSnapshot | null;
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Simple interface for executing a job.
|
|
3311
|
+
* A JobExecutor simply takes a job and executes it - nothing more.
|
|
3312
|
+
*/
|
|
3313
|
+
interface IJobExecutor {
|
|
3314
|
+
/**
|
|
3315
|
+
* Execute a single job.
|
|
3316
|
+
* @param job - The job to execute
|
|
3317
|
+
* @returns Promise that resolves to the job result
|
|
3318
|
+
*/
|
|
3319
|
+
executeJob(job: Job, signal?: AbortSignal): Promise<JobResult>;
|
|
3320
|
+
}
|
|
3321
|
+
/**
|
|
3322
|
+
* Interface for managing multiple job executors.
|
|
3323
|
+
* Listens for 'jobAvailable' events from the event bus, pulls jobs from the queue,
|
|
3324
|
+
* and coordinates the distribution of jobs across multiple executor instances.
|
|
3325
|
+
*/
|
|
3326
|
+
interface IJobExecutorManager {
|
|
3327
|
+
/**
|
|
3328
|
+
* Start the executor manager.
|
|
3329
|
+
* Begins listening for 'jobAvailable' events and dispatching to executors.
|
|
2868
3330
|
*
|
|
2869
|
-
* @param
|
|
2870
|
-
* @returns
|
|
2871
|
-
* @throws ManifestNotFoundError if no manifest is registered for the document type
|
|
3331
|
+
* @param numExecutors - Number of executor instances to create
|
|
3332
|
+
* @returns Promise that resolves when the manager is started
|
|
2872
3333
|
*/
|
|
2873
|
-
|
|
3334
|
+
start(numExecutors: number): Promise<void>;
|
|
2874
3335
|
/**
|
|
2875
|
-
*
|
|
2876
|
-
* Returns the sequence of upgrade transitions needed.
|
|
3336
|
+
* Stop the executor manager.
|
|
2877
3337
|
*
|
|
2878
|
-
* @param
|
|
2879
|
-
* @
|
|
2880
|
-
* @param toVersion The target version
|
|
2881
|
-
* @returns Array of upgrade transitions in order
|
|
2882
|
-
* @throws DowngradeNotSupportedError if toVersion is less than fromVersion
|
|
2883
|
-
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2884
|
-
* @throws MissingUpgradeTransitionError if any transition in the path is missing
|
|
3338
|
+
* @param graceful - Whether to wait for current jobs to complete
|
|
3339
|
+
* @returns Promise that resolves when the manager is stopped
|
|
2885
3340
|
*/
|
|
2886
|
-
|
|
3341
|
+
stop(graceful?: boolean): Promise<void>;
|
|
2887
3342
|
/**
|
|
2888
|
-
* Get
|
|
3343
|
+
* Get all managed executor instances.
|
|
2889
3344
|
*
|
|
2890
|
-
* @
|
|
2891
|
-
* @param fromVersion The starting version
|
|
2892
|
-
* @param toVersion The target version (must be fromVersion + 1)
|
|
2893
|
-
* @returns The upgrade reducer function
|
|
2894
|
-
* @throws InvalidUpgradeStepError if toVersion is not fromVersion + 1
|
|
2895
|
-
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2896
|
-
* @throws MissingUpgradeTransitionError if the transition is not found
|
|
3345
|
+
* @returns Array of executor instances
|
|
2897
3346
|
*/
|
|
2898
|
-
|
|
3347
|
+
getExecutors(): IJobExecutor[];
|
|
3348
|
+
/**
|
|
3349
|
+
* Get the current status of the manager.
|
|
3350
|
+
*
|
|
3351
|
+
* @returns The current manager status
|
|
3352
|
+
*/
|
|
3353
|
+
getStatus(): ExecutorManagerStatus;
|
|
2899
3354
|
}
|
|
2900
3355
|
//#endregion
|
|
2901
|
-
//#region src/
|
|
2902
|
-
|
|
3356
|
+
//#region src/job-tracker/interfaces.d.ts
|
|
3357
|
+
/**
|
|
3358
|
+
* Interface for tracking job lifecycle status.
|
|
3359
|
+
* Maintains job state throughout execution: PENDING → RUNNING → COMPLETED/FAILED.
|
|
3360
|
+
*/
|
|
3361
|
+
interface IJobTracker {
|
|
2903
3362
|
/**
|
|
2904
|
-
*
|
|
2905
|
-
*
|
|
2906
|
-
*
|
|
3363
|
+
* Register a new job with PENDING status.
|
|
3364
|
+
*
|
|
3365
|
+
* @param jobInfo - The job information to register
|
|
2907
3366
|
*/
|
|
2908
|
-
|
|
3367
|
+
registerJob(jobInfo: JobInfo): void;
|
|
2909
3368
|
/**
|
|
2910
|
-
*
|
|
3369
|
+
* Update a job's status to RUNNING.
|
|
3370
|
+
*
|
|
3371
|
+
* @param jobId - The job ID to mark as running
|
|
2911
3372
|
*/
|
|
2912
|
-
|
|
3373
|
+
markRunning(jobId: string): void;
|
|
2913
3374
|
/**
|
|
2914
|
-
*
|
|
2915
|
-
*
|
|
3375
|
+
* Mark a job as failed.
|
|
3376
|
+
*
|
|
3377
|
+
* @param jobId - The job ID to mark as failed
|
|
3378
|
+
* @param error - Error information including message and stack trace
|
|
3379
|
+
* @param job - Optional full job object for debugging purposes
|
|
2916
3380
|
*/
|
|
2917
|
-
|
|
3381
|
+
markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
|
|
2918
3382
|
/**
|
|
2919
|
-
*
|
|
3383
|
+
* Retrieve the current status of a job.
|
|
3384
|
+
*
|
|
3385
|
+
* @param jobId - The job ID to query
|
|
3386
|
+
* @returns The job information, or null if the job is not found
|
|
2920
3387
|
*/
|
|
2921
|
-
|
|
3388
|
+
getJobStatus(jobId: string): JobInfo | null;
|
|
2922
3389
|
/**
|
|
2923
|
-
*
|
|
3390
|
+
* Shutdown the job tracker and clean up resources.
|
|
3391
|
+
* Unsubscribes from all event bus subscriptions.
|
|
2924
3392
|
*/
|
|
2925
|
-
|
|
3393
|
+
shutdown(): void;
|
|
3394
|
+
}
|
|
3395
|
+
//#endregion
|
|
3396
|
+
//#region src/queue/interfaces.d.ts
|
|
3397
|
+
/**
|
|
3398
|
+
* Interface for a job queue that manages write operations.
|
|
3399
|
+
* Internally organizes jobs by documentId, scope, and branch to ensure proper ordering.
|
|
3400
|
+
* Emits events to the event bus when new jobs are available for consumption.
|
|
3401
|
+
*/
|
|
3402
|
+
interface IQueue {
|
|
3403
|
+
/**
|
|
3404
|
+
* Add a new job to the queue.
|
|
3405
|
+
* Jobs are automatically organized by documentId, scope, and branch internally.
|
|
3406
|
+
* Emits a 'jobAvailable' event to the event bus when the job is queued.
|
|
3407
|
+
* @param job - The job to add to the queue
|
|
3408
|
+
* @returns Promise that resolves when the job is queued
|
|
3409
|
+
*/
|
|
3410
|
+
enqueue(job: Job): Promise<void>;
|
|
3411
|
+
/**
|
|
3412
|
+
* Get the next job to execute for a specific document/scope/branch combination.
|
|
3413
|
+
* @param documentId - The document ID to get jobs for
|
|
3414
|
+
* @param scope - The scope to get jobs for
|
|
3415
|
+
* @param branch - The branch to get jobs for
|
|
3416
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3417
|
+
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
3418
|
+
*/
|
|
3419
|
+
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3420
|
+
/**
|
|
3421
|
+
* Get the next available job from any queue.
|
|
3422
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3423
|
+
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
3424
|
+
*/
|
|
3425
|
+
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3426
|
+
/**
|
|
3427
|
+
* Get the next available job whose routing metadata satisfies the predicate.
|
|
3428
|
+
* Walks ready sub-queue heads in queue insertion order, skips heads whose document
|
|
3429
|
+
* is currently executing (same isDocumentExecuting gate as dequeueNext), and returns
|
|
3430
|
+
* the first head for which predicate returns true.
|
|
3431
|
+
* Returns null when paused, when nothing matches, or when the queue is empty.
|
|
3432
|
+
* Rejects if signal is already aborted.
|
|
3433
|
+
* @param predicate - Filter applied to JobRoutingMeta of each candidate head
|
|
3434
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3435
|
+
* @returns Promise that resolves to the first matching job execution handle or null
|
|
3436
|
+
*/
|
|
3437
|
+
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3438
|
+
/**
|
|
3439
|
+
* Get the current size of the queue for a specific document/scope/branch.
|
|
3440
|
+
* @param documentId - The document ID
|
|
3441
|
+
* @param scope - The scope
|
|
3442
|
+
* @param branch - The branch
|
|
3443
|
+
* @returns Promise that resolves to the number of jobs in the queue
|
|
3444
|
+
*/
|
|
3445
|
+
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
3446
|
+
/**
|
|
3447
|
+
* Get the total size of all queues.
|
|
3448
|
+
* @returns Promise that resolves to the total number of jobs across all queues
|
|
3449
|
+
*/
|
|
3450
|
+
totalSize(): Promise<number>;
|
|
3451
|
+
/**
|
|
3452
|
+
* Remove a specific job from the queue.
|
|
3453
|
+
* @param jobId - The ID of the job to remove
|
|
3454
|
+
* @returns Promise that resolves to true if job was removed, false if not found
|
|
3455
|
+
*/
|
|
3456
|
+
remove(jobId: string): Promise<boolean>;
|
|
3457
|
+
/**
|
|
3458
|
+
* Clear all jobs for a specific document/scope/branch combination.
|
|
3459
|
+
* @param documentId - The document ID
|
|
3460
|
+
* @param scope - The scope
|
|
3461
|
+
* @param branch - The branch
|
|
3462
|
+
* @returns Promise that resolves when the queue is cleared
|
|
3463
|
+
*/
|
|
3464
|
+
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
3465
|
+
/**
|
|
3466
|
+
* Clear all jobs from all queues.
|
|
3467
|
+
* @returns Promise that resolves when all queues are cleared
|
|
3468
|
+
*/
|
|
3469
|
+
clearAll(): Promise<void>;
|
|
3470
|
+
/**
|
|
3471
|
+
* Check if there are any jobs in the queue.
|
|
3472
|
+
* @returns Promise that resolves to true if there are jobs, false otherwise
|
|
3473
|
+
*/
|
|
3474
|
+
hasJobs(): Promise<boolean>;
|
|
3475
|
+
/**
|
|
3476
|
+
* Mark a job as completed.
|
|
3477
|
+
* @param jobId - The ID of the job to mark as completed
|
|
3478
|
+
* @returns Promise that resolves when the job is marked as completed
|
|
3479
|
+
*/
|
|
3480
|
+
completeJob(jobId: string): Promise<void>;
|
|
3481
|
+
/**
|
|
3482
|
+
* Mark a job as failed.
|
|
3483
|
+
* @param jobId - The ID of the job to mark as failed
|
|
3484
|
+
* @param error - Optional error information
|
|
3485
|
+
* @returns Promise that resolves when the job is marked as failed
|
|
3486
|
+
*/
|
|
3487
|
+
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
3488
|
+
/**
|
|
3489
|
+
* Retry a failed job.
|
|
3490
|
+
* @param jobId - The ID of the job to retry
|
|
3491
|
+
* @param error - Optional error information from the failure
|
|
3492
|
+
* @param accounting - Whether the attempt counts against the job's retry
|
|
3493
|
+
* limit; defaults to {@link RetryAccounting.CountAgainstLimit}
|
|
3494
|
+
* @returns Promise that resolves when the job is requeued for retry
|
|
3495
|
+
*/
|
|
3496
|
+
retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
|
|
3497
|
+
/**
|
|
3498
|
+
* Returns true if and only if all jobs have been resolved.
|
|
3499
|
+
*/
|
|
3500
|
+
get isDrained(): boolean;
|
|
3501
|
+
/**
|
|
3502
|
+
* Blocks the queue from accepting new jobs.
|
|
3503
|
+
* @param onDrained - Optional callback to call when the queue is drained
|
|
3504
|
+
*/
|
|
3505
|
+
block(onDrained?: () => void): void;
|
|
3506
|
+
/**
|
|
3507
|
+
* Unblocks the queue from accepting new jobs.
|
|
3508
|
+
*/
|
|
3509
|
+
unblock(): void;
|
|
3510
|
+
}
|
|
3511
|
+
//#endregion
|
|
3512
|
+
//#region src/read-models/types.d.ts
|
|
3513
|
+
interface ViewStateTable {
|
|
3514
|
+
readModelId: string;
|
|
3515
|
+
lastOrdinal: number;
|
|
3516
|
+
lastOperationTimestamp: Generated<Date>;
|
|
3517
|
+
}
|
|
3518
|
+
interface DocumentSnapshotTable {
|
|
3519
|
+
id: Generated<string>;
|
|
3520
|
+
documentId: string;
|
|
3521
|
+
slug: string | null;
|
|
3522
|
+
name: string | null;
|
|
3523
|
+
scope: string;
|
|
3524
|
+
branch: string;
|
|
3525
|
+
content: unknown;
|
|
3526
|
+
documentType: string;
|
|
3527
|
+
lastOperationIndex: number;
|
|
3528
|
+
lastOperationHash: string;
|
|
3529
|
+
lastUpdatedAt: Generated<Date>;
|
|
3530
|
+
snapshotVersion: Generated<number>;
|
|
3531
|
+
identifiers: unknown;
|
|
3532
|
+
metadata: unknown;
|
|
3533
|
+
isDeleted: Generated<boolean>;
|
|
3534
|
+
deletedAt: Date | null;
|
|
3535
|
+
}
|
|
3536
|
+
interface SlugMappingTable {
|
|
3537
|
+
slug: string;
|
|
3538
|
+
documentId: string;
|
|
3539
|
+
scope: string;
|
|
3540
|
+
branch: string;
|
|
3541
|
+
createdAt: Generated<Date>;
|
|
3542
|
+
updatedAt: Generated<Date>;
|
|
3543
|
+
}
|
|
3544
|
+
interface ProcessorCursorTable {
|
|
3545
|
+
processorId: string;
|
|
3546
|
+
factoryId: string;
|
|
3547
|
+
driveId: string;
|
|
3548
|
+
processorIndex: number;
|
|
3549
|
+
lastOrdinal: Generated<number>;
|
|
3550
|
+
status: Generated<string>;
|
|
3551
|
+
lastError: string | null;
|
|
3552
|
+
lastErrorTimestamp: Date | null;
|
|
3553
|
+
createdAt: Generated<Date>;
|
|
3554
|
+
updatedAt: Generated<Date>;
|
|
3555
|
+
}
|
|
3556
|
+
interface DocumentViewDatabase {
|
|
3557
|
+
ViewState: ViewStateTable;
|
|
3558
|
+
DocumentSnapshot: DocumentSnapshotTable;
|
|
3559
|
+
SlugMapping: SlugMappingTable;
|
|
3560
|
+
ProcessorCursor: ProcessorCursorTable;
|
|
3561
|
+
}
|
|
3562
|
+
type InsertableDocumentSnapshot = Insertable<DocumentSnapshotTable>;
|
|
3563
|
+
//#endregion
|
|
3564
|
+
//#region src/shared/consistency-tracker.d.ts
|
|
3565
|
+
interface IConsistencyTracker {
|
|
3566
|
+
/**
|
|
3567
|
+
* Updates the tracker with new operation indexes.
|
|
3568
|
+
* When multiple coordinates have the same key, keeps the highest operationIndex.
|
|
3569
|
+
* Resolves any pending waiters whose coordinates are now satisfied.
|
|
3570
|
+
*/
|
|
3571
|
+
update(coordinates: ConsistencyCoordinate[]): void;
|
|
3572
|
+
/**
|
|
3573
|
+
* Returns the latest operation index for a given key, or undefined if not tracked.
|
|
3574
|
+
*/
|
|
3575
|
+
getLatest(key: ConsistencyKey): number | undefined;
|
|
3576
|
+
/**
|
|
3577
|
+
* Returns a promise that resolves when all coordinates are satisfied.
|
|
3578
|
+
* Rejects if the timeout is reached or the signal is aborted.
|
|
3579
|
+
*/
|
|
3580
|
+
waitFor(coordinates: ConsistencyCoordinate[], timeoutMs?: number, signal?: AbortSignal): Promise<void>;
|
|
3581
|
+
/**
|
|
3582
|
+
* Returns a serializable snapshot of the current state.
|
|
3583
|
+
*/
|
|
3584
|
+
serialize(): Array<[ConsistencyKey, number]>;
|
|
3585
|
+
/**
|
|
3586
|
+
* Restores state from a serialized snapshot.
|
|
3587
|
+
*/
|
|
3588
|
+
hydrate(entries: Array<[ConsistencyKey, number]>): void;
|
|
2926
3589
|
}
|
|
2927
3590
|
/**
|
|
2928
3591
|
* Creates a consistency key from documentId, scope, and branch.
|
|
@@ -2946,134 +3609,6 @@ declare class ConsistencyTracker implements IConsistencyTracker {
|
|
|
2946
3609
|
private removeWaiter;
|
|
2947
3610
|
}
|
|
2948
3611
|
//#endregion
|
|
2949
|
-
//#region src/storage/kysely/types.d.ts
|
|
2950
|
-
interface OperationTable {
|
|
2951
|
-
id: Generated<number>;
|
|
2952
|
-
jobId: string;
|
|
2953
|
-
opId: string;
|
|
2954
|
-
prevOpId: string;
|
|
2955
|
-
writeTimestampUtcMs: Generated<Date>;
|
|
2956
|
-
documentId: string;
|
|
2957
|
-
documentType: string;
|
|
2958
|
-
scope: string;
|
|
2959
|
-
branch: string;
|
|
2960
|
-
timestampUtcMs: Date;
|
|
2961
|
-
index: number;
|
|
2962
|
-
action: unknown;
|
|
2963
|
-
skip: number;
|
|
2964
|
-
error?: string | null;
|
|
2965
|
-
hash: string;
|
|
2966
|
-
}
|
|
2967
|
-
interface KeyframeTable {
|
|
2968
|
-
id: Generated<number>;
|
|
2969
|
-
documentId: string;
|
|
2970
|
-
documentType: string;
|
|
2971
|
-
scope: string;
|
|
2972
|
-
branch: string;
|
|
2973
|
-
revision: number;
|
|
2974
|
-
document: unknown;
|
|
2975
|
-
createdAt: Generated<Date>;
|
|
2976
|
-
}
|
|
2977
|
-
interface DocumentCollectionTable {
|
|
2978
|
-
documentId: string;
|
|
2979
|
-
collectionId: string;
|
|
2980
|
-
joinedOrdinal: bigint;
|
|
2981
|
-
leftOrdinal: bigint | null;
|
|
2982
|
-
}
|
|
2983
|
-
interface OperationIndexOperationTable {
|
|
2984
|
-
ordinal: Generated<number>;
|
|
2985
|
-
opId: string;
|
|
2986
|
-
documentId: string;
|
|
2987
|
-
documentType: string;
|
|
2988
|
-
scope: string;
|
|
2989
|
-
branch: string;
|
|
2990
|
-
timestampUtcMs: string;
|
|
2991
|
-
writeTimestampUtcMs: Generated<Date>;
|
|
2992
|
-
index: number;
|
|
2993
|
-
skip: number;
|
|
2994
|
-
hash: string;
|
|
2995
|
-
action: unknown;
|
|
2996
|
-
sourceRemote: Generated<string>;
|
|
2997
|
-
}
|
|
2998
|
-
interface SyncRemoteTable {
|
|
2999
|
-
name: string;
|
|
3000
|
-
collection_id: string;
|
|
3001
|
-
channel_type: string;
|
|
3002
|
-
channel_id: string;
|
|
3003
|
-
remote_name: string;
|
|
3004
|
-
channel_parameters: unknown;
|
|
3005
|
-
filter_document_ids: unknown;
|
|
3006
|
-
filter_scopes: unknown;
|
|
3007
|
-
filter_branch: string;
|
|
3008
|
-
push_state: string;
|
|
3009
|
-
push_last_success_utc_ms: string | null;
|
|
3010
|
-
push_last_failure_utc_ms: string | null;
|
|
3011
|
-
push_failure_count: number;
|
|
3012
|
-
pull_state: string;
|
|
3013
|
-
pull_last_success_utc_ms: string | null;
|
|
3014
|
-
pull_last_failure_utc_ms: string | null;
|
|
3015
|
-
pull_failure_count: number;
|
|
3016
|
-
created_at: Generated<Date>;
|
|
3017
|
-
updated_at: Generated<Date>;
|
|
3018
|
-
}
|
|
3019
|
-
interface SyncCursorTable {
|
|
3020
|
-
remote_name: string;
|
|
3021
|
-
cursor_type: string;
|
|
3022
|
-
cursor_ordinal: bigint;
|
|
3023
|
-
last_synced_at_utc_ms: string | null;
|
|
3024
|
-
updated_at: Generated<Date>;
|
|
3025
|
-
}
|
|
3026
|
-
/**
|
|
3027
|
-
* Kysely table definition for the `sync_dead_letters` table.
|
|
3028
|
-
*/
|
|
3029
|
-
interface SyncDeadLetterTable {
|
|
3030
|
-
ordinal: Generated<number>;
|
|
3031
|
-
id: string;
|
|
3032
|
-
job_id: string;
|
|
3033
|
-
job_dependencies: unknown;
|
|
3034
|
-
remote_name: string;
|
|
3035
|
-
document_id: string;
|
|
3036
|
-
scopes: unknown;
|
|
3037
|
-
branch: string;
|
|
3038
|
-
operations: unknown;
|
|
3039
|
-
error_source: string;
|
|
3040
|
-
error_message: string;
|
|
3041
|
-
created_at: Generated<Date>;
|
|
3042
|
-
}
|
|
3043
|
-
interface Database$1 {
|
|
3044
|
-
Operation: OperationTable;
|
|
3045
|
-
Keyframe: KeyframeTable;
|
|
3046
|
-
document_collections: DocumentCollectionTable;
|
|
3047
|
-
operation_index_operations: OperationIndexOperationTable;
|
|
3048
|
-
sync_remotes: SyncRemoteTable;
|
|
3049
|
-
sync_cursors: SyncCursorTable;
|
|
3050
|
-
sync_dead_letters: SyncDeadLetterTable;
|
|
3051
|
-
}
|
|
3052
|
-
interface DocumentTable {
|
|
3053
|
-
id: string;
|
|
3054
|
-
createdAt: Generated<Date>;
|
|
3055
|
-
updatedAt: Generated<Date>;
|
|
3056
|
-
}
|
|
3057
|
-
interface DocumentRelationshipTable {
|
|
3058
|
-
id: Generated<string>;
|
|
3059
|
-
sourceId: string;
|
|
3060
|
-
targetId: string;
|
|
3061
|
-
relationshipType: string;
|
|
3062
|
-
metadata: unknown;
|
|
3063
|
-
createdAt: Generated<Date>;
|
|
3064
|
-
updatedAt: Generated<Date>;
|
|
3065
|
-
}
|
|
3066
|
-
interface IndexerStateTable {
|
|
3067
|
-
id: Generated<number>;
|
|
3068
|
-
lastOperationId: number;
|
|
3069
|
-
lastOperationTimestamp: Generated<Date>;
|
|
3070
|
-
}
|
|
3071
|
-
interface DocumentIndexerDatabase {
|
|
3072
|
-
Document: DocumentTable;
|
|
3073
|
-
DocumentRelationship: DocumentRelationshipTable;
|
|
3074
|
-
IndexerState: IndexerStateTable;
|
|
3075
|
-
}
|
|
3076
|
-
//#endregion
|
|
3077
3612
|
//#region src/storage/pool-instrumentation.d.ts
|
|
3078
3613
|
/**
|
|
3079
3614
|
* Snapshot of a pg.Pool's internal counters at a point in time.
|
|
@@ -3137,7 +3672,13 @@ declare class PollingChannelError extends Error {
|
|
|
3137
3672
|
declare class ChannelError extends Error {
|
|
3138
3673
|
source: ChannelErrorSource;
|
|
3139
3674
|
error: Error;
|
|
3140
|
-
|
|
3675
|
+
/**
|
|
3676
|
+
* The classification when something other than the error carries it. Absent
|
|
3677
|
+
* means derive it from `error.name`; a dead letter mirrored from a peer sets it,
|
|
3678
|
+
* because only the message crosses the wire.
|
|
3679
|
+
*/
|
|
3680
|
+
readonly errorType?: SyncOperationErrorType;
|
|
3681
|
+
constructor(source: ChannelErrorSource, error: Error, errorType?: SyncOperationErrorType);
|
|
3141
3682
|
}
|
|
3142
3683
|
//#endregion
|
|
3143
3684
|
//#region src/sync/sync-operation.d.ts
|
|
@@ -3815,12 +4356,6 @@ declare class DriveClient implements IDriveClient {
|
|
|
3815
4356
|
private removeFileNode;
|
|
3816
4357
|
}
|
|
3817
4358
|
//#endregion
|
|
3818
|
-
//#region src/cache/collection-membership-cache.d.ts
|
|
3819
|
-
interface ICollectionMembershipCache {
|
|
3820
|
-
getCollectionsForDocuments(documentIds: string[]): Promise<Record<string, string[]>>;
|
|
3821
|
-
invalidate(documentId: string): void;
|
|
3822
|
-
}
|
|
3823
|
-
//#endregion
|
|
3824
4359
|
//#region src/registry/document-model-resolver.d.ts
|
|
3825
4360
|
interface IDocumentModelResolver {
|
|
3826
4361
|
ensureModelLoaded(documentType: string): Promise<void>;
|
|
@@ -3880,38 +4415,6 @@ declare class NullDocumentModelResolver implements IDocumentModelResolver {
|
|
|
3880
4415
|
*/
|
|
3881
4416
|
type WorkerFactory = (index: number) => IExecutorWorker;
|
|
3882
4417
|
//#endregion
|
|
3883
|
-
//#region src/cache/write-cache-types.d.ts
|
|
3884
|
-
/**
|
|
3885
|
-
* Configuration options for the write cache
|
|
3886
|
-
*/
|
|
3887
|
-
type WriteCacheConfig = {
|
|
3888
|
-
/** Maximum number of document streams to cache (LRU eviction). Default: 1000 */maxDocuments: number; /** Number of snapshots to keep in each document's ring buffer. Default: 10 */
|
|
3889
|
-
ringBufferSize: number; /** Persist a keyframe snapshot every N revisions. Default: 10 */
|
|
3890
|
-
keyframeInterval: number;
|
|
3891
|
-
};
|
|
3892
|
-
/**
|
|
3893
|
-
* Unique identifier for a document stream
|
|
3894
|
-
*/
|
|
3895
|
-
type DocumentStreamKey = {
|
|
3896
|
-
/** Document identifier */documentId: string; /** Operation scope */
|
|
3897
|
-
scope: string; /** Branch name */
|
|
3898
|
-
branch: string;
|
|
3899
|
-
};
|
|
3900
|
-
/**
|
|
3901
|
-
* A cached document snapshot at a specific revision
|
|
3902
|
-
*/
|
|
3903
|
-
type CachedSnapshot = {
|
|
3904
|
-
/** The revision number of this snapshot */revision: number; /** The document state at this revision */
|
|
3905
|
-
document: PHDocument;
|
|
3906
|
-
};
|
|
3907
|
-
/**
|
|
3908
|
-
* Serialized keyframe snapshot for K/V store persistence
|
|
3909
|
-
*/
|
|
3910
|
-
type KeyframeSnapshot = {
|
|
3911
|
-
/** The revision number of this keyframe */revision: number; /** Serialized document state */
|
|
3912
|
-
document: string;
|
|
3913
|
-
};
|
|
3914
|
-
//#endregion
|
|
3915
4418
|
//#region src/projection/protocol.d.ts
|
|
3916
4419
|
/**
|
|
3917
4420
|
* Identifier for a built-in read model the projection worker materializes
|
|
@@ -4095,973 +4598,635 @@ type ProjectionShardManagerConfig = {
|
|
|
4095
4598
|
shardCount: number;
|
|
4096
4599
|
db: DbConfig;
|
|
4097
4600
|
models: ModelManifestEntry[];
|
|
4098
|
-
preReadyKinds: BuiltInReadModelKind[];
|
|
4099
|
-
postReadyKinds: BuiltInReadModelKind[];
|
|
4100
|
-
factory: ProjectionWorkerFactory;
|
|
4101
|
-
logger: ILogger;
|
|
4102
|
-
hostBus: IEventBus;
|
|
4103
|
-
initTimeoutMs?: number;
|
|
4104
|
-
shutdownGraceMs?: number;
|
|
4105
|
-
drainTimeoutMs?: number;
|
|
4106
|
-
chainDepthReportIntervalMs?: number;
|
|
4107
|
-
/**
|
|
4108
|
-
* Host-side forwarding instrumentations indexed by shard index. The
|
|
4109
|
-
* manager routes each shard's `pool-acquire-samples` message to the
|
|
4110
|
-
* matching forwarder so the host's OpenTelemetry instrumentation records
|
|
4111
|
-
* acquire-wait latencies as if each shard's pg.Pool were local.
|
|
4112
|
-
*/
|
|
4113
|
-
poolInstrumentations?: ForwardingPoolInstrumentation[];
|
|
4114
|
-
};
|
|
4115
|
-
//#endregion
|
|
4116
|
-
//#region src/signer/types.d.ts
|
|
4117
|
-
/**
|
|
4118
|
-
* Configuration for signing and verification.
|
|
4119
|
-
*/
|
|
4120
|
-
type SignerConfig = {
|
|
4121
|
-
/**
|
|
4122
|
-
* The signer used to sign actions before submission.
|
|
4123
|
-
*/
|
|
4124
|
-
signer: ISigner;
|
|
4125
|
-
/**
|
|
4126
|
-
* Optional handler for verifying signatures on incoming operations.
|
|
4127
|
-
* If not provided, signature verification will be skipped.
|
|
4128
|
-
*/
|
|
4129
|
-
verifier?: SignatureVerificationHandler;
|
|
4130
|
-
};
|
|
4131
|
-
//#endregion
|
|
4132
|
-
//#region src/storage/migrations/types.d.ts
|
|
4133
|
-
type MigrationStrategy = "auto" | "manual" | "none";
|
|
4134
|
-
interface MigrationResult {
|
|
4135
|
-
success: boolean;
|
|
4136
|
-
migrationsExecuted: string[];
|
|
4137
|
-
error?: Error;
|
|
4138
|
-
}
|
|
4139
|
-
//#endregion
|
|
4140
|
-
//#region src/sync/sync-builder.d.ts
|
|
4141
|
-
declare class SyncBuilder {
|
|
4142
|
-
private channelFactory?;
|
|
4143
|
-
private remoteStorage?;
|
|
4144
|
-
private cursorStorage?;
|
|
4145
|
-
private deadLetterStorage?;
|
|
4146
|
-
private config;
|
|
4147
|
-
withChannelFactory(factory: IChannelFactory): this;
|
|
4148
|
-
withRemoteStorage(storage: ISyncRemoteStorage): this;
|
|
4149
|
-
withCursorStorage(storage: ISyncCursorStorage): this;
|
|
4150
|
-
withDeadLetterStorage(storage: ISyncDeadLetterStorage): this;
|
|
4151
|
-
withMaxDeadLettersPerRemote(limit: number): this;
|
|
4152
|
-
withMaxInboxBatchSize(limit: number): this;
|
|
4153
|
-
build(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): ISyncManager;
|
|
4154
|
-
buildModule(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): InProcessSyncModule;
|
|
4155
|
-
}
|
|
4156
|
-
//#endregion
|
|
4157
|
-
//#region src/core/reactor-builder.d.ts
|
|
4158
|
-
/**
|
|
4159
|
-
* Dependencies provided to read-model factories registered via
|
|
4160
|
-
* `withReadModelFactory`. These are constructed inside `buildModule()`, which
|
|
4161
|
-
* is why factory-based registration is needed for read models that depend on
|
|
4162
|
-
* them (`BaseReadModel` subclasses, in particular).
|
|
4163
|
-
*/
|
|
4164
|
-
interface ReadModelFactoryDeps {
|
|
4165
|
-
operationIndex: IOperationIndex;
|
|
4166
|
-
writeCache: IWriteCache;
|
|
4167
|
-
processorManagerConsistencyTracker: IConsistencyTracker;
|
|
4168
|
-
}
|
|
4169
|
-
/**
|
|
4170
|
-
* Factory that builds a pre-ready read model from internal reactor
|
|
4171
|
-
* dependencies once they are available. Awaited during `buildModule()`.
|
|
4172
|
-
*/
|
|
4173
|
-
type ReadModelFactory = (deps: ReadModelFactoryDeps) => IReadModel | Promise<IReadModel>;
|
|
4174
|
-
type WorkerPoolBase = {
|
|
4175
|
-
/** Number of worker threads to spawn; also the sticky-routing modulus. */numWorkers: number;
|
|
4176
|
-
/**
|
|
4177
|
-
* Factory spec the default transport's workers import to instantiate
|
|
4178
|
-
* their signature verifier. Omitted = no executor-side verification,
|
|
4179
|
-
* parity with the in-process executor's default.
|
|
4180
|
-
*/
|
|
4181
|
-
verifier?: SignatureVerifierSpec;
|
|
4182
|
-
};
|
|
4183
|
-
/**
|
|
4184
|
-
* Executor worker-pool configuration. Either `db` (default thread
|
|
4185
|
-
* transport; each worker opens its own Postgres pool) or a custom
|
|
4186
|
-
* `factory` transport is required by construction — an enabled pool
|
|
4187
|
-
* without connection info is unrepresentable.
|
|
4188
|
-
*/
|
|
4189
|
-
type WorkerPoolOptions = (WorkerPoolBase & {
|
|
4190
|
-
db: DbConfig;
|
|
4191
|
-
factory?: WorkerFactory;
|
|
4192
|
-
}) | (WorkerPoolBase & {
|
|
4193
|
-
db?: DbConfig;
|
|
4194
|
-
factory: WorkerFactory;
|
|
4195
|
-
});
|
|
4196
|
-
/**
|
|
4197
|
-
* Caller-facing config for {@link ReactorBuilder.withProjectionShards}.
|
|
4198
|
-
* When set, the builder replaces the in-process
|
|
4199
|
-
* {@link ReadModelCoordinator} with a {@link ProjectionShardManager} that
|
|
4200
|
-
* fans JOB_WRITE_READY events to N projection workers sharded by
|
|
4201
|
-
* documentId.
|
|
4202
|
-
*
|
|
4203
|
-
* @see Sharded projection workers sub-feature brief
|
|
4204
|
-
* (Powerhouse board wiki id: eb26f01f-8f68-4918-a6f6-ac7a4679b533)
|
|
4205
|
-
*/
|
|
4206
|
-
type ProjectionShardBuilderConfig = {
|
|
4207
|
-
shardCount: number;
|
|
4208
|
-
preReadyKinds: BuiltInReadModelKind[];
|
|
4209
|
-
postReadyKinds: BuiltInReadModelKind[];
|
|
4210
|
-
/**
|
|
4211
|
-
* Connection info for the projection workers' own pools. Falls back to
|
|
4212
|
-
* the executor worker pool's `db` when {@link ReactorBuilder.withWorkerPool}
|
|
4213
|
-
* is configured with one.
|
|
4214
|
-
*/
|
|
4215
|
-
db?: DbConfig;
|
|
4216
|
-
poolSize?: number;
|
|
4217
|
-
initTimeoutMs?: number;
|
|
4218
|
-
shutdownGraceMs?: number;
|
|
4219
|
-
drainTimeoutMs?: number;
|
|
4220
|
-
chainDepthReportIntervalMs?: number;
|
|
4221
|
-
};
|
|
4222
|
-
declare class ReactorBuilder {
|
|
4223
|
-
private logger?;
|
|
4224
|
-
private documentModelSources;
|
|
4225
|
-
private upgradeManifests;
|
|
4226
|
-
private features;
|
|
4227
|
-
private readModels;
|
|
4228
|
-
private readModelFactories;
|
|
4229
|
-
private executorManager;
|
|
4230
|
-
private executorConfig;
|
|
4231
|
-
private writeCacheConfig?;
|
|
4232
|
-
private migrationStrategy;
|
|
4233
|
-
private syncBuilder?;
|
|
4234
|
-
private eventBus?;
|
|
4235
|
-
private readModelCoordinator?;
|
|
4236
|
-
private signatureVerifier?;
|
|
4237
|
-
private kyselyInstance?;
|
|
4238
|
-
private signalHandlersEnabled;
|
|
4239
|
-
private queueInstance?;
|
|
4240
|
-
private channelScheme?;
|
|
4241
|
-
private jwtHandler?;
|
|
4242
|
-
private documentModelLoader?;
|
|
4243
|
-
private shutdownHooks;
|
|
4244
|
-
private driveContainerTypes;
|
|
4245
|
-
private workerPool?;
|
|
4246
|
-
private resolvedModelManifest?;
|
|
4247
|
-
private projectionShardConfig?;
|
|
4248
|
-
private projectionWorkerFactory?;
|
|
4249
|
-
private instrumentedPools;
|
|
4250
|
-
withLogger(logger: ILogger): this;
|
|
4251
|
-
/**
|
|
4252
|
-
* Register document-model sources: live modules, importable files, or
|
|
4253
|
-
* importable packages. Appends across calls. At `buildModule()` every
|
|
4254
|
-
* source is resolved host-side and registered on the registry; file and
|
|
4255
|
-
* package sources additionally form the worker manifest when the worker
|
|
4256
|
-
* pool is enabled (live modules cannot cross a thread boundary).
|
|
4257
|
-
*/
|
|
4258
|
-
withDocumentModelSources(sources: DocumentModelSource[]): this;
|
|
4259
|
-
withUpgradeManifests(manifests: UpgradeManifest<readonly number[]>[]): this;
|
|
4260
|
-
withFeatures(features: ReactorFeatures): this;
|
|
4261
|
-
withReadModel(readModel: IReadModel): this;
|
|
4262
|
-
/**
|
|
4263
|
-
* Register a factory that builds a pre-ready read model after the reactor's
|
|
4264
|
-
* internal `operationIndex`, `writeCache`, and processor-manager consistency
|
|
4265
|
-
* tracker are constructed. Use this for read models (e.g. `BaseReadModel`
|
|
4266
|
-
* subclasses) that need those dependencies and therefore cannot be built
|
|
4267
|
-
* before calling `buildModule()`.
|
|
4268
|
-
*/
|
|
4269
|
-
withReadModelFactory(factory: ReadModelFactory): this;
|
|
4270
|
-
withReadModelCoordinator(readModelCoordinator: IReadModelCoordinator): this;
|
|
4271
|
-
withExecutor(executor: IJobExecutorManager): this;
|
|
4272
|
-
withExecutorConfig(config: Partial<JobExecutorConfig>): this;
|
|
4273
|
-
withWriteCacheConfig(config: Partial<WriteCacheConfig>): this;
|
|
4274
|
-
withDriveContainerTypes(types: string[]): this;
|
|
4275
|
-
withMigrationStrategy(strategy: MigrationStrategy): this;
|
|
4276
|
-
withSync(syncBuilder: SyncBuilder): this;
|
|
4277
|
-
withEventBus(eventBus: IEventBus): this;
|
|
4278
|
-
withSignatureVerifier(verifier: SignatureVerificationHandler): this;
|
|
4279
|
-
withKysely(kysely: Kysely<Database>): this;
|
|
4280
|
-
/**
|
|
4281
|
-
* Register an externally-constructed pg.Pool's {@link PoolInstrumentation}
|
|
4282
|
-
* so it surfaces through {@link ReactorModule.pools}. Use this when the
|
|
4283
|
-
* caller built the pool itself (e.g. the in-process bench host wiring) so
|
|
4284
|
-
* pool acquire-wait and pool-stat metrics still emit. The builder also
|
|
4285
|
-
* registers any pool it constructs internally via {@link createPostgresDatabase}.
|
|
4286
|
-
*/
|
|
4287
|
-
withInstrumentedPool(instrumentation: PoolInstrumentation): this;
|
|
4288
|
-
withQueue(queue: IQueue): this;
|
|
4289
|
-
withChannelScheme(scheme: ChannelScheme): this;
|
|
4290
|
-
withJwtHandler(handler: JwtHandler): this;
|
|
4291
|
-
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4292
|
-
withSignalHandlers(): this;
|
|
4293
|
-
/**
|
|
4294
|
-
* Register an async cleanup hook to run during graceful shutdown. Hooks fire
|
|
4295
|
-
* after `reactor.kill()` resolves and before `database.destroy()`, so callers
|
|
4296
|
-
* that depend on the reactor (e.g. an HTTP API layered on top) can drain
|
|
4297
|
-
* cleanly before the underlying kysely instance is torn down. Hook errors are
|
|
4298
|
-
* logged and otherwise ignored — one bad hook cannot strand the rest of the
|
|
4299
|
-
* shutdown chain.
|
|
4300
|
-
*/
|
|
4301
|
-
withShutdownHook(hook: () => Promise<void>): this;
|
|
4302
|
-
/**
|
|
4303
|
-
* Enable the executor worker pool: N `node:worker_threads` workers with
|
|
4304
|
-
* sticky per-document routing, replacing the in-process executor. Calling
|
|
4305
|
-
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
4306
|
-
* (each worker opens its own Postgres pool; the parent database is built
|
|
4307
|
-
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
4308
|
-
* transport. `verifier` is imported by the default transport's workers;
|
|
4309
|
-
* omitted = no executor-side signature verification.
|
|
4310
|
-
*/
|
|
4311
|
-
withWorkerPool(options: WorkerPoolOptions): this;
|
|
4312
|
-
/**
|
|
4313
|
-
* Configure N sharded projection workers. When set, the builder replaces
|
|
4314
|
-
* the default in-process {@link ReadModelCoordinator} with a
|
|
4315
|
-
* {@link ProjectionShardManager}.
|
|
4316
|
-
*
|
|
4317
|
-
* Projection workers open their own Postgres pools from `config.db`,
|
|
4318
|
-
* falling back to the executor worker pool's `db` when
|
|
4319
|
-
* {@link withWorkerPool} is configured with one; only the `poolSize` is
|
|
4320
|
-
* overridden by {@link ProjectionShardBuilderConfig.poolSize}. The same
|
|
4321
|
-
* model manifest resolved from {@link withDocumentModelSources} is
|
|
4322
|
-
* forwarded.
|
|
4323
|
-
*/
|
|
4324
|
-
withProjectionShards(config: ProjectionShardBuilderConfig): this;
|
|
4325
|
-
/**
|
|
4326
|
-
* Inject a custom {@link ProjectionWorkerFactory}. When set, the builder
|
|
4327
|
-
* skips default thread-transport wiring for the projection shards and
|
|
4328
|
-
* hands the factory directly to {@link ProjectionShardManager}.
|
|
4329
|
-
*/
|
|
4330
|
-
withProjectionWorkerFactory(factory: ProjectionWorkerFactory): this;
|
|
4331
|
-
getResolvedModelManifest(): ModelManifestEntry[] | undefined;
|
|
4332
|
-
build(): Promise<IReactor>;
|
|
4333
|
-
buildModule(): Promise<InProcessReactorModule>;
|
|
4334
|
-
/**
|
|
4335
|
-
* The single Postgres config for the parent, executor workers, and
|
|
4336
|
-
* projection shards. They must share one physical database (the parent
|
|
4337
|
-
* writes operations; workers and shards read them), so divergent
|
|
4338
|
-
* worker/shard targets throw. `withKysely` overrides the parent and is not
|
|
4339
|
-
* validated against a worker/shard `db`.
|
|
4340
|
-
*/
|
|
4341
|
-
private resolveReactorDbConfig;
|
|
4342
|
-
/**
|
|
4343
|
-
* Constructs a {@link ProjectionShardManager} bound to the host event
|
|
4344
|
-
* bus. Builds the default thread-transport factory unless one was
|
|
4345
|
-
* injected via {@link withProjectionWorkerFactory}. Calls
|
|
4346
|
-
* `manager.startup()` so all N workers reach READY before the reactor
|
|
4347
|
-
* is returned to the caller.
|
|
4348
|
-
*/
|
|
4349
|
-
private createProjectionShardManager;
|
|
4350
|
-
private createDefaultProjectionWorkerFactory;
|
|
4351
|
-
/**
|
|
4352
|
-
* Default {@link WorkerFactory} used when the pool options carry no
|
|
4353
|
-
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
4354
|
-
* Worker pointing at the compiled `worker/entry.js`.
|
|
4355
|
-
*/
|
|
4356
|
-
private createDefaultWorkerFactory;
|
|
4357
|
-
/**
|
|
4358
|
-
* Builds the parent Kysely instance against a real Postgres server using
|
|
4359
|
-
* the same {@link DbConfig} the workers receive at init. Used in the
|
|
4360
|
-
* worker-pool path so the parent reactor and each worker thread share
|
|
4361
|
-
* storage; PGlite cannot be shared across threads. The constructed pool
|
|
4362
|
-
* is wrapped with {@link instrumentPgPool} and the resulting
|
|
4363
|
-
* {@link PoolInstrumentation} is pushed onto {@link instrumentedPools} so
|
|
4364
|
-
* the reactor module exposes acquire-wait and pool-stat surfaces.
|
|
4365
|
-
*/
|
|
4366
|
-
private createPostgresDatabase;
|
|
4367
|
-
private attachSignalHandlers;
|
|
4368
|
-
}
|
|
4369
|
-
//#endregion
|
|
4370
|
-
//#region src/core/reactor-client-builder.d.ts
|
|
4371
|
-
/**
|
|
4372
|
-
* Builder class for constructing ReactorClient instances with proper configuration
|
|
4373
|
-
*/
|
|
4374
|
-
declare class ReactorClientBuilder {
|
|
4375
|
-
private logger?;
|
|
4376
|
-
private reactorBuilder?;
|
|
4377
|
-
private reactor?;
|
|
4378
|
-
private eventBus?;
|
|
4379
|
-
private documentIndexer?;
|
|
4380
|
-
private documentView?;
|
|
4381
|
-
private signer?;
|
|
4382
|
-
private signatureVerifier?;
|
|
4383
|
-
private subscriptionManager?;
|
|
4384
|
-
private jobAwaiter?;
|
|
4385
|
-
private documentModelLoader?;
|
|
4386
|
-
/**
|
|
4387
|
-
* Sets the logger for the ReactorClient.
|
|
4388
|
-
* @param logger - The logger to use.
|
|
4389
|
-
* @returns The ReactorClientBuilder instance.
|
|
4390
|
-
*/
|
|
4391
|
-
withLogger(logger: ILogger): this;
|
|
4392
|
-
/**
|
|
4393
|
-
* Either this or withReactor must be set.
|
|
4394
|
-
*/
|
|
4395
|
-
withReactorBuilder(reactorBuilder: ReactorBuilder): this;
|
|
4396
|
-
/**
|
|
4397
|
-
* Either this or withReactorBuilder must be set.
|
|
4398
|
-
*/
|
|
4399
|
-
withReactor(reactor: IReactor, eventBus: IEventBus, documentIndexer: IDocumentIndexer, documentView: IDocumentView): this;
|
|
4400
|
-
/**
|
|
4401
|
-
* Sets the signer configuration for signing and verifying actions.
|
|
4402
|
-
*
|
|
4403
|
-
* @param config - Either an ISigner for signing only, or a SignerConfig for both signing and verification
|
|
4404
|
-
*/
|
|
4405
|
-
withSigner(config: ISigner | SignerConfig): this;
|
|
4406
|
-
withSubscriptionManager(subscriptionManager: IReactorSubscriptionManager): this;
|
|
4407
|
-
withJobAwaiter(jobAwaiter: IJobAwaiter): this;
|
|
4408
|
-
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4409
|
-
build(): Promise<ReactorClient>;
|
|
4410
|
-
buildModule(): Promise<InProcessReactorClientModule>;
|
|
4411
|
-
}
|
|
4412
|
-
//#endregion
|
|
4413
|
-
//#region src/core/drive-container-types.d.ts
|
|
4414
|
-
declare const DEFAULT_DRIVE_CONTAINER_TYPES: ReadonlySet<string>;
|
|
4415
|
-
//#endregion
|
|
4416
|
-
//#region src/core/reactor.d.ts
|
|
4417
|
-
/**
|
|
4418
|
-
* This class implements the IReactor interface and serves as the main entry point
|
|
4419
|
-
* for the new Reactor architecture.
|
|
4420
|
-
*/
|
|
4421
|
-
declare class Reactor implements IReactor {
|
|
4422
|
-
private logger;
|
|
4423
|
-
private documentModelRegistry;
|
|
4424
|
-
private shutdownStatus;
|
|
4425
|
-
private setShutdown;
|
|
4426
|
-
private setCompleted;
|
|
4427
|
-
private queue;
|
|
4428
|
-
private jobTracker;
|
|
4429
|
-
private readModelCoordinator;
|
|
4430
|
-
private features;
|
|
4431
|
-
private documentView;
|
|
4432
|
-
private documentIndexer;
|
|
4433
|
-
private operationStore;
|
|
4434
|
-
private eventBus;
|
|
4435
|
-
private executorManager;
|
|
4436
|
-
constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager);
|
|
4437
|
-
kill(): ShutdownStatus;
|
|
4438
|
-
getDocumentModels(namespace?: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DocumentModelModule>>;
|
|
4439
|
-
get<TDocument extends PHDocument>(id: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4440
|
-
getBySlug<TDocument extends PHDocument>(slug: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4441
|
-
getByIdOrSlug<TDocument extends PHDocument>(identifier: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4442
|
-
getOutgoingRelationships(sourceId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4443
|
-
getIncomingRelationships(targetId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4444
|
-
getOperations(documentId: string, view?: ViewFilter, filter?: OperationFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<Record<string, PagedResults<Operation>>>;
|
|
4445
|
-
find(search: SearchFilter, view?: ViewFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<PHDocument>>;
|
|
4446
|
-
create(document: PHDocument, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4447
|
-
deleteDocument(id: string, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4448
|
-
execute(docId: string, branch: string, actions: Action[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4449
|
-
load(docId: string, branch: string, operations: Operation[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4450
|
-
executeBatch(request: BatchExecutionRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchExecutionResult>;
|
|
4451
|
-
loadBatch(request: BatchLoadRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchLoadResult>;
|
|
4452
|
-
addRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4453
|
-
removeRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4454
|
-
getJobStatus(jobId: string, signal?: AbortSignal): Promise<JobInfo>;
|
|
4455
|
-
private findByIds;
|
|
4456
|
-
private findBySlugs;
|
|
4457
|
-
private findByParentId;
|
|
4458
|
-
private findByType;
|
|
4459
|
-
private emitJobPending;
|
|
4460
|
-
}
|
|
4461
|
-
//#endregion
|
|
4462
|
-
//#region src/shared/drive-url.d.ts
|
|
4463
|
-
interface ParsedDriveUrl {
|
|
4464
|
-
url: string;
|
|
4465
|
-
driveId: string;
|
|
4466
|
-
graphqlEndpoint: string;
|
|
4467
|
-
}
|
|
4468
|
-
/**
|
|
4469
|
-
* Parse a drive URL to extract drive ID and construct GraphQL endpoint.
|
|
4470
|
-
* Preserves any subpath prefix so the result is correct when the reactor is
|
|
4471
|
-
* served behind a proxy at a non-root path.
|
|
4472
|
-
* e.g., "http://localhost:4001/d/abc123" -> { driveId: "abc123", graphqlEndpoint: "http://localhost:4001/graphql/r" }
|
|
4473
|
-
* e.g., "https://example.com/api/reactor/d/abc123" -> { ..., graphqlEndpoint: "https://example.com/api/reactor/graphql/r" }
|
|
4474
|
-
*/
|
|
4475
|
-
declare function parseDriveUrl(url: string): ParsedDriveUrl;
|
|
4476
|
-
/**
|
|
4477
|
-
* Extract drive ID from a drive URL.
|
|
4478
|
-
*/
|
|
4479
|
-
declare function driveIdFromUrl(url: string): string;
|
|
4480
|
-
//#endregion
|
|
4481
|
-
//#region src/shared/factories.d.ts
|
|
4482
|
-
/**
|
|
4483
|
-
* Factory method to create a ShutdownStatus that can be updated
|
|
4484
|
-
*
|
|
4485
|
-
* @param initialState - Initial shutdown state (default: false)
|
|
4486
|
-
* @returns A tuple of [ShutdownStatus, setShutdown function, setCompleted function]
|
|
4487
|
-
*/
|
|
4488
|
-
declare function createMutableShutdownStatus(initialState?: boolean): [ShutdownStatus, (value: boolean) => void, (completed: Promise<void>) => void];
|
|
4489
|
-
//#endregion
|
|
4490
|
-
//#region src/shared/utils.d.ts
|
|
4491
|
-
type ParsedPaging = {
|
|
4492
|
-
offset: number;
|
|
4493
|
-
limit: number;
|
|
4494
|
-
};
|
|
4495
|
-
/**
|
|
4496
|
-
* Validates PagingOptions and returns a normalized offset and limit.
|
|
4497
|
-
* Throws if the cursor is not empty and not a non-negative integer, or if
|
|
4498
|
-
* limit is less than 1. When `paging` is undefined, returns offset 0 and
|
|
4499
|
-
* the caller-supplied `defaultLimit`.
|
|
4500
|
-
*/
|
|
4501
|
-
declare function parsePagingOptions(paging: PagingOptions | undefined, defaultLimit: number): ParsedPaging;
|
|
4502
|
-
//#endregion
|
|
4503
|
-
//#region src/subs/default-error-handler.d.ts
|
|
4504
|
-
/**
|
|
4505
|
-
* Default error handler that re-throws subscription errors.
|
|
4506
|
-
* This ensures that errors are not silently swallowed.
|
|
4507
|
-
*/
|
|
4508
|
-
declare class DefaultSubscriptionErrorHandler implements ISubscriptionErrorHandler {
|
|
4509
|
-
handleError(error: unknown, context: SubscriptionErrorContext): void;
|
|
4510
|
-
}
|
|
4511
|
-
//#endregion
|
|
4512
|
-
//#region src/subs/react-subscription-manager.d.ts
|
|
4513
|
-
type DocumentCreatedCallback = (result: PagedResults<string>) => void;
|
|
4514
|
-
type DocumentDeletedCallback = (documentIds: string[]) => void;
|
|
4515
|
-
type DocumentStateUpdatedCallback = (result: PagedResults<PHDocument>) => void;
|
|
4516
|
-
type RelationshipChangedCallback = (parentId: string, childId: string, changeType: RelationshipChangeType) => void;
|
|
4517
|
-
declare class ReactorSubscriptionManager implements IReactorSubscriptionManager {
|
|
4518
|
-
private createdSubscriptions;
|
|
4519
|
-
private deletedSubscriptions;
|
|
4520
|
-
private updatedSubscriptions;
|
|
4521
|
-
private relationshipSubscriptions;
|
|
4522
|
-
private subscriptionCounter;
|
|
4523
|
-
private errorHandler;
|
|
4524
|
-
constructor(errorHandler: ISubscriptionErrorHandler);
|
|
4525
|
-
onDocumentCreated(callback: DocumentCreatedCallback, search?: SearchFilter): () => void;
|
|
4526
|
-
onDocumentDeleted(callback: DocumentDeletedCallback, search?: SearchFilter): () => void;
|
|
4527
|
-
onDocumentStateUpdated(callback: DocumentStateUpdatedCallback, search?: SearchFilter, view?: ViewFilter): () => void;
|
|
4528
|
-
onRelationshipChanged(callback: RelationshipChangedCallback, search?: SearchFilter): () => void;
|
|
4529
|
-
/**
|
|
4530
|
-
* Notify subscribers about created documents
|
|
4531
|
-
*/
|
|
4532
|
-
notifyDocumentsCreated(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4533
|
-
/**
|
|
4534
|
-
* Notify subscribers about deleted documents
|
|
4535
|
-
*/
|
|
4536
|
-
notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4601
|
+
preReadyKinds: BuiltInReadModelKind[];
|
|
4602
|
+
postReadyKinds: BuiltInReadModelKind[];
|
|
4603
|
+
factory: ProjectionWorkerFactory;
|
|
4604
|
+
logger: ILogger;
|
|
4605
|
+
hostBus: IEventBus;
|
|
4606
|
+
initTimeoutMs?: number;
|
|
4607
|
+
shutdownGraceMs?: number;
|
|
4608
|
+
drainTimeoutMs?: number;
|
|
4609
|
+
chainDepthReportIntervalMs?: number;
|
|
4537
4610
|
/**
|
|
4538
|
-
*
|
|
4611
|
+
* Host-side forwarding instrumentations indexed by shard index. The
|
|
4612
|
+
* manager routes each shard's `pool-acquire-samples` message to the
|
|
4613
|
+
* matching forwarder so the host's OpenTelemetry instrumentation records
|
|
4614
|
+
* acquire-wait latencies as if each shard's pg.Pool were local.
|
|
4539
4615
|
*/
|
|
4540
|
-
|
|
4616
|
+
poolInstrumentations?: ForwardingPoolInstrumentation[];
|
|
4617
|
+
};
|
|
4618
|
+
//#endregion
|
|
4619
|
+
//#region src/signer/types.d.ts
|
|
4620
|
+
/**
|
|
4621
|
+
* Configuration for signing and verification.
|
|
4622
|
+
*/
|
|
4623
|
+
type SignerConfig = {
|
|
4541
4624
|
/**
|
|
4542
|
-
*
|
|
4625
|
+
* The signer used to sign actions before submission.
|
|
4543
4626
|
*/
|
|
4544
|
-
|
|
4627
|
+
signer: ISigner;
|
|
4545
4628
|
/**
|
|
4546
|
-
*
|
|
4629
|
+
* Optional handler for verifying signatures on incoming operations.
|
|
4630
|
+
* If not provided, signature verification will be skipped.
|
|
4547
4631
|
*/
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4632
|
+
verifier?: SignatureVerificationHandler;
|
|
4633
|
+
};
|
|
4634
|
+
//#endregion
|
|
4635
|
+
//#region src/storage/migrations/types.d.ts
|
|
4636
|
+
type MigrationStrategy = "auto" | "manual" | "none";
|
|
4637
|
+
interface MigrationResult {
|
|
4638
|
+
success: boolean;
|
|
4639
|
+
migrationsExecuted: string[];
|
|
4640
|
+
error?: Error;
|
|
4552
4641
|
}
|
|
4553
4642
|
//#endregion
|
|
4554
|
-
//#region src/
|
|
4555
|
-
declare class
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4643
|
+
//#region src/sync/sync-builder.d.ts
|
|
4644
|
+
declare class SyncBuilder {
|
|
4645
|
+
private channelFactory?;
|
|
4646
|
+
private remoteStorage?;
|
|
4647
|
+
private cursorStorage?;
|
|
4648
|
+
private deadLetterStorage?;
|
|
4649
|
+
private config;
|
|
4650
|
+
withChannelFactory(factory: IChannelFactory): this;
|
|
4651
|
+
withRemoteStorage(storage: ISyncRemoteStorage): this;
|
|
4652
|
+
withCursorStorage(storage: ISyncCursorStorage): this;
|
|
4653
|
+
withDeadLetterStorage(storage: ISyncDeadLetterStorage): this;
|
|
4654
|
+
withMaxDeadLettersPerRemote(limit: number): this;
|
|
4655
|
+
withMaxInboxBatchSize(limit: number): this;
|
|
4656
|
+
build(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): ISyncManager;
|
|
4657
|
+
buildModule(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): InProcessSyncModule;
|
|
4559
4658
|
}
|
|
4560
4659
|
//#endregion
|
|
4561
|
-
//#region src/
|
|
4660
|
+
//#region src/core/reactor-builder.d.ts
|
|
4562
4661
|
/**
|
|
4563
|
-
*
|
|
4564
|
-
*
|
|
4565
|
-
*
|
|
4566
|
-
*
|
|
4662
|
+
* Dependencies provided to read-model factories registered via
|
|
4663
|
+
* `withReadModelFactory`. These are constructed inside `buildModule()`, which
|
|
4664
|
+
* is why factory-based registration is needed for read models that depend on
|
|
4665
|
+
* them (`BaseReadModel` subclasses, in particular).
|
|
4567
4666
|
*/
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
private toErrorInfo;
|
|
4667
|
+
interface ReadModelFactoryDeps {
|
|
4668
|
+
documentModelRegistry: IDocumentModelRegistry;
|
|
4669
|
+
operationIndex: IOperationIndex;
|
|
4670
|
+
writeCache: IWriteCache;
|
|
4671
|
+
processorManagerConsistencyTracker: IConsistencyTracker;
|
|
4672
|
+
}
|
|
4673
|
+
/**
|
|
4674
|
+
* Factory that builds a pre-ready read model from internal reactor
|
|
4675
|
+
* dependencies once they are available. Awaited during `buildModule()`.
|
|
4676
|
+
*/
|
|
4677
|
+
type ReadModelFactory = (deps: ReadModelFactoryDeps) => IReadModel | Promise<IReadModel>;
|
|
4678
|
+
type WorkerPoolBase = {
|
|
4679
|
+
/** Number of worker threads to spawn; also the sticky-routing modulus. */numWorkers: number;
|
|
4582
4680
|
/**
|
|
4583
|
-
*
|
|
4681
|
+
* Factory spec the default transport's workers import to instantiate
|
|
4682
|
+
* their signature verifier. Omitted = no executor-side verification,
|
|
4683
|
+
* parity with the in-process executor's default.
|
|
4584
4684
|
*/
|
|
4585
|
-
|
|
4685
|
+
verifier?: SignatureVerifierSpec;
|
|
4686
|
+
};
|
|
4687
|
+
/**
|
|
4688
|
+
* Executor worker-pool configuration. Either `db` (default thread
|
|
4689
|
+
* transport; each worker opens its own Postgres pool) or a custom
|
|
4690
|
+
* `factory` transport is required by construction — an enabled pool
|
|
4691
|
+
* without connection info is unrepresentable.
|
|
4692
|
+
*/
|
|
4693
|
+
type WorkerPoolOptions = (WorkerPoolBase & {
|
|
4694
|
+
db: DbConfig;
|
|
4695
|
+
factory?: WorkerFactory;
|
|
4696
|
+
}) | (WorkerPoolBase & {
|
|
4697
|
+
db?: DbConfig;
|
|
4698
|
+
factory: WorkerFactory;
|
|
4699
|
+
});
|
|
4700
|
+
/**
|
|
4701
|
+
* Caller-facing config for {@link ReactorBuilder.withProjectionShards}.
|
|
4702
|
+
* When set, the builder replaces the in-process
|
|
4703
|
+
* {@link ReadModelCoordinator} with a {@link ProjectionShardManager} that
|
|
4704
|
+
* fans JOB_WRITE_READY events to N projection workers sharded by
|
|
4705
|
+
* documentId.
|
|
4706
|
+
*
|
|
4707
|
+
* @see Sharded projection workers sub-feature brief
|
|
4708
|
+
* (Powerhouse board wiki id: eb26f01f-8f68-4918-a6f6-ac7a4679b533)
|
|
4709
|
+
*/
|
|
4710
|
+
type ProjectionShardBuilderConfig = {
|
|
4711
|
+
shardCount: number;
|
|
4712
|
+
preReadyKinds: BuiltInReadModelKind[];
|
|
4713
|
+
postReadyKinds: BuiltInReadModelKind[];
|
|
4586
4714
|
/**
|
|
4587
|
-
*
|
|
4715
|
+
* Connection info for the projection workers' own pools. Falls back to
|
|
4716
|
+
* the executor worker pool's `db` when {@link ReactorBuilder.withWorkerPool}
|
|
4717
|
+
* is configured with one.
|
|
4588
4718
|
*/
|
|
4589
|
-
|
|
4719
|
+
db?: DbConfig;
|
|
4720
|
+
poolSize?: number;
|
|
4721
|
+
initTimeoutMs?: number;
|
|
4722
|
+
shutdownGraceMs?: number;
|
|
4723
|
+
drainTimeoutMs?: number;
|
|
4724
|
+
chainDepthReportIntervalMs?: number;
|
|
4725
|
+
};
|
|
4726
|
+
declare class ReactorBuilder {
|
|
4727
|
+
private logger?;
|
|
4728
|
+
private documentModelSources;
|
|
4729
|
+
private upgradeManifests;
|
|
4730
|
+
private features;
|
|
4731
|
+
private readModels;
|
|
4732
|
+
private readModelFactories;
|
|
4733
|
+
private executorManager;
|
|
4734
|
+
private executorConfig;
|
|
4735
|
+
private writeCacheConfig?;
|
|
4736
|
+
private migrationStrategy;
|
|
4737
|
+
private syncBuilder?;
|
|
4738
|
+
private eventBus?;
|
|
4739
|
+
private readModelCoordinator?;
|
|
4740
|
+
private signatureVerifier?;
|
|
4741
|
+
private kyselyInstance?;
|
|
4742
|
+
private signalHandlersEnabled;
|
|
4743
|
+
private queueInstance?;
|
|
4744
|
+
private channelScheme?;
|
|
4745
|
+
private jwtHandler?;
|
|
4746
|
+
private documentModelLoader?;
|
|
4747
|
+
private shutdownHooks;
|
|
4748
|
+
private driveContainerTypes;
|
|
4749
|
+
private workerPool?;
|
|
4750
|
+
private resolvedModelManifest?;
|
|
4751
|
+
private projectionShardConfig?;
|
|
4752
|
+
private projectionWorkerFactory?;
|
|
4753
|
+
private instrumentedPools;
|
|
4754
|
+
withLogger(logger: ILogger): this;
|
|
4590
4755
|
/**
|
|
4591
|
-
*
|
|
4756
|
+
* Register document-model sources: live modules, importable files, or
|
|
4757
|
+
* importable packages. Appends across calls. At `buildModule()` every
|
|
4758
|
+
* source is resolved host-side and registered on the registry; file and
|
|
4759
|
+
* package sources additionally form the worker manifest when the worker
|
|
4760
|
+
* pool is enabled (live modules cannot cross a thread boundary).
|
|
4592
4761
|
*/
|
|
4593
|
-
|
|
4762
|
+
withDocumentModelSources(sources: DocumentModelSource[]): this;
|
|
4763
|
+
withUpgradeManifests(manifests: UpgradeManifest<readonly number[]>[]): this;
|
|
4764
|
+
withFeatures(features: ReactorFeatures): this;
|
|
4765
|
+
withReadModel(readModel: IReadModel): this;
|
|
4594
4766
|
/**
|
|
4595
|
-
*
|
|
4767
|
+
* Register a factory that builds a pre-ready read model after the reactor's
|
|
4768
|
+
* internal `operationIndex`, `writeCache`, and processor-manager consistency
|
|
4769
|
+
* tracker are constructed. Use this for read models (e.g. `BaseReadModel`
|
|
4770
|
+
* subclasses) that need those dependencies and therefore cannot be built
|
|
4771
|
+
* before calling `buildModule()`.
|
|
4596
4772
|
*/
|
|
4597
|
-
|
|
4773
|
+
withReadModelFactory(factory: ReadModelFactory): this;
|
|
4774
|
+
withReadModelCoordinator(readModelCoordinator: IReadModelCoordinator): this;
|
|
4775
|
+
withExecutor(executor: IJobExecutorManager): this;
|
|
4776
|
+
withExecutorConfig(config: Partial<JobExecutorConfig>): this;
|
|
4777
|
+
withWriteCacheConfig(config: Partial<WriteCacheConfig>): this;
|
|
4778
|
+
withDriveContainerTypes(types: string[]): this;
|
|
4779
|
+
withMigrationStrategy(strategy: MigrationStrategy): this;
|
|
4780
|
+
withSync(syncBuilder: SyncBuilder): this;
|
|
4781
|
+
withEventBus(eventBus: IEventBus): this;
|
|
4782
|
+
withSignatureVerifier(verifier: SignatureVerificationHandler): this;
|
|
4783
|
+
withKysely(kysely: Kysely<Database>): this;
|
|
4598
4784
|
/**
|
|
4599
|
-
*
|
|
4785
|
+
* Register an externally-constructed pg.Pool's {@link PoolInstrumentation}
|
|
4786
|
+
* so it surfaces through {@link ReactorModule.pools}. Use this when the
|
|
4787
|
+
* caller built the pool itself (e.g. the in-process bench host wiring) so
|
|
4788
|
+
* pool acquire-wait and pool-stat metrics still emit. The builder also
|
|
4789
|
+
* registers any pool it constructs internally via {@link createPostgresDatabase}.
|
|
4600
4790
|
*/
|
|
4601
|
-
|
|
4791
|
+
withInstrumentedPool(instrumentation: PoolInstrumentation): this;
|
|
4792
|
+
withQueue(queue: IQueue): this;
|
|
4793
|
+
withChannelScheme(scheme: ChannelScheme): this;
|
|
4794
|
+
withJwtHandler(handler: JwtHandler): this;
|
|
4795
|
+
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4796
|
+
withSignalHandlers(): this;
|
|
4602
4797
|
/**
|
|
4603
|
-
*
|
|
4798
|
+
* Register an async cleanup hook to run during graceful shutdown. Hooks fire
|
|
4799
|
+
* after `reactor.kill()` resolves and before `database.destroy()`, so callers
|
|
4800
|
+
* that depend on the reactor (e.g. an HTTP API layered on top) can drain
|
|
4801
|
+
* cleanly before the underlying kysely instance is torn down. Hook errors are
|
|
4802
|
+
* logged and otherwise ignored — one bad hook cannot strand the rest of the
|
|
4803
|
+
* shutdown chain.
|
|
4604
4804
|
*/
|
|
4605
|
-
|
|
4805
|
+
withShutdownHook(hook: () => Promise<void>): this;
|
|
4606
4806
|
/**
|
|
4607
|
-
*
|
|
4608
|
-
*
|
|
4609
|
-
*
|
|
4610
|
-
*
|
|
4611
|
-
*
|
|
4612
|
-
*
|
|
4613
|
-
*
|
|
4614
|
-
*/
|
|
4615
|
-
|
|
4616
|
-
private getCreateDocumentType;
|
|
4617
|
-
enqueue(job: Job): Promise<void>;
|
|
4618
|
-
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4619
|
-
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4620
|
-
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4621
|
-
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
4622
|
-
totalSize(): Promise<number>;
|
|
4623
|
-
remove(jobId: string): Promise<boolean>;
|
|
4624
|
-
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
4625
|
-
clearAll(): Promise<void>;
|
|
4626
|
-
hasJobs(): Promise<boolean>;
|
|
4627
|
-
completeJob(jobId: string): Promise<void>;
|
|
4628
|
-
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
4629
|
-
deferJob(jobId: string): void;
|
|
4630
|
-
retryJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
4807
|
+
* Enable the executor worker pool: N `node:worker_threads` workers with
|
|
4808
|
+
* sticky per-document routing, replacing the in-process executor. Calling
|
|
4809
|
+
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
4810
|
+
* (each worker opens its own Postgres pool; the parent database is built
|
|
4811
|
+
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
4812
|
+
* transport. `verifier` is imported by the default transport's workers;
|
|
4813
|
+
* omitted = no executor-side signature verification.
|
|
4814
|
+
*/
|
|
4815
|
+
withWorkerPool(options: WorkerPoolOptions): this;
|
|
4631
4816
|
/**
|
|
4632
|
-
*
|
|
4817
|
+
* Configure N sharded projection workers. When set, the builder replaces
|
|
4818
|
+
* the default in-process {@link ReadModelCoordinator} with a
|
|
4819
|
+
* {@link ProjectionShardManager}.
|
|
4820
|
+
*
|
|
4821
|
+
* Projection workers open their own Postgres pools from `config.db`,
|
|
4822
|
+
* falling back to the executor worker pool's `db` when
|
|
4823
|
+
* {@link withWorkerPool} is configured with one; only the `poolSize` is
|
|
4824
|
+
* overridden by {@link ProjectionShardBuilderConfig.poolSize}. The same
|
|
4825
|
+
* model manifest resolved from {@link withDocumentModelSources} is
|
|
4826
|
+
* forwarded.
|
|
4633
4827
|
*/
|
|
4634
|
-
|
|
4828
|
+
withProjectionShards(config: ProjectionShardBuilderConfig): this;
|
|
4635
4829
|
/**
|
|
4636
|
-
*
|
|
4830
|
+
* Inject a custom {@link ProjectionWorkerFactory}. When set, the builder
|
|
4831
|
+
* skips default thread-transport wiring for the projection shards and
|
|
4832
|
+
* hands the factory directly to {@link ProjectionShardManager}.
|
|
4637
4833
|
*/
|
|
4638
|
-
|
|
4834
|
+
withProjectionWorkerFactory(factory: ProjectionWorkerFactory): this;
|
|
4835
|
+
getResolvedModelManifest(): ModelManifestEntry[] | undefined;
|
|
4836
|
+
build(): Promise<IReactor>;
|
|
4837
|
+
buildModule(): Promise<InProcessReactorModule>;
|
|
4639
4838
|
/**
|
|
4640
|
-
*
|
|
4641
|
-
*
|
|
4839
|
+
* The single Postgres config for the parent, executor workers, and
|
|
4840
|
+
* projection shards. They must share one physical database (the parent
|
|
4841
|
+
* writes operations; workers and shards read them), so divergent
|
|
4842
|
+
* worker/shard targets throw. `withKysely` overrides the parent and is not
|
|
4843
|
+
* validated against a worker/shard `db`.
|
|
4642
4844
|
*/
|
|
4643
|
-
|
|
4845
|
+
private resolveReactorDbConfig;
|
|
4644
4846
|
/**
|
|
4645
|
-
*
|
|
4847
|
+
* Constructs a {@link ProjectionShardManager} bound to the host event
|
|
4848
|
+
* bus. Builds the default thread-transport factory unless one was
|
|
4849
|
+
* injected via {@link withProjectionWorkerFactory}. Calls
|
|
4850
|
+
* `manager.startup()` so all N workers reach READY before the reactor
|
|
4851
|
+
* is returned to the caller.
|
|
4646
4852
|
*/
|
|
4647
|
-
|
|
4853
|
+
private createProjectionShardManager;
|
|
4854
|
+
private createDefaultProjectionWorkerFactory;
|
|
4648
4855
|
/**
|
|
4649
|
-
*
|
|
4856
|
+
* Default {@link WorkerFactory} used when the pool options carry no
|
|
4857
|
+
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
4858
|
+
* Worker pointing at the compiled `worker/entry.js`.
|
|
4650
4859
|
*/
|
|
4651
|
-
|
|
4860
|
+
private createDefaultWorkerFactory;
|
|
4652
4861
|
/**
|
|
4653
|
-
*
|
|
4862
|
+
* Builds the parent Kysely instance against a real Postgres server using
|
|
4863
|
+
* the same {@link DbConfig} the workers receive at init. Used in the
|
|
4864
|
+
* worker-pool path so the parent reactor and each worker thread share
|
|
4865
|
+
* storage; PGlite cannot be shared across threads. The constructed pool
|
|
4866
|
+
* is wrapped with {@link instrumentPgPool} and the resulting
|
|
4867
|
+
* {@link PoolInstrumentation} is pushed onto {@link instrumentedPools} so
|
|
4868
|
+
* the reactor module exposes acquire-wait and pool-stat surfaces.
|
|
4654
4869
|
*/
|
|
4655
|
-
|
|
4870
|
+
private createPostgresDatabase;
|
|
4871
|
+
private attachSignalHandlers;
|
|
4872
|
+
}
|
|
4873
|
+
//#endregion
|
|
4874
|
+
//#region src/core/reactor-client-builder.d.ts
|
|
4875
|
+
/**
|
|
4876
|
+
* Builder class for constructing ReactorClient instances with proper configuration
|
|
4877
|
+
*/
|
|
4878
|
+
declare class ReactorClientBuilder {
|
|
4879
|
+
private logger?;
|
|
4880
|
+
private reactorBuilder?;
|
|
4881
|
+
private reactor?;
|
|
4882
|
+
private eventBus?;
|
|
4883
|
+
private documentIndexer?;
|
|
4884
|
+
private documentView?;
|
|
4885
|
+
private signer?;
|
|
4886
|
+
private signatureVerifier?;
|
|
4887
|
+
private subscriptionManager?;
|
|
4888
|
+
private jobAwaiter?;
|
|
4889
|
+
private documentModelLoader?;
|
|
4656
4890
|
/**
|
|
4657
|
-
*
|
|
4891
|
+
* Sets the logger for the ReactorClient.
|
|
4892
|
+
* @param logger - The logger to use.
|
|
4893
|
+
* @returns The ReactorClientBuilder instance.
|
|
4658
4894
|
*/
|
|
4659
|
-
|
|
4895
|
+
withLogger(logger: ILogger): this;
|
|
4660
4896
|
/**
|
|
4661
|
-
*
|
|
4897
|
+
* Either this or withReactor must be set.
|
|
4662
4898
|
*/
|
|
4663
|
-
|
|
4899
|
+
withReactorBuilder(reactorBuilder: ReactorBuilder): this;
|
|
4664
4900
|
/**
|
|
4665
|
-
*
|
|
4901
|
+
* Either this or withReactorBuilder must be set.
|
|
4666
4902
|
*/
|
|
4667
|
-
|
|
4903
|
+
withReactor(reactor: IReactor, eventBus: IEventBus, documentIndexer: IDocumentIndexer, documentView: IDocumentView): this;
|
|
4668
4904
|
/**
|
|
4669
|
-
*
|
|
4905
|
+
* Sets the signer configuration for signing and verifying actions.
|
|
4906
|
+
*
|
|
4907
|
+
* @param config - Either an ISigner for signing only, or a SignerConfig for both signing and verification
|
|
4670
4908
|
*/
|
|
4671
|
-
|
|
4909
|
+
withSigner(config: ISigner | SignerConfig): this;
|
|
4910
|
+
withSubscriptionManager(subscriptionManager: IReactorSubscriptionManager): this;
|
|
4911
|
+
withJobAwaiter(jobAwaiter: IJobAwaiter): this;
|
|
4912
|
+
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4913
|
+
build(): Promise<ReactorClient>;
|
|
4914
|
+
buildModule(): Promise<InProcessReactorClientModule>;
|
|
4672
4915
|
}
|
|
4673
4916
|
//#endregion
|
|
4674
|
-
//#region src/
|
|
4917
|
+
//#region src/core/drive-container-types.d.ts
|
|
4918
|
+
declare const DEFAULT_DRIVE_CONTAINER_TYPES: ReadonlySet<string>;
|
|
4919
|
+
//#endregion
|
|
4920
|
+
//#region src/core/reactor.d.ts
|
|
4675
4921
|
/**
|
|
4676
|
-
*
|
|
4677
|
-
*
|
|
4678
|
-
* Subscribes to operation events to update job states.
|
|
4922
|
+
* This class implements the IReactor interface and serves as the main entry point
|
|
4923
|
+
* for the new Reactor architecture.
|
|
4679
4924
|
*/
|
|
4680
|
-
declare class
|
|
4925
|
+
declare class Reactor implements IReactor {
|
|
4926
|
+
private logger;
|
|
4927
|
+
private documentModelRegistry;
|
|
4928
|
+
private shutdownStatus;
|
|
4929
|
+
private setShutdown;
|
|
4930
|
+
private setCompleted;
|
|
4931
|
+
private queue;
|
|
4932
|
+
private jobTracker;
|
|
4933
|
+
private readModelCoordinator;
|
|
4934
|
+
private features;
|
|
4935
|
+
private documentView;
|
|
4936
|
+
private documentIndexer;
|
|
4937
|
+
private operationStore;
|
|
4681
4938
|
private eventBus;
|
|
4682
|
-
private
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4939
|
+
private executorManager;
|
|
4940
|
+
constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager);
|
|
4941
|
+
kill(): ShutdownStatus;
|
|
4942
|
+
getDocumentModels(namespace?: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DocumentModelModule>>;
|
|
4943
|
+
get<TDocument extends PHDocument>(id: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4944
|
+
getBySlug<TDocument extends PHDocument>(slug: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4945
|
+
getByIdOrSlug<TDocument extends PHDocument>(identifier: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4946
|
+
getOutgoingRelationships(sourceId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4947
|
+
getIncomingRelationships(targetId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4948
|
+
getOperations(documentId: string, view?: ViewFilter, filter?: OperationFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<Record<string, PagedResults<Operation>>>;
|
|
4949
|
+
find(search: SearchFilter, view?: ViewFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<PHDocument>>;
|
|
4950
|
+
create(document: PHDocument, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4951
|
+
deleteDocument(id: string, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4952
|
+
execute(docId: string, branch: string, actions: Action[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4953
|
+
load(docId: string, branch: string, operations: Operation[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4954
|
+
executeBatch(request: BatchExecutionRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchExecutionResult>;
|
|
4955
|
+
loadBatch(request: BatchLoadRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchLoadResult>;
|
|
4956
|
+
addRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4957
|
+
removeRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4958
|
+
getJobStatus(jobId: string, signal?: AbortSignal): Promise<JobInfo>;
|
|
4959
|
+
private findByIds;
|
|
4960
|
+
private findBySlugs;
|
|
4961
|
+
private findByParentId;
|
|
4962
|
+
private findByType;
|
|
4963
|
+
private emitJobPending;
|
|
4694
4964
|
}
|
|
4695
4965
|
//#endregion
|
|
4696
|
-
//#region src/
|
|
4697
|
-
|
|
4966
|
+
//#region src/shared/drive-url.d.ts
|
|
4967
|
+
interface ParsedDriveUrl {
|
|
4968
|
+
url: string;
|
|
4969
|
+
driveId: string;
|
|
4970
|
+
graphqlEndpoint: string;
|
|
4971
|
+
}
|
|
4698
4972
|
/**
|
|
4699
|
-
*
|
|
4700
|
-
*
|
|
4973
|
+
* Parse a drive URL to extract drive ID and construct GraphQL endpoint.
|
|
4974
|
+
* Preserves any subpath prefix so the result is correct when the reactor is
|
|
4975
|
+
* served behind a proxy at a non-root path.
|
|
4976
|
+
* e.g., "http://localhost:4001/d/abc123" -> { driveId: "abc123", graphqlEndpoint: "http://localhost:4001/graphql/r" }
|
|
4977
|
+
* e.g., "https://example.com/api/reactor/d/abc123" -> { ..., graphqlEndpoint: "https://example.com/api/reactor/graphql/r" }
|
|
4701
4978
|
*/
|
|
4702
|
-
declare
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
private logger;
|
|
4708
|
-
private resolver;
|
|
4709
|
-
private executors;
|
|
4710
|
-
private isRunning;
|
|
4711
|
-
private activeJobs;
|
|
4712
|
-
private totalJobsProcessed;
|
|
4713
|
-
private unsubscribe?;
|
|
4714
|
-
private deferredJobs;
|
|
4715
|
-
private resultHandler;
|
|
4716
|
-
private jobTimeoutMs;
|
|
4717
|
-
constructor(executorFactory: JobExecutorFactory, eventBus: IEventBus, queue: IQueue, jobTracker: IJobTracker, logger: ILogger, resolver: IDocumentModelResolver, jobTimeoutMs?: number);
|
|
4718
|
-
start(numExecutors: number): Promise<void>;
|
|
4719
|
-
stop(graceful?: boolean): Promise<void>;
|
|
4720
|
-
getExecutors(): IJobExecutor[];
|
|
4721
|
-
getStatus(): ExecutorManagerStatus;
|
|
4722
|
-
private processNextJob;
|
|
4723
|
-
private checkForMoreJobs;
|
|
4724
|
-
private processExistingJobs;
|
|
4725
|
-
private flushDeferredJobs;
|
|
4726
|
-
}
|
|
4979
|
+
declare function parseDriveUrl(url: string): ParsedDriveUrl;
|
|
4980
|
+
/**
|
|
4981
|
+
* Extract drive ID from a drive URL.
|
|
4982
|
+
*/
|
|
4983
|
+
declare function driveIdFromUrl(url: string): string;
|
|
4727
4984
|
//#endregion
|
|
4728
|
-
//#region src/
|
|
4985
|
+
//#region src/shared/factories.d.ts
|
|
4729
4986
|
/**
|
|
4730
|
-
*
|
|
4987
|
+
* Factory method to create a ShutdownStatus that can be updated
|
|
4731
4988
|
*
|
|
4732
|
-
*
|
|
4733
|
-
*
|
|
4734
|
-
* cross-scope contract for accessing document scope metadata.
|
|
4989
|
+
* @param initialState - Initial shutdown state (default: false)
|
|
4990
|
+
* @returns A tuple of [ShutdownStatus, setShutdown function, setCompleted function]
|
|
4735
4991
|
*/
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
/**
|
|
4743
|
-
* The document type (from header), cached for convenience.
|
|
4744
|
-
*/
|
|
4745
|
-
documentType: string;
|
|
4746
|
-
/**
|
|
4747
|
-
* The revision of the document scope when this metadata was captured.
|
|
4748
|
-
* Used for cache invalidation and consistency checks.
|
|
4749
|
-
*/
|
|
4750
|
-
documentScopeRevision: number;
|
|
4992
|
+
declare function createMutableShutdownStatus(initialState?: boolean): [ShutdownStatus, (value: boolean) => void, (completed: Promise<void>) => void];
|
|
4993
|
+
//#endregion
|
|
4994
|
+
//#region src/shared/utils.d.ts
|
|
4995
|
+
type ParsedPaging = {
|
|
4996
|
+
offset: number;
|
|
4997
|
+
limit: number;
|
|
4751
4998
|
};
|
|
4752
4999
|
/**
|
|
4753
|
-
*
|
|
4754
|
-
*
|
|
4755
|
-
*
|
|
4756
|
-
*
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
*
|
|
4763
|
-
*
|
|
5000
|
+
* Validates PagingOptions and returns a normalized offset and limit.
|
|
5001
|
+
* Throws if the cursor is not empty and not a non-negative integer, or if
|
|
5002
|
+
* limit is less than 1. When `paging` is undefined, returns offset 0 and
|
|
5003
|
+
* the caller-supplied `defaultLimit`.
|
|
5004
|
+
*/
|
|
5005
|
+
declare function parsePagingOptions(paging: PagingOptions | undefined, defaultLimit: number): ParsedPaging;
|
|
5006
|
+
//#endregion
|
|
5007
|
+
//#region src/subs/default-error-handler.d.ts
|
|
5008
|
+
/**
|
|
5009
|
+
* Default error handler that re-throws subscription errors.
|
|
5010
|
+
* This ensures that errors are not silently swallowed.
|
|
4764
5011
|
*/
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
*
|
|
4787
|
-
* @param documentId - The document identifier
|
|
4788
|
-
* @param branch - Branch name
|
|
4789
|
-
* @param targetRevision - The document scope revision to reconstruct up to
|
|
4790
|
-
* @param signal - Optional abort signal to cancel the operation
|
|
4791
|
-
* @returns Document metadata as of the target revision
|
|
4792
|
-
* @throws {Error} "Operation aborted" if signal is aborted
|
|
4793
|
-
* @throws {Error} If document not found
|
|
4794
|
-
*/
|
|
4795
|
-
rebuildAtRevision(documentId: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
5012
|
+
declare class DefaultSubscriptionErrorHandler implements ISubscriptionErrorHandler {
|
|
5013
|
+
handleError(error: unknown, context: SubscriptionErrorContext): void;
|
|
5014
|
+
}
|
|
5015
|
+
//#endregion
|
|
5016
|
+
//#region src/subs/react-subscription-manager.d.ts
|
|
5017
|
+
type DocumentCreatedCallback = (result: PagedResults<string>) => void;
|
|
5018
|
+
type DocumentDeletedCallback = (documentIds: string[]) => void;
|
|
5019
|
+
type DocumentStateUpdatedCallback = (result: PagedResults<PHDocument>) => void;
|
|
5020
|
+
type RelationshipChangedCallback = (parentId: string, childId: string, changeType: RelationshipChangeType) => void;
|
|
5021
|
+
declare class ReactorSubscriptionManager implements IReactorSubscriptionManager {
|
|
5022
|
+
private createdSubscriptions;
|
|
5023
|
+
private deletedSubscriptions;
|
|
5024
|
+
private updatedSubscriptions;
|
|
5025
|
+
private relationshipSubscriptions;
|
|
5026
|
+
private subscriptionCounter;
|
|
5027
|
+
private errorHandler;
|
|
5028
|
+
constructor(errorHandler: ISubscriptionErrorHandler);
|
|
5029
|
+
onDocumentCreated(callback: DocumentCreatedCallback, search?: SearchFilter): () => void;
|
|
5030
|
+
onDocumentDeleted(callback: DocumentDeletedCallback, search?: SearchFilter): () => void;
|
|
5031
|
+
onDocumentStateUpdated(callback: DocumentStateUpdatedCallback, search?: SearchFilter, view?: ViewFilter): () => void;
|
|
5032
|
+
onRelationshipChanged(callback: RelationshipChangedCallback, search?: SearchFilter): () => void;
|
|
4796
5033
|
/**
|
|
4797
|
-
*
|
|
4798
|
-
*
|
|
4799
|
-
* Called by the job executor after CREATE_DOCUMENT, UPGRADE_DOCUMENT, or
|
|
4800
|
-
* DELETE_DOCUMENT operations to keep the cache current.
|
|
4801
|
-
*
|
|
4802
|
-
* @param documentId - The document identifier
|
|
4803
|
-
* @param branch - Branch name
|
|
4804
|
-
* @param meta - The new metadata to cache
|
|
5034
|
+
* Notify subscribers about created documents
|
|
4805
5035
|
*/
|
|
4806
|
-
|
|
5036
|
+
notifyDocumentsCreated(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4807
5037
|
/**
|
|
4808
|
-
*
|
|
4809
|
-
*
|
|
4810
|
-
* Call before reshuffling operations that modify the document scope, or
|
|
4811
|
-
* when document state may have changed externally.
|
|
4812
|
-
*
|
|
4813
|
-
* @param documentId - The document identifier
|
|
4814
|
-
* @param branch - Optional branch to narrow invalidation (if omitted, all branches)
|
|
4815
|
-
* @returns Number of entries invalidated
|
|
5038
|
+
* Notify subscribers about deleted documents
|
|
4816
5039
|
*/
|
|
4817
|
-
|
|
5040
|
+
notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4818
5041
|
/**
|
|
4819
|
-
*
|
|
5042
|
+
* Notify subscribers about updated documents
|
|
4820
5043
|
*/
|
|
4821
|
-
|
|
5044
|
+
notifyDocumentsUpdated(documents: PHDocument[]): void;
|
|
4822
5045
|
/**
|
|
4823
|
-
*
|
|
5046
|
+
* Notify subscribers about relationship changes
|
|
4824
5047
|
*/
|
|
4825
|
-
|
|
5048
|
+
notifyRelationshipChanged(parentId: string, childId: string, changeType: RelationshipChangeType, childType?: string): void;
|
|
4826
5049
|
/**
|
|
4827
|
-
*
|
|
5050
|
+
* Clear all subscriptions
|
|
4828
5051
|
*/
|
|
4829
|
-
|
|
5052
|
+
clearAll(): void;
|
|
5053
|
+
private filterDocumentIds;
|
|
5054
|
+
private filterDocuments;
|
|
5055
|
+
private matchesRelationshipFilter;
|
|
4830
5056
|
}
|
|
4831
5057
|
//#endregion
|
|
4832
|
-
//#region src/
|
|
5058
|
+
//#region src/events/event-bus.d.ts
|
|
5059
|
+
declare class EventBus implements IEventBus {
|
|
5060
|
+
readonly eventTypeToSubscribers: Map<number, Subscriber[]>;
|
|
5061
|
+
subscribe<K>(type: number, subscriber: (type: number, event: K) => void | Promise<void>): Unsubscribe;
|
|
5062
|
+
emit(type: number, data: any): Promise<void>;
|
|
5063
|
+
}
|
|
5064
|
+
//#endregion
|
|
5065
|
+
//#region src/queue/queue.d.ts
|
|
4833
5066
|
/**
|
|
4834
|
-
*
|
|
4835
|
-
*
|
|
4836
|
-
*
|
|
4837
|
-
*
|
|
4838
|
-
* items in chronological order (oldest to newest) via getAll().
|
|
4839
|
-
*
|
|
4840
|
-
* @template T - The type of items stored in the buffer
|
|
5067
|
+
* In-memory implementation of the IQueue interface.
|
|
5068
|
+
* Organizes jobs by documentId, scope, and branch to ensure proper ordering.
|
|
5069
|
+
* Ensures serial execution per document by tracking executing jobs.
|
|
5070
|
+
* Implements dependency management through queue hints.
|
|
4841
5071
|
*/
|
|
4842
|
-
declare class
|
|
4843
|
-
private
|
|
4844
|
-
private
|
|
4845
|
-
private
|
|
4846
|
-
private
|
|
4847
|
-
|
|
5072
|
+
declare class InMemoryQueue implements IQueue {
|
|
5073
|
+
private eventBus;
|
|
5074
|
+
private resolver;
|
|
5075
|
+
private queues;
|
|
5076
|
+
private jobIdToQueueKey;
|
|
5077
|
+
private docIdToJobId;
|
|
5078
|
+
private jobIdToDocId;
|
|
5079
|
+
private completedJobs;
|
|
5080
|
+
private jobIndex;
|
|
5081
|
+
private isBlocked;
|
|
5082
|
+
private onDrainedCallback?;
|
|
5083
|
+
private isPausedFlag;
|
|
5084
|
+
constructor(eventBus: IEventBus, resolver: IDocumentModelResolver);
|
|
5085
|
+
private toErrorInfo;
|
|
4848
5086
|
/**
|
|
4849
|
-
*
|
|
4850
|
-
*
|
|
4851
|
-
* @param item - The item to add
|
|
5087
|
+
* Creates a unique key for a document/scope/branch combination
|
|
4852
5088
|
*/
|
|
4853
|
-
|
|
5089
|
+
private createQueueKey;
|
|
4854
5090
|
/**
|
|
4855
|
-
*
|
|
4856
|
-
*
|
|
4857
|
-
* @returns Array of items in insertion order
|
|
5091
|
+
* Gets or creates a queue for the given key
|
|
4858
5092
|
*/
|
|
4859
|
-
|
|
5093
|
+
private getQueue;
|
|
4860
5094
|
/**
|
|
4861
|
-
*
|
|
5095
|
+
* Check if a document has any jobs currently executing
|
|
4862
5096
|
*/
|
|
4863
|
-
|
|
5097
|
+
private isDocumentExecuting;
|
|
4864
5098
|
/**
|
|
4865
|
-
*
|
|
5099
|
+
* Mark a job as executing for its document
|
|
4866
5100
|
*/
|
|
4867
|
-
|
|
4868
|
-
}
|
|
4869
|
-
//#endregion
|
|
4870
|
-
//#region src/cache/kysely-write-cache.d.ts
|
|
4871
|
-
type DocumentStream = {
|
|
4872
|
-
key: string;
|
|
4873
|
-
ringBuffer: RingBuffer<CachedSnapshot>;
|
|
4874
|
-
};
|
|
4875
|
-
/**
|
|
4876
|
-
* In-memory write cache with keyframe persistence for PHDocuments.
|
|
4877
|
-
*
|
|
4878
|
-
* Caches document snapshots in ring buffers with LRU eviction. On cache miss,
|
|
4879
|
-
* rebuilds documents from nearest keyframe or full operation history.
|
|
4880
|
-
*
|
|
4881
|
-
* **Performance Characteristics:**
|
|
4882
|
-
* - Cache hit: O(1) lookup in ring buffer
|
|
4883
|
-
* - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe
|
|
4884
|
-
* - Warm miss: O(m) where m is operations since cached revision
|
|
4885
|
-
* - Eviction: O(1) for LRU tracking and removal
|
|
4886
|
-
*
|
|
4887
|
-
* **Thread Safety:**
|
|
4888
|
-
* Not thread-safe. Designed for single-threaded job executor environment.
|
|
4889
|
-
* External synchronization required for concurrent access across multiple executors.
|
|
4890
|
-
*
|
|
4891
|
-
* **Example:**
|
|
4892
|
-
* ```typescript
|
|
4893
|
-
* const cache = new KyselyWriteCache(
|
|
4894
|
-
* keyframeStore,
|
|
4895
|
-
* operationStore,
|
|
4896
|
-
* registry,
|
|
4897
|
-
* { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }
|
|
4898
|
-
* );
|
|
4899
|
-
*
|
|
4900
|
-
* await cache.startup();
|
|
4901
|
-
*
|
|
4902
|
-
* // Retrieve or rebuild document
|
|
4903
|
-
* const doc = await cache.getState(docId, docType, scope, branch, revision);
|
|
4904
|
-
*
|
|
4905
|
-
* // Cache result after job execution
|
|
4906
|
-
* cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);
|
|
4907
|
-
*
|
|
4908
|
-
* await cache.shutdown();
|
|
4909
|
-
* ```
|
|
4910
|
-
*/
|
|
4911
|
-
declare class KyselyWriteCache implements IWriteCache {
|
|
4912
|
-
private streams;
|
|
4913
|
-
private lruTracker;
|
|
4914
|
-
private keyframeStore;
|
|
4915
|
-
private operationStore;
|
|
4916
|
-
private registry;
|
|
4917
|
-
private config;
|
|
4918
|
-
constructor(keyframeStore: IKeyframeStore, operationStore: IOperationStore, registry: IDocumentModelRegistry, config: WriteCacheConfig);
|
|
4919
|
-
withScopedStores(operationStore: IOperationStore, keyframeStore: IKeyframeStore): KyselyWriteCache;
|
|
5101
|
+
private markJobExecuting;
|
|
4920
5102
|
/**
|
|
4921
|
-
*
|
|
4922
|
-
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
5103
|
+
* Mark a job as no longer executing for its document
|
|
4923
5104
|
*/
|
|
4924
|
-
|
|
5105
|
+
private markJobComplete;
|
|
4925
5106
|
/**
|
|
4926
|
-
*
|
|
4927
|
-
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
5107
|
+
* Check if all dependencies for a job have been completed
|
|
4928
5108
|
*/
|
|
4929
|
-
|
|
5109
|
+
private areDependenciesMet;
|
|
4930
5110
|
/**
|
|
4931
|
-
*
|
|
4932
|
-
*
|
|
4933
|
-
* Cache hit path: Returns cached snapshot if available (O(1))
|
|
4934
|
-
* Warm miss path: Rebuilds from cached base revision + incremental ops
|
|
4935
|
-
* Cold miss path: Rebuilds from keyframe or from scratch using all operations
|
|
5111
|
+
* Returns the head of the sub-queue if its dependencies are met, or null.
|
|
4936
5112
|
*
|
|
4937
|
-
*
|
|
4938
|
-
*
|
|
4939
|
-
*
|
|
4940
|
-
*
|
|
4941
|
-
*
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
5113
|
+
* The dispatcher only ever considers the head — a dep-blocked head holds
|
|
5114
|
+
* the rest of its sub-queue. This preserves per-(documentId, scope, branch)
|
|
5115
|
+
* FIFO regardless of how dependencies are authored, and makes the queue's
|
|
5116
|
+
* documented "serialized per document" invariant hold even when callers
|
|
5117
|
+
* omit queueHint dependencies on jobs that share a sub-queue.
|
|
5118
|
+
*/
|
|
5119
|
+
private getNextJobWithMetDependencies;
|
|
5120
|
+
private getCreateDocumentType;
|
|
5121
|
+
enqueue(job: Job): Promise<void>;
|
|
5122
|
+
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5123
|
+
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5124
|
+
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5125
|
+
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
5126
|
+
totalSize(): Promise<number>;
|
|
5127
|
+
remove(jobId: string): Promise<boolean>;
|
|
5128
|
+
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
5129
|
+
clearAll(): Promise<void>;
|
|
5130
|
+
hasJobs(): Promise<boolean>;
|
|
5131
|
+
completeJob(jobId: string): Promise<void>;
|
|
5132
|
+
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
5133
|
+
deferJob(jobId: string): void;
|
|
5134
|
+
retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
|
|
5135
|
+
/**
|
|
5136
|
+
* Check if the queue is drained and call the callback if it is
|
|
5137
|
+
*/
|
|
5138
|
+
private checkDrained;
|
|
5139
|
+
/**
|
|
5140
|
+
* Returns true if and only if all jobs have been resolved.
|
|
4948
5141
|
*/
|
|
4949
|
-
|
|
5142
|
+
get isDrained(): boolean;
|
|
4950
5143
|
/**
|
|
4951
|
-
*
|
|
4952
|
-
*
|
|
4953
|
-
* The cached document is a shallow copy of the input with its operation history
|
|
4954
|
-
* truncated to the last operation per scope and its clipboard cleared. This keeps
|
|
4955
|
-
* memory use and copy costs constant regardless of operation count. Consumers of
|
|
4956
|
-
* getState() must not rely on the full operation history being present; the only
|
|
4957
|
-
* guaranteed invariant is that operations[scope].at(-1) reflects the latest
|
|
4958
|
-
* operation index for each scope.
|
|
4959
|
-
*
|
|
4960
|
-
* Updates LRU tracker and may evict least recently used stream if at capacity.
|
|
4961
|
-
* Asynchronously persists keyframes at configured intervals (fire-and-forget).
|
|
4962
|
-
*
|
|
4963
|
-
* @param documentId - The document identifier
|
|
4964
|
-
* @param scope - The operation scope
|
|
4965
|
-
* @param branch - The operation branch
|
|
4966
|
-
* @param revision - The revision number
|
|
4967
|
-
* @param document - The document to cache
|
|
4968
|
-
* @throws {Error} If document serialization fails
|
|
5144
|
+
* Blocks the queue from accepting new jobs.
|
|
5145
|
+
* @param onDrained - Optional callback to call when the queue is drained
|
|
4969
5146
|
*/
|
|
4970
|
-
|
|
5147
|
+
block(onDrained?: () => void): void;
|
|
4971
5148
|
/**
|
|
4972
|
-
*
|
|
4973
|
-
*
|
|
4974
|
-
* Supports three invalidation scopes:
|
|
4975
|
-
* - Document-level: invalidate(documentId) - removes all streams for document
|
|
4976
|
-
* - Scope-level: invalidate(documentId, scope) - removes all branches for scope
|
|
4977
|
-
* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream
|
|
4978
|
-
*
|
|
4979
|
-
* @param documentId - The document identifier
|
|
4980
|
-
* @param scope - Optional scope to narrow invalidation
|
|
4981
|
-
* @param branch - Optional branch to narrow invalidation (requires scope)
|
|
4982
|
-
* @returns The number of streams evicted
|
|
5149
|
+
* Unblocks the queue from accepting new jobs.
|
|
4983
5150
|
*/
|
|
4984
|
-
|
|
5151
|
+
unblock(): void;
|
|
4985
5152
|
/**
|
|
4986
|
-
*
|
|
4987
|
-
* Resets LRU tracking state. This operation always succeeds.
|
|
5153
|
+
* Pauses job dequeuing. Jobs can still be enqueued but dequeueNext() will return null.
|
|
4988
5154
|
*/
|
|
4989
|
-
|
|
5155
|
+
pause(): void;
|
|
4990
5156
|
/**
|
|
4991
|
-
*
|
|
4992
|
-
* for testing, but not on the interface.
|
|
4993
|
-
*
|
|
4994
|
-
* @internal
|
|
5157
|
+
* Resumes job dequeuing and emits JOB_AVAILABLE events for pending jobs to wake up executors.
|
|
4995
5158
|
*/
|
|
4996
|
-
|
|
4997
|
-
private findNearestKeyframe;
|
|
4998
|
-
private coldMissRebuild;
|
|
5159
|
+
resume(): Promise<void>;
|
|
4999
5160
|
/**
|
|
5000
|
-
*
|
|
5001
|
-
*
|
|
5002
|
-
* Uses the validated-upgrade boundary rules from D7:
|
|
5003
|
-
* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary
|
|
5004
|
-
* - Otherwise: timestamp fallback
|
|
5005
|
-
* - Falls back to final module version when neither is decidable
|
|
5161
|
+
* Returns whether job dequeuing is paused.
|
|
5006
5162
|
*/
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
private get queryExecutor();
|
|
5021
|
-
withTransaction(trx: Transaction<Database$1>): KyselyOperationStore;
|
|
5022
|
-
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal): Promise<Operation[]>;
|
|
5023
|
-
private resolveUniqueConstraint;
|
|
5024
|
-
private executeApply;
|
|
5025
|
-
private findIdempotentReplay;
|
|
5026
|
-
getSince(documentId: string, scope: string, branch: string, revision: number, filter?: OperationFilter, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
5027
|
-
getSinceId(id: number, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<OperationWithContext$1>>;
|
|
5028
|
-
getConflicting(documentId: string, scope: string, branch: string, minTimestamp: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
5029
|
-
getRevisions(documentId: string, branch: string, signal?: AbortSignal): Promise<DocumentRevisions>;
|
|
5030
|
-
private rowToOperation;
|
|
5031
|
-
private rowToOperationWithContext;
|
|
5163
|
+
get paused(): boolean;
|
|
5164
|
+
/**
|
|
5165
|
+
* Returns all pending jobs across all queues.
|
|
5166
|
+
*/
|
|
5167
|
+
getPendingJobs(): Job[];
|
|
5168
|
+
/**
|
|
5169
|
+
* Returns a map of document IDs to sets of executing job IDs.
|
|
5170
|
+
*/
|
|
5171
|
+
getExecutingJobIds(): Map<string, Set<string>>;
|
|
5172
|
+
/**
|
|
5173
|
+
* Returns a job by ID from the job index.
|
|
5174
|
+
*/
|
|
5175
|
+
getJob(jobId: string): Job | undefined;
|
|
5032
5176
|
}
|
|
5033
5177
|
//#endregion
|
|
5034
|
-
//#region src/
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5178
|
+
//#region src/job-tracker/in-memory-job-tracker.d.ts
|
|
5179
|
+
/**
|
|
5180
|
+
* In-memory implementation of IJobTracker.
|
|
5181
|
+
* Maintains job status in a Map for synchronous access.
|
|
5182
|
+
* Subscribes to operation events to update job states.
|
|
5183
|
+
*/
|
|
5184
|
+
declare class InMemoryJobTracker implements IJobTracker {
|
|
5185
|
+
private eventBus;
|
|
5186
|
+
private jobs;
|
|
5187
|
+
private unsubscribers;
|
|
5188
|
+
constructor(eventBus: IEventBus);
|
|
5189
|
+
private subscribeToEvents;
|
|
5190
|
+
private handleWriteReady;
|
|
5191
|
+
private handleReadReady;
|
|
5192
|
+
private handleJobFailed;
|
|
5193
|
+
shutdown(): void;
|
|
5194
|
+
registerJob(jobInfo: JobInfo): void;
|
|
5195
|
+
markRunning(jobId: string): void;
|
|
5196
|
+
markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
|
|
5197
|
+
getJobStatus(jobId: string): JobInfo | null;
|
|
5053
5198
|
}
|
|
5054
5199
|
//#endregion
|
|
5055
|
-
//#region src/executor/
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5200
|
+
//#region src/executor/simple-job-executor-manager.d.ts
|
|
5201
|
+
type JobExecutorFactory = () => IJobExecutor;
|
|
5202
|
+
/**
|
|
5203
|
+
* Manages multiple job executors and coordinates job distribution.
|
|
5204
|
+
* Listens for job available events and dispatches jobs to executors.
|
|
5205
|
+
*/
|
|
5206
|
+
declare class SimpleJobExecutorManager implements IJobExecutorManager {
|
|
5207
|
+
private executorFactory;
|
|
5208
|
+
private eventBus;
|
|
5209
|
+
private queue;
|
|
5210
|
+
private jobTracker;
|
|
5211
|
+
private logger;
|
|
5212
|
+
private resolver;
|
|
5213
|
+
private executors;
|
|
5214
|
+
private isRunning;
|
|
5215
|
+
private activeJobs;
|
|
5216
|
+
private totalJobsProcessed;
|
|
5217
|
+
private unsubscribe?;
|
|
5218
|
+
private deferredJobs;
|
|
5219
|
+
private resultHandler;
|
|
5220
|
+
private jobTimeoutMs;
|
|
5221
|
+
constructor(executorFactory: JobExecutorFactory, eventBus: IEventBus, queue: IQueue, jobTracker: IJobTracker, logger: ILogger, resolver: IDocumentModelResolver, jobTimeoutMs?: number);
|
|
5222
|
+
start(numExecutors: number): Promise<void>;
|
|
5223
|
+
stop(graceful?: boolean): Promise<void>;
|
|
5224
|
+
getExecutors(): IJobExecutor[];
|
|
5225
|
+
getStatus(): ExecutorManagerStatus;
|
|
5226
|
+
private processNextJob;
|
|
5227
|
+
private checkForMoreJobs;
|
|
5228
|
+
private processExistingJobs;
|
|
5229
|
+
private flushDeferredJobs;
|
|
5065
5230
|
}
|
|
5066
5231
|
//#endregion
|
|
5067
5232
|
//#region src/executor/simple-job-executor.d.ts
|
|
@@ -5079,6 +5244,8 @@ declare class SimpleJobExecutor implements IJobExecutor {
|
|
|
5079
5244
|
private collectionMembershipCache;
|
|
5080
5245
|
private driveContainerTypes;
|
|
5081
5246
|
private config;
|
|
5247
|
+
private featureFlags;
|
|
5248
|
+
private decisionModel;
|
|
5082
5249
|
private signatureVerifierModule;
|
|
5083
5250
|
private documentActionHandler;
|
|
5084
5251
|
private executionScope;
|
|
@@ -5091,6 +5258,62 @@ declare class SimpleJobExecutor implements IJobExecutor {
|
|
|
5091
5258
|
private getCollectionMembershipsForOperations;
|
|
5092
5259
|
private processActions;
|
|
5093
5260
|
private executeRegularAction;
|
|
5261
|
+
/**
|
|
5262
|
+
* Orders a write by timestamp and decides it where it lands. The caller
|
|
5263
|
+
* supplies the timestamp, so a write can belong before operations already
|
|
5264
|
+
* stored; those are re-appended alongside it, the way a load reshuffles.
|
|
5265
|
+
*
|
|
5266
|
+
* Deciding a backdated write at the stream heads instead of at its position
|
|
5267
|
+
* would overwrite the verdict every other replica computes for it.
|
|
5268
|
+
*/
|
|
5269
|
+
private positionByTimestamp;
|
|
5270
|
+
/**
|
|
5271
|
+
* Decides each operation where it lands and carries the verdict on it. A
|
|
5272
|
+
* refused submitted action is reported to the caller and nothing is stored; a
|
|
5273
|
+
* refused operation the reshuffle merely moved keeps its verdict, because it
|
|
5274
|
+
* already holds a position.
|
|
5275
|
+
*
|
|
5276
|
+
* The operations carry the indexes and skips they will be stored at, because
|
|
5277
|
+
* the walk resolves skips before it orders them.
|
|
5278
|
+
*/
|
|
5279
|
+
private evaluatePositioned;
|
|
5280
|
+
/**
|
|
5281
|
+
* The scopes a re-evaluation pass visits, in a fixed order.
|
|
5282
|
+
*
|
|
5283
|
+
* The revisions map comes from a query with no ORDER BY, and the order is
|
|
5284
|
+
* load-bearing: each scope's pass re-reads the auth stream, and the walk skips
|
|
5285
|
+
* an operation by its stored denial, so a denial this pass just wrote is
|
|
5286
|
+
* visible to a later-visited scope and invisible to an earlier one. The model's
|
|
5287
|
+
* own projection order leads, then the rest sorted, so the pass is reproducible
|
|
5288
|
+
* across replicas and across runs.
|
|
5289
|
+
*/
|
|
5290
|
+
private evaluationOrder;
|
|
5291
|
+
/**
|
|
5292
|
+
* The first timestamp in the batch that does not strictly exceed everything
|
|
5293
|
+
* ahead of it, or undefined when the whole batch is monotonic.
|
|
5294
|
+
*
|
|
5295
|
+
* The bound is carried forward rather than compared against one stored maximum,
|
|
5296
|
+
* because a single execute can carry several auth actions stamped in the same
|
|
5297
|
+
* millisecond. Letting a tie through would store a stream the position walk
|
|
5298
|
+
* then refuses to read, with no repair path.
|
|
5299
|
+
*/
|
|
5300
|
+
private firstNonMonotonicTimestamp;
|
|
5301
|
+
/** The operations a batch of submitted actions appends at the scope's tail. */
|
|
5302
|
+
private appendedOperations;
|
|
5303
|
+
/**
|
|
5304
|
+
* Re-evaluates the document when a write meets both criteria: it was written
|
|
5305
|
+
* to a stream the model reads, and it is timestamped before an operation
|
|
5306
|
+
* already stored. The caller supplies the timestamp and the reactor does not replace
|
|
5307
|
+
* it, so a mutation job can write such an operation just as a load job can,
|
|
5308
|
+
* which is why both executeJob and executeLoadJob call this.
|
|
5309
|
+
*/
|
|
5310
|
+
private reevaluateIfCriteriaMet;
|
|
5311
|
+
/**
|
|
5312
|
+
* Re-evaluates every scope the model evaluates. Where an operation's
|
|
5313
|
+
* evaluation differs from what is stored, the tail from that operation is
|
|
5314
|
+
* re-appended, carrying a skip that spans the indices it supersedes.
|
|
5315
|
+
*/
|
|
5316
|
+
private reevaluateDocument;
|
|
5094
5317
|
private executeLoadJob;
|
|
5095
5318
|
private accumulateResultOrReturnError;
|
|
5096
5319
|
}
|
|
@@ -5159,6 +5382,141 @@ declare class DocumentModelRegistry implements IDocumentModelRegistry {
|
|
|
5159
5382
|
getUpgradeReducer(documentType: string, fromVersion: number, toVersion: number): UpgradeReducer<any, any>;
|
|
5160
5383
|
}
|
|
5161
5384
|
//#endregion
|
|
5385
|
+
//#region src/decision/types.d.ts
|
|
5386
|
+
/** One operation stream. */
|
|
5387
|
+
type StreamQuery = {
|
|
5388
|
+
documentId: string;
|
|
5389
|
+
branch: string;
|
|
5390
|
+
scope: string;
|
|
5391
|
+
};
|
|
5392
|
+
/** The document and branch a decision model is built for. */
|
|
5393
|
+
type DecisionTarget = {
|
|
5394
|
+
documentId: string;
|
|
5395
|
+
branch: string;
|
|
5396
|
+
};
|
|
5397
|
+
/** The executing scope's own state, for conditions that read it. */
|
|
5398
|
+
type DecisionContext = {
|
|
5399
|
+
scopeState: unknown;
|
|
5400
|
+
};
|
|
5401
|
+
/**
|
|
5402
|
+
* A named stream whose value in the model is that scope's state from the
|
|
5403
|
+
* document rebuild the reactor already performs. A derived query may read
|
|
5404
|
+
* only statically-queried projections, so composition is one layer deep.
|
|
5405
|
+
*/
|
|
5406
|
+
type Projection<M> = {
|
|
5407
|
+
query: StreamQuery | ((model: Partial<M>) => StreamQuery[]);
|
|
5408
|
+
/**
|
|
5409
|
+
* Action types in this stream that can change an evaluation. Reads of the stream
|
|
5410
|
+
* are filtered to these, so anything left out is invisible to a decision.
|
|
5411
|
+
*/
|
|
5412
|
+
decidingActions: string[]; /** Applies one of this stream's operations while deciding. */
|
|
5413
|
+
apply: (document: PHDocument, operation: Operation) => PHDocument;
|
|
5414
|
+
};
|
|
5415
|
+
/**
|
|
5416
|
+
* The outcome of evaluating one operation. A refusal carries the reason it is
|
|
5417
|
+
* recorded with, because a model has more than one way to refuse.
|
|
5418
|
+
*/
|
|
5419
|
+
type Evaluation = {
|
|
5420
|
+
decision: "allow";
|
|
5421
|
+
} | {
|
|
5422
|
+
decision: "deny";
|
|
5423
|
+
reason: string;
|
|
5424
|
+
};
|
|
5425
|
+
/** Projections plus a decision function over the built model. */
|
|
5426
|
+
type DecisionModel<M> = {
|
|
5427
|
+
projections: { [K in keyof M]: Projection<M> };
|
|
5428
|
+
/**
|
|
5429
|
+
* Whether or not this model decides about operations in a given scope. That
|
|
5430
|
+
* is, a scope it reads is not necessarily one it evaluates, and vise-versa.
|
|
5431
|
+
*/
|
|
5432
|
+
evaluatesScope(scope: string): boolean;
|
|
5433
|
+
decide(model: M, subject: AuthSubject, request: AuthRequest, ctx: DecisionContext): Evaluation;
|
|
5434
|
+
};
|
|
5435
|
+
/** A built model plus the read-set condition recording what the build read. */
|
|
5436
|
+
type BuiltDecisionModel<M> = {
|
|
5437
|
+
model: M;
|
|
5438
|
+
appendCondition: AppendCondition;
|
|
5439
|
+
};
|
|
5440
|
+
//#endregion
|
|
5441
|
+
//#region src/decision/build-decision-model.d.ts
|
|
5442
|
+
/**
|
|
5443
|
+
* Reads each projection's stream through the write cache, recording the
|
|
5444
|
+
* revision observed. Static projections resolve first; derived projections
|
|
5445
|
+
* see only those and contribute a map from document id to state. Each
|
|
5446
|
+
* distinct stream is read once and yields one append condition entry.
|
|
5447
|
+
*/
|
|
5448
|
+
declare function buildDecisionModel<M>(cache: IWriteCache, definition: (target: DecisionTarget) => DecisionModel<M>, target: DecisionTarget, signal?: AbortSignal): Promise<BuiltDecisionModel<M>>;
|
|
5449
|
+
//#endregion
|
|
5450
|
+
//#region src/decision/auth-decision-model.d.ts
|
|
5451
|
+
type AuthDecisionModel = {
|
|
5452
|
+
document: PHDocumentState;
|
|
5453
|
+
auth: PHAuthState;
|
|
5454
|
+
};
|
|
5455
|
+
/** This decision model uses both the document and the auth streams. */
|
|
5456
|
+
declare function authDecisionModel(target: DecisionTarget): DecisionModel<AuthDecisionModel>;
|
|
5457
|
+
//#endregion
|
|
5458
|
+
//#region src/decision/document-decision-model.d.ts
|
|
5459
|
+
/** What the document decision model reads: the target's document scope. */
|
|
5460
|
+
type DocumentDecisionModel = {
|
|
5461
|
+
document: PHDocumentState;
|
|
5462
|
+
};
|
|
5463
|
+
/**
|
|
5464
|
+
* The simplest decision model: one projection over the document scope, which
|
|
5465
|
+
* rejects on a deleted document.
|
|
5466
|
+
*/
|
|
5467
|
+
declare function documentDecisionModel(target: DecisionTarget): DecisionModel<DocumentDecisionModel>;
|
|
5468
|
+
//#endregion
|
|
5469
|
+
//#region src/decision/registered-model.d.ts
|
|
5470
|
+
/**
|
|
5471
|
+
* A model this reactor can register. Every one carries the document projection,
|
|
5472
|
+
* because admission reads the version and the deletion timestamp off it; a model
|
|
5473
|
+
* with more projections than that is still assignable here.
|
|
5474
|
+
*/
|
|
5475
|
+
type RegisteredDecisionModel = (target: DecisionTarget) => DecisionModel<DocumentDecisionModel>;
|
|
5476
|
+
/** What admission needs out of a model built at the stream heads. */
|
|
5477
|
+
type AdmissionDecision = {
|
|
5478
|
+
evaluation: Evaluation;
|
|
5479
|
+
appendCondition: AppendCondition;
|
|
5480
|
+
documentVersion: number;
|
|
5481
|
+
deletedAtUtcIso: string | null;
|
|
5482
|
+
};
|
|
5483
|
+
/**
|
|
5484
|
+
* Builds the model at the stream heads and decides one request against it. The
|
|
5485
|
+
* append condition it returns is the read-set the store enforces at write time.
|
|
5486
|
+
*/
|
|
5487
|
+
declare function decideAtHead(model: RegisteredDecisionModel, cache: IWriteCache, target: DecisionTarget, subject: AuthSubject, request: AuthRequest, signal?: AbortSignal): Promise<AdmissionDecision>;
|
|
5488
|
+
/**
|
|
5489
|
+
* The model this reactor enforces. With `authEnforcement` off the auth scope is
|
|
5490
|
+
* absent from every append condition and no load walks it.
|
|
5491
|
+
*/
|
|
5492
|
+
declare function selectDecisionModel(flags: ReactorFeatureFlags): RegisteredDecisionModel;
|
|
5493
|
+
//#endregion
|
|
5494
|
+
//#region src/decision/stream-order.d.ts
|
|
5495
|
+
/** Where a stream's stored order contradicts its timestamps. */
|
|
5496
|
+
type OutOfOrderPair = {
|
|
5497
|
+
previous: Operation;
|
|
5498
|
+
current: Operation;
|
|
5499
|
+
/**
|
|
5500
|
+
* `descending` cannot be walked at all. `tied` walks fine — the intra-stream
|
|
5501
|
+
* rule breaks the tie by index — but violates the monotonic auth rule, so a
|
|
5502
|
+
* stream holding one can never be replicated to a peer that lacks it.
|
|
5503
|
+
*/
|
|
5504
|
+
kind: "descending" | "tied";
|
|
5505
|
+
};
|
|
5506
|
+
/**
|
|
5507
|
+
* The first pair of effective operations whose stored order contradicts their
|
|
5508
|
+
* timestamps, or undefined when the stream is in position order.
|
|
5509
|
+
*
|
|
5510
|
+
* Such a stream cannot be walked, and the auth stream is never reshuffled once
|
|
5511
|
+
* the monotonic rule is on, so run this before enabling enforcement on a fleet.
|
|
5512
|
+
*
|
|
5513
|
+
* `requireStrict` additionally rejects a tie, which is what the auth stream's
|
|
5514
|
+
* monotonic rule requires and what the walk alone does not care about.
|
|
5515
|
+
*/
|
|
5516
|
+
declare function firstOutOfOrderPair(operations: Operation[], options?: {
|
|
5517
|
+
requireStrict?: boolean;
|
|
5518
|
+
}): OutOfOrderPair | undefined;
|
|
5519
|
+
//#endregion
|
|
5162
5520
|
//#region src/read-models/base-read-model.d.ts
|
|
5163
5521
|
type BaseReadModelConfig = {
|
|
5164
5522
|
readModelId: string;
|
|
@@ -5243,7 +5601,7 @@ declare class KyselyDocumentIndexer extends BaseReadModel implements IDocumentIn
|
|
|
5243
5601
|
* serialized so the executor can return to dispatch without holding ordering
|
|
5244
5602
|
* implicitly.
|
|
5245
5603
|
*/
|
|
5246
|
-
declare class ReadModelCoordinator implements
|
|
5604
|
+
declare class ReadModelCoordinator implements ILiveReadModelCoordinator {
|
|
5247
5605
|
private eventBus;
|
|
5248
5606
|
readonly preReady: IReadModel[];
|
|
5249
5607
|
readonly postReady: IReadModel[];
|
|
@@ -5262,6 +5620,7 @@ declare class ReadModelCoordinator implements IReadModelCoordinator {
|
|
|
5262
5620
|
*/
|
|
5263
5621
|
drain(): Promise<void>;
|
|
5264
5622
|
getChainDepth(): number;
|
|
5623
|
+
addReadModel(readModel: IReadModel, stage: ReadModelRegistrationStage): void;
|
|
5265
5624
|
private handleWriteReady;
|
|
5266
5625
|
private emitEmptyReadReady;
|
|
5267
5626
|
private runChain;
|
|
@@ -5275,8 +5634,21 @@ declare class ReadModelCoordinator implements IReadModelCoordinator {
|
|
|
5275
5634
|
type Database$2 = Database$1 & DocumentViewDatabase;
|
|
5276
5635
|
declare class KyselyDocumentView extends BaseReadModel implements IDocumentView {
|
|
5277
5636
|
private operationStore;
|
|
5637
|
+
/**
|
|
5638
|
+
* Whether a single-document read serves a deleted document's state as of the
|
|
5639
|
+
* deletion rather than hiding it. Only meaningful with `documentDecisions`,
|
|
5640
|
+
* which is what makes deletion positional. Listings omit it either way.
|
|
5641
|
+
*/
|
|
5642
|
+
private readonly servesDeletionBoundary;
|
|
5278
5643
|
private _db;
|
|
5279
|
-
constructor(db: Kysely<Database$2>, operationStore: IOperationStore, operationIndex: IOperationIndex, writeCache: IWriteCache, consistencyTracker: IConsistencyTracker
|
|
5644
|
+
constructor(db: Kysely<Database$2>, operationStore: IOperationStore, operationIndex: IOperationIndex, writeCache: IWriteCache, consistencyTracker: IConsistencyTracker,
|
|
5645
|
+
/**
|
|
5646
|
+
* Whether a single-document read serves a deleted document's state as of the
|
|
5647
|
+
* deletion rather than hiding it. Only meaningful with `documentDecisions`,
|
|
5648
|
+
* which is what makes deletion positional. Listings omit it either way.
|
|
5649
|
+
*/
|
|
5650
|
+
|
|
5651
|
+
servesDeletionBoundary: boolean);
|
|
5280
5652
|
protected commitOperations(items: OperationWithContext$1[]): Promise<void>;
|
|
5281
5653
|
exists(documentIds: string[], consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<boolean[]>;
|
|
5282
5654
|
get<TDocument extends PHDocument>(documentId: string, view?: ViewFilter$1, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
@@ -5408,6 +5780,8 @@ declare class GqlRequestChannel implements IChannel {
|
|
|
5408
5780
|
private isPushing;
|
|
5409
5781
|
private pendingDrain;
|
|
5410
5782
|
private receivingPages;
|
|
5783
|
+
/** Cleared for good the first time the remote rejects {@link DECISION_FIELDS}. */
|
|
5784
|
+
private peerServesDecisionFields;
|
|
5411
5785
|
private isRecovering;
|
|
5412
5786
|
private connectionState;
|
|
5413
5787
|
/** Latest unrecoverable error was an auth rejection; cleared on connect. */
|
|
@@ -5454,6 +5828,18 @@ declare class GqlRequestChannel implements IChannel {
|
|
|
5454
5828
|
* Queries the remote GraphQL endpoint for sync envelopes.
|
|
5455
5829
|
*/
|
|
5456
5830
|
private pollSyncEnvelopes;
|
|
5831
|
+
/**
|
|
5832
|
+
* True when the remote rejected the query for naming a field it does not
|
|
5833
|
+
* have. Selecting an unknown field fails validation for the whole query, so
|
|
5834
|
+
* an unhandled one takes the channel's polling down until the process
|
|
5835
|
+
* restarts rather than degrading.
|
|
5836
|
+
*/
|
|
5837
|
+
private rejectsDecisionFields;
|
|
5838
|
+
/**
|
|
5839
|
+
* The poll query. `withDecisionFields` selects the two fields added with the
|
|
5840
|
+
* auth projection; a remote on the previous schema is polled without them.
|
|
5841
|
+
*/
|
|
5842
|
+
private pollQuery;
|
|
5457
5843
|
/**
|
|
5458
5844
|
* Registers or updates this channel on the remote server via GraphQL mutation.
|
|
5459
5845
|
* Returns the remote's ack ordinal so the client can trim its outbox.
|
|
@@ -5616,6 +6002,18 @@ declare function batchOperationsByDocument(operations: OperationWithContext$1[])
|
|
|
5616
6002
|
* jobId; all other jobIds are remapped so external dependencies still resolve.
|
|
5617
6003
|
*/
|
|
5618
6004
|
declare function consolidateSyncOperations(syncOps: SyncOperation[]): SyncOperation[];
|
|
6005
|
+
/**
|
|
6006
|
+
* Classifies a failure by error name rather than `instanceof`, because a failure
|
|
6007
|
+
* that crossed the pooled-worker boundary arrives as plain data.
|
|
6008
|
+
*/
|
|
6009
|
+
declare function classifyJobFailure(errorName: string): SyncOperationErrorType;
|
|
6010
|
+
/** The explicit type when something else carried it, else derived by name. */
|
|
6011
|
+
declare function syncOperationErrorType(error: ChannelError | undefined): SyncOperationErrorType;
|
|
6012
|
+
/**
|
|
6013
|
+
* A held auth operation must not quarantine: reconciling the two policies needs
|
|
6014
|
+
* the traffic a quarantine would stop.
|
|
6015
|
+
*/
|
|
6016
|
+
declare function quarantinesDocument(errorType: SyncOperationErrorType): boolean;
|
|
5619
6017
|
//#endregion
|
|
5620
6018
|
//#region src/admin/types.d.ts
|
|
5621
6019
|
type KeyframeValidationIssue = {
|
|
@@ -5631,11 +6029,20 @@ type SnapshotValidationIssue = {
|
|
|
5631
6029
|
snapshotHash: string;
|
|
5632
6030
|
replayedHash: string;
|
|
5633
6031
|
};
|
|
6032
|
+
/** Effective operations whose stored order contradicts their timestamps. */
|
|
6033
|
+
type StreamOrderIssue = {
|
|
6034
|
+
scope: string;
|
|
6035
|
+
branch: string;
|
|
6036
|
+
previous: Operation;
|
|
6037
|
+
current: Operation;
|
|
6038
|
+
kind: OutOfOrderPair["kind"];
|
|
6039
|
+
};
|
|
5634
6040
|
type ValidationResult = {
|
|
5635
6041
|
documentId: string;
|
|
5636
6042
|
isConsistent: boolean;
|
|
5637
6043
|
keyframeIssues: KeyframeValidationIssue[];
|
|
5638
6044
|
snapshotIssues: SnapshotValidationIssue[];
|
|
6045
|
+
streamOrderIssues: StreamOrderIssue[];
|
|
5639
6046
|
};
|
|
5640
6047
|
type RebuildResult = {
|
|
5641
6048
|
documentId: string;
|
|
@@ -5659,6 +6066,7 @@ declare class DocumentIntegrityService implements IDocumentIntegrityService {
|
|
|
5659
6066
|
validateDocument(documentId: string, branch?: string, signal?: AbortSignal): Promise<ValidationResult>;
|
|
5660
6067
|
rebuildKeyframes(documentId: string, branch?: string, signal?: AbortSignal): Promise<RebuildResult>;
|
|
5661
6068
|
rebuildSnapshots(documentId: string, branch?: string, signal?: AbortSignal): Promise<RebuildResult>;
|
|
6069
|
+
private findStreamOrderIssues;
|
|
5662
6070
|
private discoverScopes;
|
|
5663
6071
|
}
|
|
5664
6072
|
//#endregion
|
|
@@ -5707,5 +6115,5 @@ declare class ProcessorManager extends BaseReadModel implements IProcessorManage
|
|
|
5707
6115
|
private deleteProcessorCursors;
|
|
5708
6116
|
}
|
|
5709
6117
|
//#endregion
|
|
5710
|
-
export { type AbortMessage, type AtomicTxn, type AttachmentHash, type AttachmentRef, BaseReadModel, type BatchExecutionRequest, type BatchExecutionResult, type BatchLoadRequest, type BatchLoadResult, type BuiltInReadModelKind, type CachedSnapshot, type ChannelConfig, ChannelError, ChannelErrorSource, type ChannelHealth, type ChannelMeta, ChannelScheme, type ConnectionState, type ConnectionStateChangeCallback, type ConnectionStateChangedEvent, type ConnectionStateSnapshot, type ConsistencyCoordinate, type ConsistencyKey, type ConsistencyToken, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, type Database, type DbConfig, type DeadLetterAddedEvent, DefaultSubscriptionErrorHandler, type DocumentChangeEvent, DocumentChangeType, type DocumentGraphEdge, type DocumentIndexerDatabase, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, type DocumentModelSource, type DocumentModelSpec, type DocumentRelationship, type DocumentRevisions, type DocumentStreamKey, type DocumentViewDatabase, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, type ExecuteMessage, type ExecutionJobPlan, type ExecutorStartedEvent, type ExecutorStoppedEvent, type FactorySpec, type FileModelSource, type GqlChannelConfig, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, type HeartbeatMessage, 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 IMailbox, type IOperationIndex, type IOperationStore, type IPollTimer, type IProcessor, type IProcessorHostModule, type IProcessorManager, type IProjectionTransport, type IQueue, type IReactor, type IReactorClient, type IReactorSubscriptionManager, type IReadModel, type IReadModelCoordinator, type IRelationalDb, type ISubscriptionErrorHandler, type ISyncCursorStorage, type ISyncManager, type ISyncRemoteStorage, type ISyncStatusTracker, type IWriteCache, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, type InProcessReactorClientModule, type InProcessReactorModule, type InProcessSyncModule, type InitMessage, type InsertableDocumentSnapshot, IntervalPollTimer, InvalidModuleError, type Job, type JobAvailableEvent, JobAwaiter, type JobCompletedEvent, type JobExecutorConfig, JobExecutorEventTypes, type JobExecutorFactory, type JobFailedEvent, type JobInfo, type JobPendingEvent, type JobReadReadyEvent, type JobResult, type JobRunningEvent, type JobStartedEvent, JobStatus, type JobWriteReadyEvent, type JobWriteReadyPayload, type JwtHandler, type KeyframeSnapshot, type KeyframeValidationIssue, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, type LoadJobPlan, type LoadModelMessage, type LogMessage, Mailbox, type MetricsMessage, type ModelLoadFailedMessage, type ModelLoadedEvent, type ModelLoadedMessage, type ModelManifestEntry, ModuleNotFoundError, type ModuleRef, NullDocumentModelResolver, type OperationBatch, type OperationContext, type OperationFilter, type OperationIndexEntry, type OperationTable, type OperationWithContext, OptimisticLockError, type PackageModelSource, type PagedResults, type PagingOptions, type ParentMessage, type ParsedDriveUrl, type ParsedPaging, PollBehavior, PollingChannelError, type PoolInstrumentation, type PoolStats, type ProcessorApp, type ProcessorFactory, type ProcessorFactoryBuilder, type ProcessorFilter, ProcessorManager, type ProcessorRecord, type ProcessorStatus, type ProjectionShardBuilderConfig, type ProjectionShardManagerConfig, type ProjectionWorkerFactory, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, type ReactorClientModule, ReactorEventTypes, type ReactorFeatures, type JobFailedEvent$1 as ReactorJobFailedEvent, type ReactorModule, ReactorSubscriptionManager, type ReadModelBatchCompletedEvent, ReadModelCoordinator, type ReadModelFactory, type ReadModelFactoryDeps, type ReadModelIndexedEvent, type ReadModelIndexingStage, type ReadModelStage, type ReadyMessage, type RebuildResult, RelationalDbProcessor, RelationshipChangeType, type Remote, type RemoteCursor, type RemoteFilter, type RemoteMeta, type RemoteOptions, type RemoteRecord, type RemoteStatus, type ResultMessage, RevisionMismatchError, type SanitizedArg, type SearchFilter, type ShutdownMessage, type ShutdownStatus, type SignatureVerificationHandler, type SignatureVerifierSpec, type SignerConfig, SimpleJobExecutorManager, type SnapshotValidationIssue, type Database$1 as StorageDatabase, type SubscriptionErrorContext, SyncBuilder, type SyncEnvelope, type SyncEnvelopeType, SyncEventTypes, type SyncFailedEvent, type SyncModule, SyncOperation, SyncOperationAggregateError, type SyncOperationErrorType, SyncOperationStatus, type SyncPendingEvent, SyncStatus, type SyncStatusChangeCallback, SyncStatusTracker, type SyncSucceededEvent, type TrackedProcessor, type Unsubscribe, type ValidationResult, type ViewFilter, type ErrorInfo as WorkerErrorInfo, type WorkerMessage, type WorkerPoolConfig, type WorkerPoolOptions, type WriteCacheConfig, addRelationshipAction, batchOperationsByDocument, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, removeRelationshipAction, runMigrations, sanitizeArg, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
6118
|
+
export { APPEND_CONDITION_FAILED_PREFIX, type AbortMessage, type AdmissionDecision, type AppendCondition, AppendConditionFailedError, type AppendConditionStream, type AtomicTxn, type AttachmentHash, type AttachmentRef, type AuthDecisionModel, BaseReadModel, type BatchExecutionRequest, type BatchExecutionResult, type BatchLoadRequest, type BatchLoadResult, type BuiltDecisionModel, type BuiltInReadModelKind, type CachedSnapshot, type ChannelConfig, ChannelError, ChannelErrorSource, type ChannelHealth, type ChannelMeta, ChannelScheme, type ConnectionState, type ConnectionStateChangeCallback, type ConnectionStateChangedEvent, type ConnectionStateSnapshot, type ConsistencyCoordinate, type ConsistencyKey, type ConsistencyToken, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, type Database, type DbConfig, type DeadLetterAddedEvent, type DecisionContext, type DecisionModel, type DecisionTarget, DefaultSubscriptionErrorHandler, type DocumentChangeEvent, DocumentChangeType, type DocumentDecisionModel, type DocumentGraphEdge, type DocumentIndexerDatabase, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, type DocumentModelSource, type DocumentModelSpec, type DocumentRelationship, type DocumentRevisions, type DocumentStreamKey, type DocumentViewDatabase, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, type Evaluation, EventBus, EventBusAggregateError, type ExecuteMessage, type ExecutionJobPlan, type ExecutorStartedEvent, type ExecutorStoppedEvent, type FactorySpec, type FileModelSource, type GqlChannelConfig, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, type HeartbeatMessage, 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 IPollTimer, type IProcessor, type IProcessorHostModule, type IProcessorManager, type IProjectionTransport, type IQueue, type IReactor, type IReactorClient, type IReactorSubscriptionManager, type IReadModel, type IReadModelCoordinator, type IRelationalDb, type ISubscriptionErrorHandler, type ISyncCursorStorage, type ISyncManager, type ISyncRemoteStorage, type ISyncStatusTracker, type IWriteCache, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, type InProcessReactorClientModule, type InProcessReactorModule, type InProcessSyncModule, type InitMessage, type InsertableDocumentSnapshot, IntervalPollTimer, InvalidModuleError, type Job, type JobAvailableEvent, JobAwaiter, type JobCompletedEvent, type JobExecutorConfig, JobExecutorEventTypes, type JobExecutorFactory, type JobFailedEvent, type JobInfo, type JobPendingEvent, type JobReadReadyEvent, type JobResult, type JobRunningEvent, type JobStartedEvent, JobStatus, type JobWriteReadyEvent, type JobWriteReadyPayload, type JwtHandler, type KeyframeSnapshot, type KeyframeValidationIssue, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, type LoadJobPlan, type LoadModelMessage, type LogMessage, Mailbox, type MetricsMessage, type ModelLoadFailedMessage, type ModelLoadedEvent, type ModelLoadedMessage, type ModelManifestEntry, ModuleNotFoundError, type ModuleRef, NullDocumentModelResolver, type OperationBatch, type OperationContext, type OperationFilter, type OperationIndexEntry, type OperationTable, type OperationWithContext, OptimisticLockError, type OutOfOrderPair, type PackageModelSource, type PagedResults, type PagingOptions, type ParentMessage, type ParsedDriveUrl, type ParsedPaging, PollBehavior, PollingChannelError, type PoolInstrumentation, type PoolStats, type ProcessorApp, type ProcessorFactory, type ProcessorFactoryBuilder, type ProcessorFilter, ProcessorManager, type ProcessorRecord, type ProcessorStatus, type Projection, type ProjectionShardBuilderConfig, type ProjectionShardManagerConfig, type ProjectionWorkerFactory, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, type ReactorClientModule, ReactorEventTypes, type ReactorFeatureFlags, type ReactorFeatures, type JobFailedEvent$1 as ReactorJobFailedEvent, type ReactorModule, ReactorSubscriptionManager, type ReadModelBatchCompletedEvent, ReadModelCoordinator, type ReadModelFactory, type ReadModelFactoryDeps, type ReadModelIndexedEvent, type ReadModelIndexingStage, type ReadModelRegistrationStage, type ReadModelStage, type ReadyMessage, type RebuildResult, type RegisteredDecisionModel, RelationalDbProcessor, RelationshipChangeType, type Remote, type RemoteCursor, type RemoteFilter, type RemoteMeta, type RemoteOptions, type RemoteRecord, type RemoteStatus, type ResultMessage, RetryAccounting, RevisionMismatchError, type SanitizedArg, type SearchFilter, type ShutdownMessage, type ShutdownStatus, type SignatureVerificationHandler, type SignatureVerifierSpec, type SignerConfig, SimpleJobExecutorManager, type SnapshotValidationIssue, type Database$1 as StorageDatabase, type StreamOrderIssue, type StreamQuery, type SubscriptionErrorContext, SyncBuilder, type SyncEnvelope, type SyncEnvelopeType, SyncEventTypes, type SyncFailedEvent, type SyncModule, SyncOperation, SyncOperationAggregateError, type SyncOperationErrorType, SyncOperationStatus, type SyncPendingEvent, SyncStatus, type SyncStatusChangeCallback, SyncStatusTracker, type SyncSucceededEvent, type TrackedProcessor, type Unsubscribe, type ValidationResult, type ViewFilter, type ErrorInfo as WorkerErrorInfo, type WorkerMessage, type WorkerPoolConfig, type WorkerPoolOptions, type WriteCacheConfig, addRelationshipAction, authDecisionModel, batchOperationsByDocument, buildDecisionModel, classifyJobFailure, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, decideAtHead, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
5711
6119
|
//# sourceMappingURL=index.d.ts.map
|