@powerhousedao/reactor 6.2.2-dev.32 → 6.2.2-dev.33
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-DisavYJh.js → build-worker-executor-B9gIvuvf.js} +2 -2
- package/dist/{build-worker-executor-DisavYJh.js.map → build-worker-executor-B9gIvuvf.js.map} +1 -1
- package/dist/{drive-container-types-CPQDOggp.js → drive-container-types-ZSLCC3lC.js} +210 -96
- package/dist/drive-container-types-ZSLCC3lC.js.map +1 -0
- package/dist/entry.js +2 -2
- package/dist/index.d.ts +1650 -1643
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +2 -2
- package/dist/{worker-B2JPT0sg.js → worker-BMn-2vsH.js} +2 -2
- package/dist/{worker-B2JPT0sg.js.map → worker-BMn-2vsH.js.map} +1 -1
- package/package.json +4 -4
- package/dist/drive-container-types-CPQDOggp.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -606,7 +606,7 @@ interface AtomicTxn {
|
|
|
606
606
|
* revision field and lastModified timestamp.
|
|
607
607
|
*/
|
|
608
608
|
type DocumentRevisions = {
|
|
609
|
-
/** Map of scope to operation index for that scope */revision: Record<string, number>; /**
|
|
609
|
+
/** Map of scope to operation index for that scope */revision: Record<string, number>; /** The largest operation timestamp in the document, across every scope. */
|
|
610
610
|
latestTimestamp: string;
|
|
611
611
|
};
|
|
612
612
|
/**
|
|
@@ -2109,298 +2109,436 @@ declare class ReactorClient implements IReactorClient {
|
|
|
2109
2109
|
private removeAllIncomingRelationships;
|
|
2110
2110
|
}
|
|
2111
2111
|
//#endregion
|
|
2112
|
-
//#region src/
|
|
2112
|
+
//#region src/cache/collection-membership-cache.d.ts
|
|
2113
|
+
interface ICollectionMembershipCache {
|
|
2114
|
+
getCollectionsForDocuments(documentIds: string[]): Promise<Record<string, string[]>>;
|
|
2115
|
+
invalidate(documentId: string): void;
|
|
2116
|
+
}
|
|
2117
|
+
//#endregion
|
|
2118
|
+
//#region src/cache/document-meta-cache-types.d.ts
|
|
2113
2119
|
/**
|
|
2114
|
-
*
|
|
2120
|
+
* Cached document metadata from the "document" scope.
|
|
2121
|
+
*
|
|
2122
|
+
* This lightweight structure holds essential document information needed by
|
|
2123
|
+
* the job executor without fetching full scope state. It provides an explicit
|
|
2124
|
+
* cross-scope contract for accessing document scope metadata.
|
|
2115
2125
|
*/
|
|
2116
|
-
type
|
|
2117
|
-
/** The job that was executed */job: Job; /** Whether the job executed successfully */
|
|
2118
|
-
success: boolean; /** Error if the job failed */
|
|
2119
|
-
error?: Error; /** The operations generated from the actions (if successful) */
|
|
2120
|
-
operations?: Operation[];
|
|
2126
|
+
type CachedDocumentMeta = {
|
|
2121
2127
|
/**
|
|
2122
|
-
*
|
|
2123
|
-
*
|
|
2128
|
+
* The full PHDocumentState from document.state.document.
|
|
2129
|
+
* Contains version, hash, isDeleted, deletedAtUtcIso, etc.
|
|
2124
2130
|
*/
|
|
2125
|
-
|
|
2126
|
-
completedAt?: string; /** Duration of job execution in milliseconds */
|
|
2127
|
-
duration?: number; /** Any additional metadata from the execution */
|
|
2128
|
-
metadata?: Record<string, any>;
|
|
2129
|
-
};
|
|
2130
|
-
/**
|
|
2131
|
-
* Enforcement the reactor performs, each off by default.
|
|
2132
|
-
*
|
|
2133
|
-
* An evaluation made while replaying is part of the document's history, so two
|
|
2134
|
-
* reactors that share documents and disagree on these diverge. A flag is turned
|
|
2135
|
-
* on for a set of reactors that sync with each other, not for one node.
|
|
2136
|
-
*/
|
|
2137
|
-
type ReactorFeatureFlags = {
|
|
2131
|
+
state: PHDocumentState;
|
|
2138
2132
|
/**
|
|
2139
|
-
*
|
|
2140
|
-
* over the document stream, rather than reading the deleted flag from the
|
|
2141
|
-
* document meta cache. Deletion then takes effect from the deleting
|
|
2142
|
-
* operation's position rather than for the whole document.
|
|
2133
|
+
* The document type (from header), cached for convenience.
|
|
2143
2134
|
*/
|
|
2144
|
-
|
|
2145
|
-
};
|
|
2146
|
-
/**
|
|
2147
|
-
* Configuration options for the job executor
|
|
2148
|
-
*/
|
|
2149
|
-
type JobExecutorConfig = {
|
|
2150
|
-
/** Feature flags; anything unset is off. */featureFlags?: Partial<ReactorFeatureFlags>; /** Maximum number of conflicting operations to skip when reshuffling. */
|
|
2151
|
-
maxSkipThreshold?: number; /** Maximum number of concurrent jobs to execute */
|
|
2152
|
-
maxConcurrency?: number; /** Maximum time in milliseconds a job can run before being considered timed out */
|
|
2153
|
-
jobTimeoutMs?: number; /** Base delay in milliseconds for exponential backoff retries */
|
|
2154
|
-
retryBaseDelayMs?: number; /** Maximum delay in milliseconds for exponential backoff retries */
|
|
2155
|
-
retryMaxDelayMs?: number;
|
|
2156
|
-
/** Maximum elapsed milliseconds before yielding to the main thread between actions.
|
|
2157
|
-
* Keeps the UI responsive when processing large batches. */
|
|
2158
|
-
yieldDeadlineMs?: number;
|
|
2159
|
-
};
|
|
2160
|
-
/**
|
|
2161
|
-
* Event types for the job executor
|
|
2162
|
-
*/
|
|
2163
|
-
declare const JobExecutorEventTypes: {
|
|
2164
|
-
readonly JOB_STARTED: 20000;
|
|
2165
|
-
readonly JOB_COMPLETED: 20001;
|
|
2166
|
-
readonly JOB_FAILED: 20002;
|
|
2167
|
-
readonly EXECUTOR_STARTED: 20003;
|
|
2168
|
-
readonly EXECUTOR_STOPPED: 20004;
|
|
2169
|
-
};
|
|
2170
|
-
/**
|
|
2171
|
-
* Event data for job execution events
|
|
2172
|
-
*/
|
|
2173
|
-
type JobStartedEvent = {
|
|
2174
|
-
job: Job;
|
|
2175
|
-
startedAt: string;
|
|
2135
|
+
documentType: string;
|
|
2176
2136
|
/**
|
|
2177
|
-
*
|
|
2178
|
-
*
|
|
2179
|
-
* manager it is "in-process-<index>". Optional for backwards compatibility
|
|
2180
|
-
* with consumers built before the field was added.
|
|
2137
|
+
* The revision of the document scope when this metadata was captured.
|
|
2138
|
+
* Used for cache invalidation and consistency checks.
|
|
2181
2139
|
*/
|
|
2182
|
-
|
|
2183
|
-
};
|
|
2184
|
-
type JobCompletedEvent = {
|
|
2185
|
-
job: Job;
|
|
2186
|
-
result: JobResult; /** See {@link JobStartedEvent.workerId}. */
|
|
2187
|
-
workerId?: string;
|
|
2188
|
-
};
|
|
2189
|
-
type JobFailedEvent = {
|
|
2190
|
-
job: Job;
|
|
2191
|
-
error: string;
|
|
2192
|
-
willRetry: boolean;
|
|
2193
|
-
retryCount: number; /** See {@link JobStartedEvent.workerId}. */
|
|
2194
|
-
workerId?: string;
|
|
2195
|
-
};
|
|
2196
|
-
type ExecutorStartedEvent = {
|
|
2197
|
-
config: JobExecutorConfig;
|
|
2198
|
-
startedAt: string;
|
|
2199
|
-
};
|
|
2200
|
-
type ExecutorStoppedEvent = {
|
|
2201
|
-
stoppedAt: string;
|
|
2202
|
-
graceful: boolean;
|
|
2203
|
-
};
|
|
2204
|
-
/**
|
|
2205
|
-
* Status information for the job executor manager
|
|
2206
|
-
*/
|
|
2207
|
-
type ExecutorManagerStatus = {
|
|
2208
|
-
/** Whether the manager is currently running */isRunning: boolean; /** Number of executor instances managed */
|
|
2209
|
-
numExecutors: number; /** Number of jobs currently being processed */
|
|
2210
|
-
activeJobs: number; /** Total number of jobs processed since start */
|
|
2211
|
-
totalJobsProcessed: number;
|
|
2212
|
-
};
|
|
2213
|
-
//#endregion
|
|
2214
|
-
//#region src/executor/worker/protocol.d.ts
|
|
2215
|
-
/**
|
|
2216
|
-
* A JSON-clonable value safe to send across the worker IPC boundary.
|
|
2217
|
-
*
|
|
2218
|
-
* The shape mirrors the structured-clone subset used by the parent's
|
|
2219
|
-
* sanitizer: primitives, arrays, plain objects, plus the explicit
|
|
2220
|
-
* {@link ErrorInfo} shape for marshalled Errors.
|
|
2221
|
-
*
|
|
2222
|
-
* @see Wire Protocol Reference wiki page
|
|
2223
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2224
|
-
*/
|
|
2225
|
-
type SanitizedArg = null | boolean | number | string | ErrorInfo | SanitizedArg[] | {
|
|
2226
|
-
[key: string]: SanitizedArg;
|
|
2227
|
-
};
|
|
2228
|
-
/**
|
|
2229
|
-
* Structured representation of an Error for IPC transport.
|
|
2230
|
-
*
|
|
2231
|
-
* Class instances cannot be structured-cloned across worker boundaries,
|
|
2232
|
-
* so Errors are flattened into this shape on the worker side and
|
|
2233
|
-
* reconstructed on the parent side.
|
|
2234
|
-
*
|
|
2235
|
-
* @see Wire Protocol Reference wiki page
|
|
2236
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2237
|
-
*/
|
|
2238
|
-
type ErrorInfo = {
|
|
2239
|
-
name: string;
|
|
2240
|
-
message: string;
|
|
2241
|
-
stack?: string;
|
|
2242
|
-
cause?: ErrorInfo;
|
|
2243
|
-
};
|
|
2244
|
-
/**
|
|
2245
|
-
* Reference to a module that the worker should `import()` at runtime,
|
|
2246
|
-
* along with the named export to pluck out as the factory.
|
|
2247
|
-
*
|
|
2248
|
-
* Exactly one of `packageName` or `filePath` is provided.
|
|
2249
|
-
*
|
|
2250
|
-
* @see Wire Protocol Reference wiki page
|
|
2251
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2252
|
-
*/
|
|
2253
|
-
type ModuleRef = {
|
|
2254
|
-
/** Bare-specifier package name (resolved by the worker's module loader). */packageName: string; /** Named export within the module to invoke as the factory. */
|
|
2255
|
-
exportName: string;
|
|
2256
|
-
} | {
|
|
2257
|
-
/** Absolute or worker-resolvable file path to import. */filePath: string; /** Named export within the module to invoke as the factory. */
|
|
2258
|
-
exportName: string;
|
|
2259
|
-
};
|
|
2260
|
-
/**
|
|
2261
|
-
* Factory specification shared by the signature verifier and document
|
|
2262
|
-
* model spec channels. The worker imports `module.exportName` and invokes
|
|
2263
|
-
* it with `initArgs` to obtain the actual instance.
|
|
2264
|
-
*
|
|
2265
|
-
* `initArgs` must be JSON-clonable.
|
|
2266
|
-
*
|
|
2267
|
-
* @see Wire Protocol Reference wiki page
|
|
2268
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2269
|
-
*/
|
|
2270
|
-
type FactorySpec = {
|
|
2271
|
-
module: ModuleRef;
|
|
2272
|
-
initArgs?: SanitizedArg;
|
|
2140
|
+
documentScopeRevision: number;
|
|
2273
2141
|
};
|
|
2274
2142
|
/**
|
|
2275
|
-
*
|
|
2276
|
-
*
|
|
2277
|
-
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2278
|
-
* sites read intent-fully.
|
|
2279
|
-
*
|
|
2280
|
-
* @see Wire Protocol Reference wiki page
|
|
2281
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2282
|
-
*/
|
|
2283
|
-
type SignatureVerifierSpec = FactorySpec;
|
|
2284
|
-
/**
|
|
2285
|
-
* Factory spec for a document model module the worker should instantiate.
|
|
2286
|
-
*
|
|
2287
|
-
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2288
|
-
* sites read intent-fully.
|
|
2289
|
-
*
|
|
2290
|
-
* @see Wire Protocol Reference wiki page
|
|
2291
|
-
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2292
|
-
*/
|
|
2293
|
-
type DocumentModelSpec = FactorySpec;
|
|
2294
|
-
/**
|
|
2295
|
-
* One entry in the document model manifest the worker materializes on
|
|
2296
|
-
* startup (or extends lazily via `load-model`).
|
|
2143
|
+
* Interface for the document metadata cache.
|
|
2297
2144
|
*
|
|
2298
|
-
*
|
|
2299
|
-
*
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
/** Document type identifier (e.g. "ph/account"). */documentType: string; /** Document model version this entry registers. */
|
|
2303
|
-
version: string; /** Factory spec the worker imports and invokes to obtain the model. */
|
|
2304
|
-
spec: DocumentModelSpec;
|
|
2305
|
-
};
|
|
2306
|
-
/**
|
|
2307
|
-
* JSON-clonable Postgres connection info passed to the worker so it can
|
|
2308
|
-
* open its own pool. Storage-specific wiring may extend this shape in
|
|
2309
|
-
* later phases.
|
|
2145
|
+
* This cache provides an explicit cross-scope contract for accessing document
|
|
2146
|
+
* scope metadata. It solves the problem where job execution in one scope (e.g.,
|
|
2147
|
+
* "global") needs access to document scope state (version, isDeleted, etc.)
|
|
2148
|
+
* which may be stale in scope-specific caches or keyframes.
|
|
2310
2149
|
*
|
|
2311
|
-
*
|
|
2312
|
-
*
|
|
2150
|
+
* The cache supports:
|
|
2151
|
+
* - Latest metadata retrieval with LRU caching
|
|
2152
|
+
* - Historical metadata reconstruction for reshuffling scenarios
|
|
2153
|
+
* - Eager updates after document scope operations
|
|
2313
2154
|
*/
|
|
2314
|
-
|
|
2315
|
-
host: string;
|
|
2316
|
-
port: number;
|
|
2317
|
-
database: string;
|
|
2318
|
-
user: string;
|
|
2319
|
-
password: string;
|
|
2320
|
-
ssl?: boolean;
|
|
2321
|
-
applicationName?: string;
|
|
2322
|
-
poolSize?: number;
|
|
2155
|
+
interface IDocumentMetaCache {
|
|
2323
2156
|
/**
|
|
2324
|
-
*
|
|
2325
|
-
*
|
|
2326
|
-
*
|
|
2157
|
+
* Retrieves the LATEST document metadata from cache or rebuilds from operations.
|
|
2158
|
+
*
|
|
2159
|
+
* On cache miss, fetches all document scope operations and reconstructs the
|
|
2160
|
+
* current PHDocumentState by applying UPGRADE_DOCUMENT and DELETE_DOCUMENT
|
|
2161
|
+
* operations.
|
|
2162
|
+
*
|
|
2163
|
+
* @param documentId - The document identifier
|
|
2164
|
+
* @param branch - Branch name
|
|
2165
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2166
|
+
* @returns The cached or rebuilt document metadata
|
|
2167
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2168
|
+
* @throws {Error} If document not found (no CREATE_DOCUMENT operation)
|
|
2327
2169
|
*/
|
|
2328
|
-
|
|
2170
|
+
getDocumentMeta(documentId: string, branch: string, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
2329
2171
|
/**
|
|
2330
|
-
*
|
|
2331
|
-
*
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2172
|
+
* Rebuilds document metadata at a SPECIFIC revision (always rebuilds, no caching).
|
|
2173
|
+
*
|
|
2174
|
+
* Used during reshuffling when operations need to be inserted at a previous
|
|
2175
|
+
* revision and we need the document scope state as of that point in time.
|
|
2176
|
+
*
|
|
2177
|
+
* @param documentId - The document identifier
|
|
2178
|
+
* @param branch - Branch name
|
|
2179
|
+
* @param targetRevision - The document scope revision to reconstruct up to
|
|
2180
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2181
|
+
* @returns Document metadata as of the target revision
|
|
2182
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2183
|
+
* @throws {Error} If document not found
|
|
2184
|
+
*/
|
|
2185
|
+
rebuildAtRevision(documentId: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
2186
|
+
/**
|
|
2187
|
+
* Eagerly updates cached metadata after document scope operations.
|
|
2188
|
+
*
|
|
2189
|
+
* Called by the job executor after CREATE_DOCUMENT, UPGRADE_DOCUMENT, or
|
|
2190
|
+
* DELETE_DOCUMENT operations to keep the cache current.
|
|
2191
|
+
*
|
|
2192
|
+
* @param documentId - The document identifier
|
|
2193
|
+
* @param branch - Branch name
|
|
2194
|
+
* @param meta - The new metadata to cache
|
|
2195
|
+
*/
|
|
2196
|
+
putDocumentMeta(documentId: string, branch: string, meta: CachedDocumentMeta): void;
|
|
2197
|
+
/**
|
|
2198
|
+
* Invalidates cached document metadata.
|
|
2199
|
+
*
|
|
2200
|
+
* Call before reshuffling operations that modify the document scope, or
|
|
2201
|
+
* when document state may have changed externally.
|
|
2202
|
+
*
|
|
2203
|
+
* @param documentId - The document identifier
|
|
2204
|
+
* @param branch - Optional branch to narrow invalidation (if omitted, all branches)
|
|
2205
|
+
* @returns Number of entries invalidated
|
|
2206
|
+
*/
|
|
2207
|
+
invalidate(documentId: string, branch?: string): number;
|
|
2208
|
+
/**
|
|
2209
|
+
* Clears all cached document metadata.
|
|
2210
|
+
*/
|
|
2211
|
+
clear(): void;
|
|
2212
|
+
/**
|
|
2213
|
+
* Performs startup initialization.
|
|
2214
|
+
*/
|
|
2215
|
+
startup(): Promise<void>;
|
|
2216
|
+
/**
|
|
2217
|
+
* Performs graceful shutdown.
|
|
2218
|
+
*/
|
|
2219
|
+
shutdown(): Promise<void>;
|
|
2220
|
+
}
|
|
2221
|
+
//#endregion
|
|
2222
|
+
//#region src/storage/kysely/types.d.ts
|
|
2223
|
+
interface OperationTable {
|
|
2224
|
+
id: Generated<number>;
|
|
2225
|
+
jobId: string;
|
|
2226
|
+
opId: string;
|
|
2227
|
+
prevOpId: string;
|
|
2228
|
+
writeTimestampUtcMs: Generated<Date>;
|
|
2229
|
+
documentId: string;
|
|
2230
|
+
documentType: string;
|
|
2231
|
+
scope: string;
|
|
2232
|
+
branch: string;
|
|
2233
|
+
timestampUtcMs: Date;
|
|
2234
|
+
index: number;
|
|
2235
|
+
action: unknown;
|
|
2236
|
+
skip: number;
|
|
2237
|
+
error?: string | null;
|
|
2238
|
+
deniedReason?: string | null;
|
|
2239
|
+
hash: string;
|
|
2240
|
+
}
|
|
2241
|
+
interface KeyframeTable {
|
|
2242
|
+
id: Generated<number>;
|
|
2243
|
+
documentId: string;
|
|
2244
|
+
documentType: string;
|
|
2245
|
+
scope: string;
|
|
2246
|
+
branch: string;
|
|
2247
|
+
revision: number;
|
|
2248
|
+
document: unknown;
|
|
2249
|
+
createdAt: Generated<Date>;
|
|
2250
|
+
}
|
|
2251
|
+
interface DocumentCollectionTable {
|
|
2252
|
+
documentId: string;
|
|
2253
|
+
collectionId: string;
|
|
2254
|
+
joinedOrdinal: bigint;
|
|
2255
|
+
leftOrdinal: bigint | null;
|
|
2256
|
+
}
|
|
2257
|
+
interface OperationIndexOperationTable {
|
|
2258
|
+
ordinal: Generated<number>;
|
|
2259
|
+
opId: string;
|
|
2260
|
+
documentId: string;
|
|
2261
|
+
documentType: string;
|
|
2262
|
+
scope: string;
|
|
2263
|
+
branch: string;
|
|
2264
|
+
timestampUtcMs: string;
|
|
2265
|
+
writeTimestampUtcMs: Generated<Date>;
|
|
2266
|
+
index: number;
|
|
2267
|
+
skip: number;
|
|
2268
|
+
hash: string;
|
|
2269
|
+
action: unknown;
|
|
2270
|
+
deniedReason?: string | null;
|
|
2271
|
+
sourceRemote: Generated<string>;
|
|
2272
|
+
}
|
|
2273
|
+
interface SyncRemoteTable {
|
|
2274
|
+
name: string;
|
|
2275
|
+
collection_id: string;
|
|
2276
|
+
channel_type: string;
|
|
2277
|
+
channel_id: string;
|
|
2278
|
+
remote_name: string;
|
|
2279
|
+
channel_parameters: unknown;
|
|
2280
|
+
filter_document_ids: unknown;
|
|
2281
|
+
filter_scopes: unknown;
|
|
2282
|
+
filter_branch: string;
|
|
2283
|
+
push_state: string;
|
|
2284
|
+
push_last_success_utc_ms: string | null;
|
|
2285
|
+
push_last_failure_utc_ms: string | null;
|
|
2286
|
+
push_failure_count: number;
|
|
2287
|
+
pull_state: string;
|
|
2288
|
+
pull_last_success_utc_ms: string | null;
|
|
2289
|
+
pull_last_failure_utc_ms: string | null;
|
|
2290
|
+
pull_failure_count: number;
|
|
2291
|
+
created_at: Generated<Date>;
|
|
2292
|
+
updated_at: Generated<Date>;
|
|
2293
|
+
}
|
|
2294
|
+
interface SyncCursorTable {
|
|
2295
|
+
remote_name: string;
|
|
2296
|
+
cursor_type: string;
|
|
2297
|
+
cursor_ordinal: bigint;
|
|
2298
|
+
last_synced_at_utc_ms: string | null;
|
|
2299
|
+
updated_at: Generated<Date>;
|
|
2300
|
+
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Kysely table definition for the `sync_dead_letters` table.
|
|
2303
|
+
*/
|
|
2304
|
+
interface SyncDeadLetterTable {
|
|
2305
|
+
ordinal: Generated<number>;
|
|
2306
|
+
id: string;
|
|
2307
|
+
job_id: string;
|
|
2308
|
+
job_dependencies: unknown;
|
|
2309
|
+
remote_name: string;
|
|
2310
|
+
document_id: string;
|
|
2311
|
+
scopes: unknown;
|
|
2312
|
+
branch: string;
|
|
2313
|
+
operations: unknown;
|
|
2314
|
+
error_source: string;
|
|
2315
|
+
error_message: string;
|
|
2316
|
+
created_at: Generated<Date>;
|
|
2317
|
+
}
|
|
2318
|
+
interface Database$1 {
|
|
2319
|
+
Operation: OperationTable;
|
|
2320
|
+
Keyframe: KeyframeTable;
|
|
2321
|
+
document_collections: DocumentCollectionTable;
|
|
2322
|
+
operation_index_operations: OperationIndexOperationTable;
|
|
2323
|
+
sync_remotes: SyncRemoteTable;
|
|
2324
|
+
sync_cursors: SyncCursorTable;
|
|
2325
|
+
sync_dead_letters: SyncDeadLetterTable;
|
|
2326
|
+
}
|
|
2327
|
+
interface DocumentTable {
|
|
2328
|
+
id: string;
|
|
2329
|
+
createdAt: Generated<Date>;
|
|
2330
|
+
updatedAt: Generated<Date>;
|
|
2331
|
+
}
|
|
2332
|
+
interface DocumentRelationshipTable {
|
|
2333
|
+
id: Generated<string>;
|
|
2334
|
+
sourceId: string;
|
|
2335
|
+
targetId: string;
|
|
2336
|
+
relationshipType: string;
|
|
2337
|
+
metadata: unknown;
|
|
2338
|
+
createdAt: Generated<Date>;
|
|
2339
|
+
updatedAt: Generated<Date>;
|
|
2340
|
+
}
|
|
2341
|
+
interface IndexerStateTable {
|
|
2342
|
+
id: Generated<number>;
|
|
2343
|
+
lastOperationId: number;
|
|
2344
|
+
lastOperationTimestamp: Generated<Date>;
|
|
2345
|
+
}
|
|
2346
|
+
interface DocumentIndexerDatabase {
|
|
2347
|
+
Document: DocumentTable;
|
|
2348
|
+
DocumentRelationship: DocumentRelationshipTable;
|
|
2349
|
+
IndexerState: IndexerStateTable;
|
|
2350
|
+
}
|
|
2351
|
+
//#endregion
|
|
2352
|
+
//#region src/executor/worker/protocol.d.ts
|
|
2353
|
+
/**
|
|
2354
|
+
* A JSON-clonable value safe to send across the worker IPC boundary.
|
|
2355
|
+
*
|
|
2356
|
+
* The shape mirrors the structured-clone subset used by the parent's
|
|
2357
|
+
* sanitizer: primitives, arrays, plain objects, plus the explicit
|
|
2358
|
+
* {@link ErrorInfo} shape for marshalled Errors.
|
|
2340
2359
|
*
|
|
2341
2360
|
* @see Wire Protocol Reference wiki page
|
|
2342
2361
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2343
2362
|
*/
|
|
2344
|
-
type
|
|
2345
|
-
|
|
2346
|
-
numWorkers: number; /** Worker isolation mode. */
|
|
2347
|
-
workerType: "thread" | "process"; /** Optional heartbeat interval in milliseconds. */
|
|
2348
|
-
heartbeatMs?: number; /** Optional per-worker Postgres pool size override. */
|
|
2349
|
-
workerPgPoolSize?: number;
|
|
2363
|
+
type SanitizedArg = null | boolean | number | string | ErrorInfo | SanitizedArg[] | {
|
|
2364
|
+
[key: string]: SanitizedArg;
|
|
2350
2365
|
};
|
|
2351
2366
|
/**
|
|
2352
|
-
*
|
|
2367
|
+
* Structured representation of an Error for IPC transport.
|
|
2353
2368
|
*
|
|
2354
|
-
*
|
|
2355
|
-
*
|
|
2369
|
+
* Class instances cannot be structured-cloned across worker boundaries,
|
|
2370
|
+
* so Errors are flattened into this shape on the worker side and
|
|
2371
|
+
* reconstructed on the parent side.
|
|
2356
2372
|
*
|
|
2357
2373
|
* @see Wire Protocol Reference wiki page
|
|
2358
2374
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2359
2375
|
*/
|
|
2360
|
-
type
|
|
2361
|
-
|
|
2362
|
-
|
|
2376
|
+
type ErrorInfo = {
|
|
2377
|
+
name: string;
|
|
2378
|
+
message: string;
|
|
2379
|
+
stack?: string;
|
|
2380
|
+
cause?: ErrorInfo;
|
|
2363
2381
|
};
|
|
2364
2382
|
/**
|
|
2365
|
-
*
|
|
2366
|
-
*
|
|
2383
|
+
* Reference to a module that the worker should `import()` at runtime,
|
|
2384
|
+
* along with the named export to pluck out as the factory.
|
|
2385
|
+
*
|
|
2386
|
+
* Exactly one of `packageName` or `filePath` is provided.
|
|
2367
2387
|
*
|
|
2368
2388
|
* @see Wire Protocol Reference wiki page
|
|
2369
2389
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2370
2390
|
*/
|
|
2371
|
-
type
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
signatureVerifier?: SignatureVerifierSpec;
|
|
2378
|
-
models: ModelManifestEntry[]; /** Omitted = the worker builds its executor with the built-in defaults. */
|
|
2379
|
-
executorConfig?: JobExecutorConfig;
|
|
2391
|
+
type ModuleRef = {
|
|
2392
|
+
/** Bare-specifier package name (resolved by the worker's module loader). */packageName: string; /** Named export within the module to invoke as the factory. */
|
|
2393
|
+
exportName: string;
|
|
2394
|
+
} | {
|
|
2395
|
+
/** Absolute or worker-resolvable file path to import. */filePath: string; /** Named export within the module to invoke as the factory. */
|
|
2396
|
+
exportName: string;
|
|
2380
2397
|
};
|
|
2381
2398
|
/**
|
|
2382
|
-
*
|
|
2399
|
+
* Factory specification shared by the signature verifier and document
|
|
2400
|
+
* model spec channels. The worker imports `module.exportName` and invokes
|
|
2401
|
+
* it with `initArgs` to obtain the actual instance.
|
|
2402
|
+
*
|
|
2403
|
+
* `initArgs` must be JSON-clonable.
|
|
2383
2404
|
*
|
|
2384
2405
|
* @see Wire Protocol Reference wiki page
|
|
2385
2406
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2386
2407
|
*/
|
|
2387
|
-
type
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
job: Job;
|
|
2408
|
+
type FactorySpec = {
|
|
2409
|
+
module: ModuleRef;
|
|
2410
|
+
initArgs?: SanitizedArg;
|
|
2391
2411
|
};
|
|
2392
2412
|
/**
|
|
2393
|
-
*
|
|
2413
|
+
* Factory spec for the signature verifier the worker should instantiate.
|
|
2414
|
+
*
|
|
2415
|
+
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2416
|
+
* sites read intent-fully.
|
|
2394
2417
|
*
|
|
2395
2418
|
* @see Wire Protocol Reference wiki page
|
|
2396
2419
|
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2397
2420
|
*/
|
|
2398
|
-
type
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2421
|
+
type SignatureVerifierSpec = FactorySpec;
|
|
2422
|
+
/**
|
|
2423
|
+
* Factory spec for a document model module the worker should instantiate.
|
|
2424
|
+
*
|
|
2425
|
+
* Structurally identical to {@link FactorySpec}; the alias exists so call
|
|
2426
|
+
* sites read intent-fully.
|
|
2427
|
+
*
|
|
2428
|
+
* @see Wire Protocol Reference wiki page
|
|
2429
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2430
|
+
*/
|
|
2431
|
+
type DocumentModelSpec = FactorySpec;
|
|
2432
|
+
/**
|
|
2433
|
+
* One entry in the document model manifest the worker materializes on
|
|
2434
|
+
* startup (or extends lazily via `load-model`).
|
|
2435
|
+
*
|
|
2436
|
+
* @see Wire Protocol Reference wiki page
|
|
2437
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2438
|
+
*/
|
|
2439
|
+
type ModelManifestEntry = {
|
|
2440
|
+
/** Document type identifier (e.g. "ph/account"). */documentType: string; /** Document model version this entry registers. */
|
|
2441
|
+
version: string; /** Factory spec the worker imports and invokes to obtain the model. */
|
|
2442
|
+
spec: DocumentModelSpec;
|
|
2443
|
+
};
|
|
2444
|
+
/**
|
|
2445
|
+
* JSON-clonable Postgres connection info passed to the worker so it can
|
|
2446
|
+
* open its own pool. Storage-specific wiring may extend this shape in
|
|
2447
|
+
* later phases.
|
|
2448
|
+
*
|
|
2449
|
+
* @see Wire Protocol Reference wiki page
|
|
2450
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2451
|
+
*/
|
|
2452
|
+
type DbConfig = {
|
|
2453
|
+
host: string;
|
|
2454
|
+
port: number;
|
|
2455
|
+
database: string;
|
|
2456
|
+
user: string;
|
|
2457
|
+
password: string;
|
|
2458
|
+
ssl?: boolean;
|
|
2459
|
+
applicationName?: string;
|
|
2460
|
+
poolSize?: number;
|
|
2461
|
+
/**
|
|
2462
|
+
* Maximum time (ms) a caller will wait to acquire a connection from the
|
|
2463
|
+
* pool before pg.Pool throws. When omitted, pg defaults to 0 (unlimited
|
|
2464
|
+
* wait), which hides acquire-starvation as silent latency.
|
|
2465
|
+
*/
|
|
2466
|
+
connectionTimeoutMillis?: number;
|
|
2467
|
+
/**
|
|
2468
|
+
* How long (ms) an idle connection stays open before pg closes it. When
|
|
2469
|
+
* omitted, pg defaults to 10000.
|
|
2470
|
+
*/
|
|
2471
|
+
idleTimeoutMillis?: number;
|
|
2472
|
+
};
|
|
2473
|
+
/**
|
|
2474
|
+
* Configuration for the executor worker pool.
|
|
2475
|
+
*
|
|
2476
|
+
* Mirrors the `workerPool` sub-config on {@link JobExecutorConfig};
|
|
2477
|
+
* a later card wires this into the executor config.
|
|
2478
|
+
*
|
|
2479
|
+
* @see Wire Protocol Reference wiki page
|
|
2480
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2481
|
+
*/
|
|
2482
|
+
type WorkerPoolConfig = {
|
|
2483
|
+
/** Whether the worker pool is active; when false the executor runs in-process. */enabled: boolean; /** Number of worker instances to spawn. */
|
|
2484
|
+
numWorkers: number; /** Worker isolation mode. */
|
|
2485
|
+
workerType: "thread" | "process"; /** Optional heartbeat interval in milliseconds. */
|
|
2486
|
+
heartbeatMs?: number; /** Optional per-worker Postgres pool size override. */
|
|
2487
|
+
workerPgPoolSize?: number;
|
|
2488
|
+
};
|
|
2489
|
+
/**
|
|
2490
|
+
* Payload the worker reports back when a job's write phase is complete.
|
|
2491
|
+
*
|
|
2492
|
+
* Parent fills `collectionMemberships` at emission time, so it is
|
|
2493
|
+
* intentionally absent from the worker -> parent message.
|
|
2494
|
+
*
|
|
2495
|
+
* @see Wire Protocol Reference wiki page
|
|
2496
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2497
|
+
*/
|
|
2498
|
+
type JobWriteReadyPayload = {
|
|
2499
|
+
operations: OperationWithContext$1[];
|
|
2500
|
+
jobMeta: JobMeta;
|
|
2501
|
+
};
|
|
2502
|
+
/**
|
|
2503
|
+
* Initializes a freshly spawned worker with the configuration and
|
|
2504
|
+
* factories it needs to start executing jobs.
|
|
2505
|
+
*
|
|
2506
|
+
* @see Wire Protocol Reference wiki page
|
|
2507
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2508
|
+
*/
|
|
2509
|
+
type InitMessage = {
|
|
2510
|
+
type: "init";
|
|
2511
|
+
correlationId: string;
|
|
2512
|
+
workerId: string;
|
|
2513
|
+
poolConfig: WorkerPoolConfig;
|
|
2514
|
+
db: DbConfig; /** Omitted = the worker performs no executor-side signature verification. */
|
|
2515
|
+
signatureVerifier?: SignatureVerifierSpec;
|
|
2516
|
+
models: ModelManifestEntry[]; /** Omitted = the worker builds its executor with the built-in defaults. */
|
|
2517
|
+
executorConfig?: JobExecutorConfig;
|
|
2518
|
+
};
|
|
2519
|
+
/**
|
|
2520
|
+
* Dispatches a job to the worker for execution.
|
|
2521
|
+
*
|
|
2522
|
+
* @see Wire Protocol Reference wiki page
|
|
2523
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2524
|
+
*/
|
|
2525
|
+
type ExecuteMessage = {
|
|
2526
|
+
type: "execute";
|
|
2527
|
+
correlationId: string;
|
|
2528
|
+
job: Job;
|
|
2529
|
+
};
|
|
2530
|
+
/**
|
|
2531
|
+
* Requests cancellation of an in-flight job.
|
|
2532
|
+
*
|
|
2533
|
+
* @see Wire Protocol Reference wiki page
|
|
2534
|
+
* (Powerhouse board wiki id: 64c03e51-1aa4-4fa9-93d8-daa45642484d)
|
|
2535
|
+
*/
|
|
2536
|
+
type AbortMessage = {
|
|
2537
|
+
type: "abort";
|
|
2538
|
+
correlationId: string; /** correlationId of the `execute` message being aborted. */
|
|
2539
|
+
targetCorrelationId: string;
|
|
2540
|
+
reason?: string;
|
|
2541
|
+
};
|
|
2404
2542
|
/**
|
|
2405
2543
|
* Asks the worker to drain in-flight work and exit.
|
|
2406
2544
|
*
|
|
@@ -2557,498 +2695,859 @@ type PoolAcquireSamplesMessage = {
|
|
|
2557
2695
|
*/
|
|
2558
2696
|
type WorkerMessage = ReadyMessage | ResultMessage | ModelLoadedMessage | ModelLoadFailedMessage | LogMessage | HeartbeatMessage | MetricsMessage | PoolAcquireSamplesMessage;
|
|
2559
2697
|
//#endregion
|
|
2560
|
-
//#region src/
|
|
2698
|
+
//#region src/core/model-sources.d.ts
|
|
2699
|
+
/** An importable file holding one or more document-model exports. */
|
|
2700
|
+
type FileModelSource = {
|
|
2701
|
+
filePath: string;
|
|
2702
|
+
exportName?: string;
|
|
2703
|
+
};
|
|
2704
|
+
/** An importable package specifier holding one or more document-model exports. */
|
|
2705
|
+
type PackageModelSource = {
|
|
2706
|
+
packageName: string;
|
|
2707
|
+
subpath?: string;
|
|
2708
|
+
exportName?: string;
|
|
2709
|
+
};
|
|
2561
2710
|
/**
|
|
2562
|
-
*
|
|
2711
|
+
* A source of document models: a live module, an importable file, or an
|
|
2712
|
+
* importable package. File and package sources can cross a worker-thread
|
|
2713
|
+
* boundary (workers re-import them); a live module cannot.
|
|
2563
2714
|
*/
|
|
2564
|
-
type
|
|
2565
|
-
|
|
2566
|
-
|
|
2715
|
+
type DocumentModelSource = DocumentModelModule<any> | FileModelSource | PackageModelSource;
|
|
2716
|
+
//#endregion
|
|
2717
|
+
//#region src/registry/interfaces.d.ts
|
|
2718
|
+
type RegistrationResult<T> = {
|
|
2719
|
+
status: "success";
|
|
2720
|
+
item: T;
|
|
2721
|
+
} | {
|
|
2722
|
+
status: "error";
|
|
2723
|
+
item: T;
|
|
2724
|
+
error: Error;
|
|
2567
2725
|
};
|
|
2568
2726
|
/**
|
|
2569
|
-
*
|
|
2727
|
+
* Loader that asynchronously resolves a document type to a
|
|
2728
|
+
* {@link DocumentModelSource}. Used by the queue to gate CREATE_DOCUMENT
|
|
2729
|
+
* jobs until the required model is available in the registry.
|
|
2570
2730
|
*
|
|
2571
|
-
*
|
|
2572
|
-
* the
|
|
2573
|
-
*
|
|
2574
|
-
*
|
|
2731
|
+
* Return an importable source ({ filePath } or { packageName }) whenever
|
|
2732
|
+
* possible: the resolver registers the resolved models on the host registry
|
|
2733
|
+
* and broadcasts importable sources to executor workers. A live
|
|
2734
|
+
* DocumentModelModule is also valid but host-only — it cannot cross a
|
|
2735
|
+
* worker-thread boundary, so worker pools will not receive it.
|
|
2575
2736
|
*/
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
};
|
|
2737
|
+
interface IDocumentModelLoader {
|
|
2738
|
+
load(documentType: string): Promise<DocumentModelSource>;
|
|
2739
|
+
}
|
|
2580
2740
|
/**
|
|
2581
|
-
*
|
|
2582
|
-
*
|
|
2583
|
-
*
|
|
2584
|
-
* test fake) and expose a transport-agnostic surface that the worker-pool
|
|
2585
|
-
* manager uses to dispatch jobs. The handle owns one worker's lifecycle
|
|
2586
|
-
* (`start` -> `execute`* -> `shutdown`) and bounds its in-flight map to a
|
|
2587
|
-
* single entry; `SimpleJobExecutor` is single-threaded inside the worker, so
|
|
2588
|
-
* concurrent dispatches would race its caches.
|
|
2741
|
+
* Registry for managing document model modules.
|
|
2742
|
+
* Provides centralized access to document models' reducers, utils, and specifications.
|
|
2743
|
+
* Supports version-aware module storage and upgrade manifest management.
|
|
2589
2744
|
*/
|
|
2590
|
-
interface
|
|
2591
|
-
/** Stable identifier of the worker (mirrors `InitMessage.workerId`). */
|
|
2592
|
-
readonly workerId: string;
|
|
2593
|
-
/** Zero-based index within the pool, used for sticky routing. */
|
|
2594
|
-
readonly index: number;
|
|
2745
|
+
interface IDocumentModelRegistry {
|
|
2595
2746
|
/**
|
|
2596
|
-
*
|
|
2597
|
-
*
|
|
2747
|
+
* Register multiple modules at once.
|
|
2748
|
+
* Modules without a version field default to version 1.
|
|
2749
|
+
* Invalid or duplicate modules are skipped without breaking registration of the remaining modules.
|
|
2750
|
+
*
|
|
2751
|
+
* @param modules Document model modules to register
|
|
2752
|
+
* @returns Array of results, one per module, indicating success or failure
|
|
2598
2753
|
*/
|
|
2599
|
-
|
|
2754
|
+
registerModules(...modules: DocumentModelModule<any>[]): RegistrationResult<DocumentModelModule<any>>[];
|
|
2600
2755
|
/**
|
|
2601
|
-
*
|
|
2602
|
-
*
|
|
2603
|
-
*
|
|
2604
|
-
*
|
|
2605
|
-
* result.
|
|
2756
|
+
* Unregister all versions of the specified document types.
|
|
2757
|
+
*
|
|
2758
|
+
* @param documentTypes The document types to unregister
|
|
2759
|
+
* @returns true if all modules were unregistered, false if any were not found
|
|
2606
2760
|
*/
|
|
2607
|
-
|
|
2761
|
+
unregisterModules(...documentTypes: string[]): boolean;
|
|
2608
2762
|
/**
|
|
2609
|
-
*
|
|
2610
|
-
*
|
|
2611
|
-
*
|
|
2763
|
+
* Get a specific document model module by document type and optional version.
|
|
2764
|
+
* If version is not specified, returns the latest version.
|
|
2765
|
+
*
|
|
2766
|
+
* @param documentType The document type identifier
|
|
2767
|
+
* @param version Optional version number to retrieve
|
|
2768
|
+
* @returns The document model module
|
|
2769
|
+
* @throws ModuleNotFoundError if the document type or version is not registered
|
|
2612
2770
|
*/
|
|
2613
|
-
|
|
2771
|
+
getModule(documentType: string, version?: number): DocumentModelModule<any>;
|
|
2614
2772
|
/**
|
|
2615
|
-
*
|
|
2616
|
-
*
|
|
2617
|
-
*
|
|
2773
|
+
* Get all registered document model modules.
|
|
2774
|
+
*
|
|
2775
|
+
* @returns Array of all registered modules
|
|
2618
2776
|
*/
|
|
2619
|
-
|
|
2777
|
+
getAllModules(): DocumentModelModule<any>[];
|
|
2620
2778
|
/**
|
|
2621
|
-
*
|
|
2622
|
-
* when the worker replies with `model-loaded`; rejects when it replies
|
|
2623
|
-
* with `model-load-failed` or the worker exits before answering.
|
|
2779
|
+
* Clear all registered modules and upgrade manifests.
|
|
2624
2780
|
*/
|
|
2625
|
-
|
|
2626
|
-
/** True when no job is currently in flight. */
|
|
2627
|
-
isIdle(): boolean;
|
|
2628
|
-
/** Snapshot of the in-flight slot, or null when idle. */
|
|
2629
|
-
getInFlight(): WorkerInFlightSnapshot | null;
|
|
2630
|
-
}
|
|
2631
|
-
/**
|
|
2632
|
-
* Simple interface for executing a job.
|
|
2633
|
-
* A JobExecutor simply takes a job and executes it - nothing more.
|
|
2634
|
-
*/
|
|
2635
|
-
interface IJobExecutor {
|
|
2781
|
+
clear(): void;
|
|
2636
2782
|
/**
|
|
2637
|
-
*
|
|
2638
|
-
*
|
|
2639
|
-
* @
|
|
2783
|
+
* Get all supported versions for a document type, sorted in ascending order.
|
|
2784
|
+
*
|
|
2785
|
+
* @param documentType The document type identifier
|
|
2786
|
+
* @returns Array of version numbers sorted ascending
|
|
2787
|
+
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
2640
2788
|
*/
|
|
2641
|
-
|
|
2642
|
-
}
|
|
2643
|
-
/**
|
|
2644
|
-
* Interface for managing multiple job executors.
|
|
2645
|
-
* Listens for 'jobAvailable' events from the event bus, pulls jobs from the queue,
|
|
2646
|
-
* and coordinates the distribution of jobs across multiple executor instances.
|
|
2647
|
-
*/
|
|
2648
|
-
interface IJobExecutorManager {
|
|
2789
|
+
getSupportedVersions(documentType: string): number[];
|
|
2649
2790
|
/**
|
|
2650
|
-
*
|
|
2651
|
-
* Begins listening for 'jobAvailable' events and dispatching to executors.
|
|
2791
|
+
* Get the latest (highest) version number for a document type.
|
|
2652
2792
|
*
|
|
2653
|
-
* @param
|
|
2654
|
-
* @returns
|
|
2793
|
+
* @param documentType The document type identifier
|
|
2794
|
+
* @returns The highest version number registered for this document type
|
|
2795
|
+
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
2655
2796
|
*/
|
|
2656
|
-
|
|
2797
|
+
getLatestVersion(documentType: string): number;
|
|
2657
2798
|
/**
|
|
2658
|
-
*
|
|
2799
|
+
* Register upgrade manifests that define upgrade paths between versions.
|
|
2800
|
+
* Invalid or duplicate manifests are skipped without breaking registration of the remaining manifests.
|
|
2659
2801
|
*
|
|
2660
|
-
* @param
|
|
2661
|
-
* @returns
|
|
2802
|
+
* @param manifests Upgrade manifests to register
|
|
2803
|
+
* @returns Array of results, one per manifest, indicating success or failure
|
|
2662
2804
|
*/
|
|
2663
|
-
|
|
2805
|
+
registerUpgradeManifests(...manifests: UpgradeManifest<readonly number[]>[]): RegistrationResult<UpgradeManifest<readonly number[]>>[];
|
|
2664
2806
|
/**
|
|
2665
|
-
*
|
|
2807
|
+
* Unregister upgrade manifests for the specified document types.
|
|
2808
|
+
* @param documentTypes The document types whose upgrade manifests should be unregistered
|
|
2809
|
+
* @returns true if all modules were unregistered, false if any were not found
|
|
2810
|
+
**/
|
|
2811
|
+
unregisterUpgradeManifests(...documentTypes: string[]): boolean;
|
|
2812
|
+
/**
|
|
2813
|
+
* Get the upgrade manifest for a document type.
|
|
2666
2814
|
*
|
|
2667
|
-
* @
|
|
2815
|
+
* @param documentType The document type identifier
|
|
2816
|
+
* @returns The upgrade manifest
|
|
2817
|
+
* @throws ManifestNotFoundError if no manifest is registered for the document type
|
|
2668
2818
|
*/
|
|
2669
|
-
|
|
2819
|
+
getUpgradeManifest(documentType: string): UpgradeManifest<readonly number[]>;
|
|
2670
2820
|
/**
|
|
2671
|
-
*
|
|
2821
|
+
* Compute the upgrade path from one version to another.
|
|
2822
|
+
* Returns the sequence of upgrade transitions needed.
|
|
2672
2823
|
*
|
|
2673
|
-
* @
|
|
2824
|
+
* @param documentType The document type identifier
|
|
2825
|
+
* @param fromVersion The starting version
|
|
2826
|
+
* @param toVersion The target version
|
|
2827
|
+
* @returns Array of upgrade transitions in order
|
|
2828
|
+
* @throws DowngradeNotSupportedError if toVersion is less than fromVersion
|
|
2829
|
+
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2830
|
+
* @throws MissingUpgradeTransitionError if any transition in the path is missing
|
|
2674
2831
|
*/
|
|
2675
|
-
|
|
2832
|
+
computeUpgradePath(documentType: string, fromVersion: number, toVersion: number): UpgradeTransition[];
|
|
2833
|
+
/**
|
|
2834
|
+
* Get the upgrade reducer for a single-step version transition.
|
|
2835
|
+
*
|
|
2836
|
+
* @param documentType The document type identifier
|
|
2837
|
+
* @param fromVersion The starting version
|
|
2838
|
+
* @param toVersion The target version (must be fromVersion + 1)
|
|
2839
|
+
* @returns The upgrade reducer function
|
|
2840
|
+
* @throws InvalidUpgradeStepError if toVersion is not fromVersion + 1
|
|
2841
|
+
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
2842
|
+
* @throws MissingUpgradeTransitionError if the transition is not found
|
|
2843
|
+
*/
|
|
2844
|
+
getUpgradeReducer(documentType: string, fromVersion: number, toVersion: number): UpgradeReducer<any, any>;
|
|
2676
2845
|
}
|
|
2677
2846
|
//#endregion
|
|
2678
|
-
//#region src/
|
|
2847
|
+
//#region src/cache/buffer/ring-buffer.d.ts
|
|
2679
2848
|
/**
|
|
2680
|
-
*
|
|
2681
|
-
*
|
|
2849
|
+
* RingBuffer is a generic circular buffer implementation that stores a fixed number
|
|
2850
|
+
* of items. When the buffer is full, new items overwrite the oldest items.
|
|
2851
|
+
*
|
|
2852
|
+
* This implementation maintains O(1) time complexity for push operations and provides
|
|
2853
|
+
* items in chronological order (oldest to newest) via getAll().
|
|
2854
|
+
*
|
|
2855
|
+
* @template T - The type of items stored in the buffer
|
|
2682
2856
|
*/
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
registerJob(jobInfo: JobInfo): void;
|
|
2857
|
+
declare class RingBuffer<T> {
|
|
2858
|
+
private buffer;
|
|
2859
|
+
private head;
|
|
2860
|
+
private size;
|
|
2861
|
+
private capacity;
|
|
2862
|
+
constructor(capacity: number);
|
|
2690
2863
|
/**
|
|
2691
|
-
*
|
|
2864
|
+
* Adds an item to the buffer. If the buffer is full, overwrites the oldest item.
|
|
2692
2865
|
*
|
|
2693
|
-
* @param
|
|
2866
|
+
* @param item - The item to add
|
|
2694
2867
|
*/
|
|
2695
|
-
|
|
2868
|
+
push(item: T): void;
|
|
2696
2869
|
/**
|
|
2697
|
-
*
|
|
2870
|
+
* Returns all items in the buffer in chronological order (oldest to newest).
|
|
2698
2871
|
*
|
|
2699
|
-
* @
|
|
2700
|
-
* @param error - Error information including message and stack trace
|
|
2701
|
-
* @param job - Optional full job object for debugging purposes
|
|
2872
|
+
* @returns Array of items in insertion order
|
|
2702
2873
|
*/
|
|
2703
|
-
|
|
2874
|
+
getAll(): T[];
|
|
2704
2875
|
/**
|
|
2705
|
-
*
|
|
2706
|
-
*
|
|
2707
|
-
* @param jobId - The job ID to query
|
|
2708
|
-
* @returns The job information, or null if the job is not found
|
|
2876
|
+
* Clears all items from the buffer.
|
|
2709
2877
|
*/
|
|
2710
|
-
|
|
2878
|
+
clear(): void;
|
|
2711
2879
|
/**
|
|
2712
|
-
*
|
|
2713
|
-
* Unsubscribes from all event bus subscriptions.
|
|
2880
|
+
* Gets the current number of items in the buffer.
|
|
2714
2881
|
*/
|
|
2715
|
-
|
|
2882
|
+
get length(): number;
|
|
2716
2883
|
}
|
|
2717
2884
|
//#endregion
|
|
2718
|
-
//#region src/
|
|
2885
|
+
//#region src/cache/kysely-write-cache.d.ts
|
|
2886
|
+
type DocumentStream = {
|
|
2887
|
+
key: string;
|
|
2888
|
+
ringBuffer: RingBuffer<CachedSnapshot>;
|
|
2889
|
+
};
|
|
2719
2890
|
/**
|
|
2720
|
-
*
|
|
2721
|
-
*
|
|
2722
|
-
*
|
|
2891
|
+
* In-memory write cache with keyframe persistence for PHDocuments.
|
|
2892
|
+
*
|
|
2893
|
+
* Caches document snapshots in ring buffers with LRU eviction. On cache miss,
|
|
2894
|
+
* rebuilds documents from nearest keyframe or full operation history.
|
|
2895
|
+
*
|
|
2896
|
+
* **Performance Characteristics:**
|
|
2897
|
+
* - Cache hit: O(1) lookup in ring buffer
|
|
2898
|
+
* - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe
|
|
2899
|
+
* - Warm miss: O(m) where m is operations since cached revision
|
|
2900
|
+
* - Eviction: O(1) for LRU tracking and removal
|
|
2901
|
+
*
|
|
2902
|
+
* **Thread Safety:**
|
|
2903
|
+
* Not thread-safe. Designed for single-threaded job executor environment.
|
|
2904
|
+
* External synchronization required for concurrent access across multiple executors.
|
|
2905
|
+
*
|
|
2906
|
+
* **Example:**
|
|
2907
|
+
* ```typescript
|
|
2908
|
+
* const cache = new KyselyWriteCache(
|
|
2909
|
+
* keyframeStore,
|
|
2910
|
+
* operationStore,
|
|
2911
|
+
* registry,
|
|
2912
|
+
* { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }
|
|
2913
|
+
* );
|
|
2914
|
+
*
|
|
2915
|
+
* await cache.startup();
|
|
2916
|
+
*
|
|
2917
|
+
* // Retrieve or rebuild document
|
|
2918
|
+
* const doc = await cache.getState(docId, docType, scope, branch, revision);
|
|
2919
|
+
*
|
|
2920
|
+
* // Cache result after job execution
|
|
2921
|
+
* cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);
|
|
2922
|
+
*
|
|
2923
|
+
* await cache.shutdown();
|
|
2924
|
+
* ```
|
|
2723
2925
|
*/
|
|
2724
|
-
|
|
2926
|
+
declare class KyselyWriteCache implements IWriteCache {
|
|
2927
|
+
private streams;
|
|
2928
|
+
private lruTracker;
|
|
2929
|
+
private keyframeStore;
|
|
2930
|
+
private operationStore;
|
|
2931
|
+
private registry;
|
|
2932
|
+
private config;
|
|
2933
|
+
constructor(keyframeStore: IKeyframeStore, operationStore: IOperationStore, registry: IDocumentModelRegistry, config: WriteCacheConfig);
|
|
2934
|
+
withScopedStores(operationStore: IOperationStore, keyframeStore: IKeyframeStore): KyselyWriteCache;
|
|
2725
2935
|
/**
|
|
2726
|
-
*
|
|
2727
|
-
*
|
|
2728
|
-
* Emits a 'jobAvailable' event to the event bus when the job is queued.
|
|
2729
|
-
* @param job - The job to add to the queue
|
|
2730
|
-
* @returns Promise that resolves when the job is queued
|
|
2936
|
+
* Initializes the write cache.
|
|
2937
|
+
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
2731
2938
|
*/
|
|
2732
|
-
|
|
2939
|
+
startup(): Promise<void>;
|
|
2733
2940
|
/**
|
|
2734
|
-
*
|
|
2735
|
-
*
|
|
2736
|
-
* @param scope - The scope to get jobs for
|
|
2737
|
-
* @param branch - The branch to get jobs for
|
|
2738
|
-
* @param signal - Optional abort signal to cancel the request
|
|
2739
|
-
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
2941
|
+
* Shuts down the write cache.
|
|
2942
|
+
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
2740
2943
|
*/
|
|
2741
|
-
|
|
2944
|
+
shutdown(): Promise<void>;
|
|
2742
2945
|
/**
|
|
2743
|
-
*
|
|
2744
|
-
*
|
|
2745
|
-
*
|
|
2946
|
+
* Retrieves document state at a specific revision from cache or rebuilds it.
|
|
2947
|
+
*
|
|
2948
|
+
* Note: this returns a _shallow_ copy of the document.
|
|
2949
|
+
*
|
|
2950
|
+
* Cache hit path: Returns cached snapshot if available (O(1))
|
|
2951
|
+
* Warm miss path: Rebuilds from cached base revision + incremental ops
|
|
2952
|
+
* Cold miss path: Rebuilds from keyframe or from scratch using all operations
|
|
2953
|
+
*
|
|
2954
|
+
* @param documentId - The document identifier
|
|
2955
|
+
* @param scope - The operation scope
|
|
2956
|
+
* @param branch - The operation branch
|
|
2957
|
+
* @param targetRevision - The target revision, or undefined for newest
|
|
2958
|
+
* @param signal - Optional abort signal to cancel the operation
|
|
2959
|
+
* @returns The document at the target revision
|
|
2960
|
+
* @throws {Error} "Operation aborted" if signal is aborted
|
|
2961
|
+
* @throws {ModuleNotFoundError} If document type not registered in registry
|
|
2962
|
+
* @throws {Error} "Failed to rebuild document" if operation store fails
|
|
2963
|
+
* @throws {Error} If reducer throws during operation application
|
|
2964
|
+
* @throws {Error} If document serialization fails
|
|
2746
2965
|
*/
|
|
2747
|
-
|
|
2966
|
+
getState(documentId: string, scope: string, branch: string, targetRevision?: number, signal?: AbortSignal): Promise<PHDocument>;
|
|
2748
2967
|
/**
|
|
2749
|
-
*
|
|
2750
|
-
*
|
|
2751
|
-
* is
|
|
2752
|
-
* the
|
|
2753
|
-
*
|
|
2754
|
-
*
|
|
2755
|
-
*
|
|
2756
|
-
*
|
|
2757
|
-
*
|
|
2968
|
+
* Stores a document snapshot in the cache at a specific revision.
|
|
2969
|
+
*
|
|
2970
|
+
* The cached document is a shallow copy of the input with its operation history
|
|
2971
|
+
* truncated to the last operation per scope and its clipboard cleared. This keeps
|
|
2972
|
+
* memory use and copy costs constant regardless of operation count. Consumers of
|
|
2973
|
+
* getState() must not rely on the full operation history being present; the only
|
|
2974
|
+
* guaranteed invariant is that operations[scope].at(-1) reflects the latest
|
|
2975
|
+
* operation index for each scope.
|
|
2976
|
+
*
|
|
2977
|
+
* Updates LRU tracker and may evict least recently used stream if at capacity.
|
|
2978
|
+
* Asynchronously persists keyframes at configured intervals (fire-and-forget).
|
|
2979
|
+
*
|
|
2980
|
+
* @param documentId - The document identifier
|
|
2981
|
+
* @param scope - The operation scope
|
|
2982
|
+
* @param branch - The operation branch
|
|
2983
|
+
* @param revision - The revision number
|
|
2984
|
+
* @param document - The document to cache
|
|
2985
|
+
* @throws {Error} If document serialization fails
|
|
2758
2986
|
*/
|
|
2759
|
-
|
|
2987
|
+
putState(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, position: SnapshotPosition): void;
|
|
2988
|
+
private store;
|
|
2760
2989
|
/**
|
|
2761
|
-
*
|
|
2762
|
-
*
|
|
2763
|
-
*
|
|
2764
|
-
*
|
|
2765
|
-
*
|
|
2990
|
+
* Invalidates cached document streams.
|
|
2991
|
+
*
|
|
2992
|
+
* Supports three invalidation scopes:
|
|
2993
|
+
* - Document-level: invalidate(documentId) - removes all streams for document
|
|
2994
|
+
* - Scope-level: invalidate(documentId, scope) - removes all branches for scope
|
|
2995
|
+
* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream
|
|
2996
|
+
*
|
|
2997
|
+
* @param documentId - The document identifier
|
|
2998
|
+
* @param scope - Optional scope to narrow invalidation
|
|
2999
|
+
* @param branch - Optional branch to narrow invalidation (requires scope)
|
|
3000
|
+
* @returns The number of streams evicted
|
|
2766
3001
|
*/
|
|
2767
|
-
|
|
2768
|
-
/**
|
|
2769
|
-
* Get the total size of all queues.
|
|
2770
|
-
* @returns Promise that resolves to the total number of jobs across all queues
|
|
2771
|
-
*/
|
|
2772
|
-
totalSize(): Promise<number>;
|
|
2773
|
-
/**
|
|
2774
|
-
* Remove a specific job from the queue.
|
|
2775
|
-
* @param jobId - The ID of the job to remove
|
|
2776
|
-
* @returns Promise that resolves to true if job was removed, false if not found
|
|
2777
|
-
*/
|
|
2778
|
-
remove(jobId: string): Promise<boolean>;
|
|
2779
|
-
/**
|
|
2780
|
-
* Clear all jobs for a specific document/scope/branch combination.
|
|
2781
|
-
* @param documentId - The document ID
|
|
2782
|
-
* @param scope - The scope
|
|
2783
|
-
* @param branch - The branch
|
|
2784
|
-
* @returns Promise that resolves when the queue is cleared
|
|
2785
|
-
*/
|
|
2786
|
-
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
2787
|
-
/**
|
|
2788
|
-
* Clear all jobs from all queues.
|
|
2789
|
-
* @returns Promise that resolves when all queues are cleared
|
|
2790
|
-
*/
|
|
2791
|
-
clearAll(): Promise<void>;
|
|
2792
|
-
/**
|
|
2793
|
-
* Check if there are any jobs in the queue.
|
|
2794
|
-
* @returns Promise that resolves to true if there are jobs, false otherwise
|
|
2795
|
-
*/
|
|
2796
|
-
hasJobs(): Promise<boolean>;
|
|
3002
|
+
invalidate(documentId: string, scope?: string, branch?: string): number;
|
|
2797
3003
|
/**
|
|
2798
|
-
*
|
|
2799
|
-
*
|
|
2800
|
-
* @returns Promise that resolves when the job is marked as completed
|
|
3004
|
+
* Clears the entire cache, removing all cached document streams.
|
|
3005
|
+
* Resets LRU tracking state. This operation always succeeds.
|
|
2801
3006
|
*/
|
|
2802
|
-
|
|
3007
|
+
clear(): void;
|
|
2803
3008
|
/**
|
|
2804
|
-
*
|
|
2805
|
-
*
|
|
2806
|
-
*
|
|
2807
|
-
* @
|
|
3009
|
+
* Retrieves a specific stream for a document. Exposed on the implementation
|
|
3010
|
+
* for testing, but not on the interface.
|
|
3011
|
+
*
|
|
3012
|
+
* @internal
|
|
2808
3013
|
*/
|
|
2809
|
-
|
|
3014
|
+
getStream(documentId: string, scope: string, branch: string): DocumentStream | undefined;
|
|
3015
|
+
private findNearestKeyframe;
|
|
3016
|
+
private coldMissRebuild;
|
|
2810
3017
|
/**
|
|
2811
|
-
*
|
|
2812
|
-
*
|
|
2813
|
-
* @param error - Optional error information from the failure
|
|
2814
|
-
* @param accounting - Whether the attempt counts against the job's retry
|
|
2815
|
-
* limit; defaults to {@link RetryAccounting.CountAgainstLimit}
|
|
2816
|
-
* @returns Promise that resolves when the job is requeued for retry
|
|
3018
|
+
* Copies the current document revisions onto the document. Overwrites the
|
|
3019
|
+
* requested scope revision with the target revision, if provided.
|
|
2817
3020
|
*/
|
|
2818
|
-
|
|
3021
|
+
private stampRevisions;
|
|
3022
|
+
/** The stored operation at `index`, or undefined if it is no longer there. */
|
|
3023
|
+
private operationAt;
|
|
2819
3024
|
/**
|
|
2820
|
-
*
|
|
3025
|
+
* Resolves which module version to use for a given operation in phase 2.
|
|
3026
|
+
*
|
|
3027
|
+
* Uses the validated-upgrade boundary rules from D7:
|
|
3028
|
+
* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary
|
|
3029
|
+
* - Otherwise: timestamp fallback
|
|
3030
|
+
* - Falls back to final module version when neither is decidable
|
|
2821
3031
|
*/
|
|
2822
|
-
|
|
3032
|
+
private resolveModuleVersionForOp;
|
|
3033
|
+
private warmMissRebuild;
|
|
3034
|
+
private findNearestOlderSnapshot;
|
|
3035
|
+
private makeStreamKey;
|
|
3036
|
+
private getOrCreateStream;
|
|
3037
|
+
private isKeyframeRevision;
|
|
3038
|
+
}
|
|
3039
|
+
//#endregion
|
|
3040
|
+
//#region src/storage/kysely/store.d.ts
|
|
3041
|
+
declare class KyselyOperationStore implements IOperationStore {
|
|
3042
|
+
private db;
|
|
3043
|
+
private trx?;
|
|
3044
|
+
constructor(db: Kysely<Database$1>);
|
|
3045
|
+
private get queryExecutor();
|
|
3046
|
+
withTransaction(trx: Transaction<Database$1>): KyselyOperationStore;
|
|
3047
|
+
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal, condition?: AppendCondition): Promise<Operation[]>;
|
|
3048
|
+
private resolveUniqueConstraint;
|
|
3049
|
+
private executeApply;
|
|
2823
3050
|
/**
|
|
2824
|
-
*
|
|
2825
|
-
*
|
|
3051
|
+
* Locks the written stream and every read-set stream, in sorted key order
|
|
3052
|
+
* so that overlapping concurrent appends serialize rather than deadlock.
|
|
3053
|
+
* The locks are still taken one row at a time, so the query preserves that
|
|
3054
|
+
* order. It must stay separate from the guarded insert, which would
|
|
3055
|
+
* otherwise read a snapshot taken before the locks were held.
|
|
2826
3056
|
*/
|
|
2827
|
-
|
|
3057
|
+
private acquireStreamLocks;
|
|
2828
3058
|
/**
|
|
2829
|
-
*
|
|
3059
|
+
* Inserts the staged operations with the condition compiled in as a WHERE
|
|
3060
|
+
* NOT EXISTS guard, making the check and the append one statement. Returns
|
|
3061
|
+
* the rows inserted; zero means the guard failed and nothing was written.
|
|
2830
3062
|
*/
|
|
2831
|
-
|
|
3063
|
+
private insertGuarded;
|
|
3064
|
+
private findIdempotentReplay;
|
|
3065
|
+
getSince(documentId: string, scope: string, branch: string, revision: number, filter?: OperationFilter, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
3066
|
+
getSinceId(id: number, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<OperationWithContext$1>>;
|
|
3067
|
+
getConflicting(documentId: string, scope: string, branch: string, minTimestamp: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<Operation>>;
|
|
3068
|
+
getRevisions(documentId: string, branch: string, signal?: AbortSignal): Promise<DocumentRevisions>;
|
|
3069
|
+
private rowToOperation;
|
|
3070
|
+
private rowToOperationWithContext;
|
|
2832
3071
|
}
|
|
2833
3072
|
//#endregion
|
|
2834
|
-
//#region src/
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
documentId: string
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
branch:
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
identifiers: unknown;
|
|
2854
|
-
metadata: unknown;
|
|
2855
|
-
isDeleted: Generated<boolean>;
|
|
2856
|
-
deletedAt: Date | null;
|
|
2857
|
-
}
|
|
2858
|
-
interface SlugMappingTable {
|
|
2859
|
-
slug: string;
|
|
2860
|
-
documentId: string;
|
|
2861
|
-
scope: string;
|
|
2862
|
-
branch: string;
|
|
2863
|
-
createdAt: Generated<Date>;
|
|
2864
|
-
updatedAt: Generated<Date>;
|
|
3073
|
+
//#region src/storage/kysely/keyframe-store.d.ts
|
|
3074
|
+
declare class KyselyKeyframeStore implements IKeyframeStore {
|
|
3075
|
+
private db;
|
|
3076
|
+
private trx?;
|
|
3077
|
+
constructor(db: Kysely<Database$1>);
|
|
3078
|
+
private get queryExecutor();
|
|
3079
|
+
withTransaction(trx: Transaction<Database$1>): KyselyKeyframeStore;
|
|
3080
|
+
putKeyframe(documentId: string, scope: string, branch: string, revision: number, document: PHDocument, signal?: AbortSignal): Promise<void>;
|
|
3081
|
+
findNearestKeyframe(documentId: string, scope: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<{
|
|
3082
|
+
revision: number;
|
|
3083
|
+
document: PHDocument;
|
|
3084
|
+
} | undefined>;
|
|
3085
|
+
listKeyframes(documentId: string, scope?: string, branch?: string, signal?: AbortSignal): Promise<Array<{
|
|
3086
|
+
scope: string;
|
|
3087
|
+
branch: string;
|
|
3088
|
+
revision: number;
|
|
3089
|
+
document: PHDocument;
|
|
3090
|
+
}>>;
|
|
3091
|
+
deleteKeyframes(documentId: string, scope?: string, branch?: string, signal?: AbortSignal): Promise<number>;
|
|
2865
3092
|
}
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
lastErrorTimestamp: Date | null;
|
|
2875
|
-
createdAt: Generated<Date>;
|
|
2876
|
-
updatedAt: Generated<Date>;
|
|
3093
|
+
//#endregion
|
|
3094
|
+
//#region src/executor/execution-scope.d.ts
|
|
3095
|
+
interface ExecutionStores {
|
|
3096
|
+
operationStore: IOperationStore;
|
|
3097
|
+
operationIndex: IOperationIndex;
|
|
3098
|
+
writeCache: IWriteCache;
|
|
3099
|
+
documentMetaCache: IDocumentMetaCache;
|
|
3100
|
+
collectionMembershipCache: ICollectionMembershipCache;
|
|
2877
3101
|
}
|
|
2878
|
-
interface
|
|
2879
|
-
|
|
2880
|
-
DocumentSnapshot: DocumentSnapshotTable;
|
|
2881
|
-
SlugMapping: SlugMappingTable;
|
|
2882
|
-
ProcessorCursor: ProcessorCursorTable;
|
|
3102
|
+
interface IExecutionScope {
|
|
3103
|
+
run<T>(fn: (stores: ExecutionStores) => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
2883
3104
|
}
|
|
2884
|
-
type InsertableDocumentSnapshot = Insertable<DocumentSnapshotTable>;
|
|
2885
3105
|
//#endregion
|
|
2886
|
-
//#region src/
|
|
2887
|
-
/** An importable file holding one or more document-model exports. */
|
|
2888
|
-
type FileModelSource = {
|
|
2889
|
-
filePath: string;
|
|
2890
|
-
exportName?: string;
|
|
2891
|
-
};
|
|
2892
|
-
/** An importable package specifier holding one or more document-model exports. */
|
|
2893
|
-
type PackageModelSource = {
|
|
2894
|
-
packageName: string;
|
|
2895
|
-
subpath?: string;
|
|
2896
|
-
exportName?: string;
|
|
2897
|
-
};
|
|
3106
|
+
//#region src/executor/types.d.ts
|
|
2898
3107
|
/**
|
|
2899
|
-
*
|
|
2900
|
-
* importable package. File and package sources can cross a worker-thread
|
|
2901
|
-
* boundary (workers re-import them); a live module cannot.
|
|
3108
|
+
* Represents the result of a job execution
|
|
2902
3109
|
*/
|
|
2903
|
-
type
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
3110
|
+
type JobResult = {
|
|
3111
|
+
/** The job that was executed */job: Job; /** Whether the job executed successfully */
|
|
3112
|
+
success: boolean; /** Error if the job failed */
|
|
3113
|
+
error?: Error; /** The operations generated from the actions (if successful) */
|
|
3114
|
+
operations?: Operation[];
|
|
3115
|
+
/**
|
|
3116
|
+
* Operations with context (includes ephemeral resultingState).
|
|
3117
|
+
* Used for emitting to IDocumentView via event bus.
|
|
3118
|
+
*/
|
|
3119
|
+
operationsWithContext?: OperationWithContext$1[]; /** Timestamp when the job execution completed */
|
|
3120
|
+
completedAt?: string; /** Duration of job execution in milliseconds */
|
|
3121
|
+
duration?: number; /** Any additional metadata from the execution */
|
|
3122
|
+
metadata?: Record<string, any>;
|
|
2913
3123
|
};
|
|
2914
3124
|
/**
|
|
2915
|
-
*
|
|
2916
|
-
* {@link DocumentModelSource}. Used by the queue to gate CREATE_DOCUMENT
|
|
2917
|
-
* jobs until the required model is available in the registry.
|
|
3125
|
+
* Enforcement the reactor performs, each off by default.
|
|
2918
3126
|
*
|
|
2919
|
-
*
|
|
2920
|
-
*
|
|
2921
|
-
*
|
|
2922
|
-
* DocumentModelModule is also valid but host-only — it cannot cross a
|
|
2923
|
-
* worker-thread boundary, so worker pools will not receive it.
|
|
3127
|
+
* An evaluation made while replaying is part of the document's history, so two
|
|
3128
|
+
* reactors that share documents and disagree on these diverge. A flag is turned
|
|
3129
|
+
* on for a set of reactors that sync with each other, not for one node.
|
|
2924
3130
|
*/
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3131
|
+
type ReactorFeatureFlags = {
|
|
3132
|
+
/**
|
|
3133
|
+
* Decide whether an operation may be admitted by building a decision model
|
|
3134
|
+
* over the document stream, rather than reading the deleted flag from the
|
|
3135
|
+
* document meta cache. Deletion then takes effect from the deleting
|
|
3136
|
+
* operation's position rather than for the whole document.
|
|
3137
|
+
*/
|
|
3138
|
+
documentDecisions: boolean;
|
|
3139
|
+
};
|
|
2928
3140
|
/**
|
|
2929
|
-
*
|
|
2930
|
-
* Provides centralized access to document models' reducers, utils, and specifications.
|
|
2931
|
-
* Supports version-aware module storage and upgrade manifest management.
|
|
3141
|
+
* Configuration options for the job executor
|
|
2932
3142
|
*/
|
|
2933
|
-
|
|
2934
|
-
/**
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
3143
|
+
type JobExecutorConfig = {
|
|
3144
|
+
/** Feature flags; anything unset is off. */featureFlags?: Partial<ReactorFeatureFlags>; /** Maximum number of conflicting operations to skip when reshuffling. */
|
|
3145
|
+
maxSkipThreshold?: number; /** Maximum number of concurrent jobs to execute */
|
|
3146
|
+
maxConcurrency?: number; /** Maximum time in milliseconds a job can run before being considered timed out */
|
|
3147
|
+
jobTimeoutMs?: number; /** Base delay in milliseconds for exponential backoff retries */
|
|
3148
|
+
retryBaseDelayMs?: number; /** Maximum delay in milliseconds for exponential backoff retries */
|
|
3149
|
+
retryMaxDelayMs?: number;
|
|
3150
|
+
/** Maximum elapsed milliseconds before yielding to the main thread between actions.
|
|
3151
|
+
* Keeps the UI responsive when processing large batches. */
|
|
3152
|
+
yieldDeadlineMs?: number;
|
|
3153
|
+
};
|
|
3154
|
+
/**
|
|
3155
|
+
* Event types for the job executor
|
|
3156
|
+
*/
|
|
3157
|
+
declare const JobExecutorEventTypes: {
|
|
3158
|
+
readonly JOB_STARTED: 20000;
|
|
3159
|
+
readonly JOB_COMPLETED: 20001;
|
|
3160
|
+
readonly JOB_FAILED: 20002;
|
|
3161
|
+
readonly EXECUTOR_STARTED: 20003;
|
|
3162
|
+
readonly EXECUTOR_STOPPED: 20004;
|
|
3163
|
+
};
|
|
3164
|
+
/**
|
|
3165
|
+
* Event data for job execution events
|
|
3166
|
+
*/
|
|
3167
|
+
type JobStartedEvent = {
|
|
3168
|
+
job: Job;
|
|
3169
|
+
startedAt: string;
|
|
3170
|
+
/**
|
|
3171
|
+
* Identifier of the executor that took the job. For the worker pool this is
|
|
3172
|
+
* the thread-worker id (e.g. "reactor-worker-3"); for the in-process simple
|
|
3173
|
+
* manager it is "in-process-<index>". Optional for backwards compatibility
|
|
3174
|
+
* with consumers built before the field was added.
|
|
2941
3175
|
*/
|
|
2942
|
-
|
|
3176
|
+
workerId?: string;
|
|
3177
|
+
};
|
|
3178
|
+
type JobCompletedEvent = {
|
|
3179
|
+
job: Job;
|
|
3180
|
+
result: JobResult; /** See {@link JobStartedEvent.workerId}. */
|
|
3181
|
+
workerId?: string;
|
|
3182
|
+
};
|
|
3183
|
+
type JobFailedEvent = {
|
|
3184
|
+
job: Job;
|
|
3185
|
+
error: string;
|
|
3186
|
+
willRetry: boolean;
|
|
3187
|
+
retryCount: number; /** See {@link JobStartedEvent.workerId}. */
|
|
3188
|
+
workerId?: string;
|
|
3189
|
+
};
|
|
3190
|
+
type ExecutorStartedEvent = {
|
|
3191
|
+
config: JobExecutorConfig;
|
|
3192
|
+
startedAt: string;
|
|
3193
|
+
};
|
|
3194
|
+
type ExecutorStoppedEvent = {
|
|
3195
|
+
stoppedAt: string;
|
|
3196
|
+
graceful: boolean;
|
|
3197
|
+
};
|
|
3198
|
+
/**
|
|
3199
|
+
* Status information for the job executor manager
|
|
3200
|
+
*/
|
|
3201
|
+
type ExecutorManagerStatus = {
|
|
3202
|
+
/** Whether the manager is currently running */isRunning: boolean; /** Number of executor instances managed */
|
|
3203
|
+
numExecutors: number; /** Number of jobs currently being processed */
|
|
3204
|
+
activeJobs: number; /** Total number of jobs processed since start */
|
|
3205
|
+
totalJobsProcessed: number;
|
|
3206
|
+
};
|
|
3207
|
+
//#endregion
|
|
3208
|
+
//#region src/executor/interfaces.d.ts
|
|
3209
|
+
/**
|
|
3210
|
+
* Snapshot of the single in-flight slot maintained by an {@link IExecutorWorker}.
|
|
3211
|
+
*/
|
|
3212
|
+
type WorkerInFlightSnapshot = {
|
|
3213
|
+
correlationId: string;
|
|
3214
|
+
jobId: string;
|
|
3215
|
+
};
|
|
3216
|
+
/**
|
|
3217
|
+
* Outcome of a worker-side job execution.
|
|
3218
|
+
*
|
|
3219
|
+
* `result` mirrors the in-process `JobResult` exactly. `writeReady` carries
|
|
3220
|
+
* the operations + jobMeta the parent needs to emit `JOB_WRITE_READY`, and is
|
|
3221
|
+
* present only when the worker produced operations. It is absent on failure
|
|
3222
|
+
* and on success-with-no-operations.
|
|
3223
|
+
*/
|
|
3224
|
+
type WorkerExecutionOutcome = {
|
|
3225
|
+
result: JobResult;
|
|
3226
|
+
writeReady?: JobWriteReadyPayload;
|
|
3227
|
+
};
|
|
3228
|
+
/**
|
|
3229
|
+
* Parent-side handle for a single executor worker.
|
|
3230
|
+
*
|
|
3231
|
+
* Implementations wrap an IPC transport (worker_threads, child_process, or a
|
|
3232
|
+
* test fake) and expose a transport-agnostic surface that the worker-pool
|
|
3233
|
+
* manager uses to dispatch jobs. The handle owns one worker's lifecycle
|
|
3234
|
+
* (`start` -> `execute`* -> `shutdown`) and bounds its in-flight map to a
|
|
3235
|
+
* single entry; `SimpleJobExecutor` is single-threaded inside the worker, so
|
|
3236
|
+
* concurrent dispatches would race its caches.
|
|
3237
|
+
*/
|
|
3238
|
+
interface IExecutorWorker {
|
|
3239
|
+
/** Stable identifier of the worker (mirrors `InitMessage.workerId`). */
|
|
3240
|
+
readonly workerId: string;
|
|
3241
|
+
/** Zero-based index within the pool, used for sticky routing. */
|
|
3242
|
+
readonly index: number;
|
|
2943
3243
|
/**
|
|
2944
|
-
*
|
|
2945
|
-
*
|
|
2946
|
-
* @param documentTypes The document types to unregister
|
|
2947
|
-
* @returns true if all modules were unregistered, false if any were not found
|
|
3244
|
+
* Spawn the worker (if not already started), send the `init` payload and
|
|
3245
|
+
* resolve when the worker replies with `ready`.
|
|
2948
3246
|
*/
|
|
2949
|
-
|
|
3247
|
+
start(): Promise<void>;
|
|
2950
3248
|
/**
|
|
2951
|
-
*
|
|
2952
|
-
*
|
|
2953
|
-
*
|
|
2954
|
-
*
|
|
2955
|
-
*
|
|
2956
|
-
* @returns The document model module
|
|
2957
|
-
* @throws ModuleNotFoundError if the document type or version is not registered
|
|
3249
|
+
* Dispatch a job to the worker and resolve with its outcome — the
|
|
3250
|
+
* `JobResult` and, on success-with-operations, a `writeReady` payload
|
|
3251
|
+
* the parent will enrich and re-emit. Rejects with a transport-level
|
|
3252
|
+
* error if the worker exits, aborts, or times out before producing a
|
|
3253
|
+
* result.
|
|
2958
3254
|
*/
|
|
2959
|
-
|
|
3255
|
+
execute(job: Job, signal?: AbortSignal): Promise<WorkerExecutionOutcome>;
|
|
2960
3256
|
/**
|
|
2961
|
-
*
|
|
2962
|
-
*
|
|
2963
|
-
*
|
|
3257
|
+
* Request cancellation of the in-flight job (if any). The handle posts an
|
|
3258
|
+
* `abort` message; if the worker fails to reply within its grace window it
|
|
3259
|
+
* is force-terminated.
|
|
2964
3260
|
*/
|
|
2965
|
-
|
|
3261
|
+
abort(correlationId: string, reason?: string): void;
|
|
2966
3262
|
/**
|
|
2967
|
-
*
|
|
3263
|
+
* Stop the worker. When `graceful` is true the handle waits for the
|
|
3264
|
+
* in-flight job to settle (up to `graceMs`) before terminating; otherwise
|
|
3265
|
+
* the worker is terminated immediately.
|
|
2968
3266
|
*/
|
|
2969
|
-
|
|
3267
|
+
shutdown(graceful: boolean, graceMs?: number): Promise<void>;
|
|
2970
3268
|
/**
|
|
2971
|
-
*
|
|
2972
|
-
*
|
|
2973
|
-
*
|
|
2974
|
-
* @returns Array of version numbers sorted ascending
|
|
2975
|
-
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
3269
|
+
* Register an additional document model on the running worker. Resolves
|
|
3270
|
+
* when the worker replies with `model-loaded`; rejects when it replies
|
|
3271
|
+
* with `model-load-failed` or the worker exits before answering.
|
|
2976
3272
|
*/
|
|
2977
|
-
|
|
3273
|
+
loadModel(entry: ModelManifestEntry, signal?: AbortSignal): Promise<void>;
|
|
3274
|
+
/** True when no job is currently in flight. */
|
|
3275
|
+
isIdle(): boolean;
|
|
3276
|
+
/** Snapshot of the in-flight slot, or null when idle. */
|
|
3277
|
+
getInFlight(): WorkerInFlightSnapshot | null;
|
|
3278
|
+
}
|
|
3279
|
+
/**
|
|
3280
|
+
* Simple interface for executing a job.
|
|
3281
|
+
* A JobExecutor simply takes a job and executes it - nothing more.
|
|
3282
|
+
*/
|
|
3283
|
+
interface IJobExecutor {
|
|
2978
3284
|
/**
|
|
2979
|
-
*
|
|
2980
|
-
*
|
|
2981
|
-
* @
|
|
2982
|
-
* @returns The highest version number registered for this document type
|
|
2983
|
-
* @throws ModuleNotFoundError if no modules are registered for the document type
|
|
3285
|
+
* Execute a single job.
|
|
3286
|
+
* @param job - The job to execute
|
|
3287
|
+
* @returns Promise that resolves to the job result
|
|
2984
3288
|
*/
|
|
2985
|
-
|
|
3289
|
+
executeJob(job: Job, signal?: AbortSignal): Promise<JobResult>;
|
|
3290
|
+
}
|
|
3291
|
+
/**
|
|
3292
|
+
* Interface for managing multiple job executors.
|
|
3293
|
+
* Listens for 'jobAvailable' events from the event bus, pulls jobs from the queue,
|
|
3294
|
+
* and coordinates the distribution of jobs across multiple executor instances.
|
|
3295
|
+
*/
|
|
3296
|
+
interface IJobExecutorManager {
|
|
2986
3297
|
/**
|
|
2987
|
-
*
|
|
2988
|
-
*
|
|
3298
|
+
* Start the executor manager.
|
|
3299
|
+
* Begins listening for 'jobAvailable' events and dispatching to executors.
|
|
2989
3300
|
*
|
|
2990
|
-
* @param
|
|
2991
|
-
* @returns
|
|
3301
|
+
* @param numExecutors - Number of executor instances to create
|
|
3302
|
+
* @returns Promise that resolves when the manager is started
|
|
2992
3303
|
*/
|
|
2993
|
-
|
|
2994
|
-
/**
|
|
2995
|
-
* Unregister upgrade manifests for the specified document types.
|
|
2996
|
-
* @param documentTypes The document types whose upgrade manifests should be unregistered
|
|
2997
|
-
* @returns true if all modules were unregistered, false if any were not found
|
|
2998
|
-
**/
|
|
2999
|
-
unregisterUpgradeManifests(...documentTypes: string[]): boolean;
|
|
3304
|
+
start(numExecutors: number): Promise<void>;
|
|
3000
3305
|
/**
|
|
3001
|
-
*
|
|
3306
|
+
* Stop the executor manager.
|
|
3002
3307
|
*
|
|
3003
|
-
* @param
|
|
3004
|
-
* @returns
|
|
3005
|
-
* @throws ManifestNotFoundError if no manifest is registered for the document type
|
|
3308
|
+
* @param graceful - Whether to wait for current jobs to complete
|
|
3309
|
+
* @returns Promise that resolves when the manager is stopped
|
|
3006
3310
|
*/
|
|
3007
|
-
|
|
3311
|
+
stop(graceful?: boolean): Promise<void>;
|
|
3008
3312
|
/**
|
|
3009
|
-
*
|
|
3010
|
-
* Returns the sequence of upgrade transitions needed.
|
|
3313
|
+
* Get all managed executor instances.
|
|
3011
3314
|
*
|
|
3012
|
-
* @
|
|
3013
|
-
* @param fromVersion The starting version
|
|
3014
|
-
* @param toVersion The target version
|
|
3015
|
-
* @returns Array of upgrade transitions in order
|
|
3016
|
-
* @throws DowngradeNotSupportedError if toVersion is less than fromVersion
|
|
3017
|
-
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
3018
|
-
* @throws MissingUpgradeTransitionError if any transition in the path is missing
|
|
3315
|
+
* @returns Array of executor instances
|
|
3019
3316
|
*/
|
|
3020
|
-
|
|
3317
|
+
getExecutors(): IJobExecutor[];
|
|
3021
3318
|
/**
|
|
3022
|
-
* Get the
|
|
3319
|
+
* Get the current status of the manager.
|
|
3023
3320
|
*
|
|
3024
|
-
* @
|
|
3025
|
-
* @param fromVersion The starting version
|
|
3026
|
-
* @param toVersion The target version (must be fromVersion + 1)
|
|
3027
|
-
* @returns The upgrade reducer function
|
|
3028
|
-
* @throws InvalidUpgradeStepError if toVersion is not fromVersion + 1
|
|
3029
|
-
* @throws ManifestNotFoundError if no upgrade manifest is registered
|
|
3030
|
-
* @throws MissingUpgradeTransitionError if the transition is not found
|
|
3321
|
+
* @returns The current manager status
|
|
3031
3322
|
*/
|
|
3032
|
-
|
|
3323
|
+
getStatus(): ExecutorManagerStatus;
|
|
3033
3324
|
}
|
|
3034
3325
|
//#endregion
|
|
3035
|
-
//#region src/
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
*/
|
|
3042
|
-
update(coordinates: ConsistencyCoordinate[]): void;
|
|
3326
|
+
//#region src/job-tracker/interfaces.d.ts
|
|
3327
|
+
/**
|
|
3328
|
+
* Interface for tracking job lifecycle status.
|
|
3329
|
+
* Maintains job state throughout execution: PENDING → RUNNING → COMPLETED/FAILED.
|
|
3330
|
+
*/
|
|
3331
|
+
interface IJobTracker {
|
|
3043
3332
|
/**
|
|
3044
|
-
*
|
|
3333
|
+
* Register a new job with PENDING status.
|
|
3334
|
+
*
|
|
3335
|
+
* @param jobInfo - The job information to register
|
|
3045
3336
|
*/
|
|
3046
|
-
|
|
3337
|
+
registerJob(jobInfo: JobInfo): void;
|
|
3047
3338
|
/**
|
|
3048
|
-
*
|
|
3049
|
-
*
|
|
3339
|
+
* Update a job's status to RUNNING.
|
|
3340
|
+
*
|
|
3341
|
+
* @param jobId - The job ID to mark as running
|
|
3050
3342
|
*/
|
|
3051
|
-
|
|
3343
|
+
markRunning(jobId: string): void;
|
|
3344
|
+
/**
|
|
3345
|
+
* Mark a job as failed.
|
|
3346
|
+
*
|
|
3347
|
+
* @param jobId - The job ID to mark as failed
|
|
3348
|
+
* @param error - Error information including message and stack trace
|
|
3349
|
+
* @param job - Optional full job object for debugging purposes
|
|
3350
|
+
*/
|
|
3351
|
+
markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
|
|
3352
|
+
/**
|
|
3353
|
+
* Retrieve the current status of a job.
|
|
3354
|
+
*
|
|
3355
|
+
* @param jobId - The job ID to query
|
|
3356
|
+
* @returns The job information, or null if the job is not found
|
|
3357
|
+
*/
|
|
3358
|
+
getJobStatus(jobId: string): JobInfo | null;
|
|
3359
|
+
/**
|
|
3360
|
+
* Shutdown the job tracker and clean up resources.
|
|
3361
|
+
* Unsubscribes from all event bus subscriptions.
|
|
3362
|
+
*/
|
|
3363
|
+
shutdown(): void;
|
|
3364
|
+
}
|
|
3365
|
+
//#endregion
|
|
3366
|
+
//#region src/queue/interfaces.d.ts
|
|
3367
|
+
/**
|
|
3368
|
+
* Interface for a job queue that manages write operations.
|
|
3369
|
+
* Internally organizes jobs by documentId, scope, and branch to ensure proper ordering.
|
|
3370
|
+
* Emits events to the event bus when new jobs are available for consumption.
|
|
3371
|
+
*/
|
|
3372
|
+
interface IQueue {
|
|
3373
|
+
/**
|
|
3374
|
+
* Add a new job to the queue.
|
|
3375
|
+
* Jobs are automatically organized by documentId, scope, and branch internally.
|
|
3376
|
+
* Emits a 'jobAvailable' event to the event bus when the job is queued.
|
|
3377
|
+
* @param job - The job to add to the queue
|
|
3378
|
+
* @returns Promise that resolves when the job is queued
|
|
3379
|
+
*/
|
|
3380
|
+
enqueue(job: Job): Promise<void>;
|
|
3381
|
+
/**
|
|
3382
|
+
* Get the next job to execute for a specific document/scope/branch combination.
|
|
3383
|
+
* @param documentId - The document ID to get jobs for
|
|
3384
|
+
* @param scope - The scope to get jobs for
|
|
3385
|
+
* @param branch - The branch to get jobs for
|
|
3386
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3387
|
+
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
3388
|
+
*/
|
|
3389
|
+
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3390
|
+
/**
|
|
3391
|
+
* Get the next available job from any queue.
|
|
3392
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3393
|
+
* @returns Promise that resolves to the next job execution handle or null if no jobs available
|
|
3394
|
+
*/
|
|
3395
|
+
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3396
|
+
/**
|
|
3397
|
+
* Get the next available job whose routing metadata satisfies the predicate.
|
|
3398
|
+
* Walks ready sub-queue heads in queue insertion order, skips heads whose document
|
|
3399
|
+
* is currently executing (same isDocumentExecuting gate as dequeueNext), and returns
|
|
3400
|
+
* the first head for which predicate returns true.
|
|
3401
|
+
* Returns null when paused, when nothing matches, or when the queue is empty.
|
|
3402
|
+
* Rejects if signal is already aborted.
|
|
3403
|
+
* @param predicate - Filter applied to JobRoutingMeta of each candidate head
|
|
3404
|
+
* @param signal - Optional abort signal to cancel the request
|
|
3405
|
+
* @returns Promise that resolves to the first matching job execution handle or null
|
|
3406
|
+
*/
|
|
3407
|
+
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
3408
|
+
/**
|
|
3409
|
+
* Get the current size of the queue for a specific document/scope/branch.
|
|
3410
|
+
* @param documentId - The document ID
|
|
3411
|
+
* @param scope - The scope
|
|
3412
|
+
* @param branch - The branch
|
|
3413
|
+
* @returns Promise that resolves to the number of jobs in the queue
|
|
3414
|
+
*/
|
|
3415
|
+
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
3416
|
+
/**
|
|
3417
|
+
* Get the total size of all queues.
|
|
3418
|
+
* @returns Promise that resolves to the total number of jobs across all queues
|
|
3419
|
+
*/
|
|
3420
|
+
totalSize(): Promise<number>;
|
|
3421
|
+
/**
|
|
3422
|
+
* Remove a specific job from the queue.
|
|
3423
|
+
* @param jobId - The ID of the job to remove
|
|
3424
|
+
* @returns Promise that resolves to true if job was removed, false if not found
|
|
3425
|
+
*/
|
|
3426
|
+
remove(jobId: string): Promise<boolean>;
|
|
3427
|
+
/**
|
|
3428
|
+
* Clear all jobs for a specific document/scope/branch combination.
|
|
3429
|
+
* @param documentId - The document ID
|
|
3430
|
+
* @param scope - The scope
|
|
3431
|
+
* @param branch - The branch
|
|
3432
|
+
* @returns Promise that resolves when the queue is cleared
|
|
3433
|
+
*/
|
|
3434
|
+
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
3435
|
+
/**
|
|
3436
|
+
* Clear all jobs from all queues.
|
|
3437
|
+
* @returns Promise that resolves when all queues are cleared
|
|
3438
|
+
*/
|
|
3439
|
+
clearAll(): Promise<void>;
|
|
3440
|
+
/**
|
|
3441
|
+
* Check if there are any jobs in the queue.
|
|
3442
|
+
* @returns Promise that resolves to true if there are jobs, false otherwise
|
|
3443
|
+
*/
|
|
3444
|
+
hasJobs(): Promise<boolean>;
|
|
3445
|
+
/**
|
|
3446
|
+
* Mark a job as completed.
|
|
3447
|
+
* @param jobId - The ID of the job to mark as completed
|
|
3448
|
+
* @returns Promise that resolves when the job is marked as completed
|
|
3449
|
+
*/
|
|
3450
|
+
completeJob(jobId: string): Promise<void>;
|
|
3451
|
+
/**
|
|
3452
|
+
* Mark a job as failed.
|
|
3453
|
+
* @param jobId - The ID of the job to mark as failed
|
|
3454
|
+
* @param error - Optional error information
|
|
3455
|
+
* @returns Promise that resolves when the job is marked as failed
|
|
3456
|
+
*/
|
|
3457
|
+
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
3458
|
+
/**
|
|
3459
|
+
* Retry a failed job.
|
|
3460
|
+
* @param jobId - The ID of the job to retry
|
|
3461
|
+
* @param error - Optional error information from the failure
|
|
3462
|
+
* @param accounting - Whether the attempt counts against the job's retry
|
|
3463
|
+
* limit; defaults to {@link RetryAccounting.CountAgainstLimit}
|
|
3464
|
+
* @returns Promise that resolves when the job is requeued for retry
|
|
3465
|
+
*/
|
|
3466
|
+
retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
|
|
3467
|
+
/**
|
|
3468
|
+
* Returns true if and only if all jobs have been resolved.
|
|
3469
|
+
*/
|
|
3470
|
+
get isDrained(): boolean;
|
|
3471
|
+
/**
|
|
3472
|
+
* Blocks the queue from accepting new jobs.
|
|
3473
|
+
* @param onDrained - Optional callback to call when the queue is drained
|
|
3474
|
+
*/
|
|
3475
|
+
block(onDrained?: () => void): void;
|
|
3476
|
+
/**
|
|
3477
|
+
* Unblocks the queue from accepting new jobs.
|
|
3478
|
+
*/
|
|
3479
|
+
unblock(): void;
|
|
3480
|
+
}
|
|
3481
|
+
//#endregion
|
|
3482
|
+
//#region src/read-models/types.d.ts
|
|
3483
|
+
interface ViewStateTable {
|
|
3484
|
+
readModelId: string;
|
|
3485
|
+
lastOrdinal: number;
|
|
3486
|
+
lastOperationTimestamp: Generated<Date>;
|
|
3487
|
+
}
|
|
3488
|
+
interface DocumentSnapshotTable {
|
|
3489
|
+
id: Generated<string>;
|
|
3490
|
+
documentId: string;
|
|
3491
|
+
slug: string | null;
|
|
3492
|
+
name: string | null;
|
|
3493
|
+
scope: string;
|
|
3494
|
+
branch: string;
|
|
3495
|
+
content: unknown;
|
|
3496
|
+
documentType: string;
|
|
3497
|
+
lastOperationIndex: number;
|
|
3498
|
+
lastOperationHash: string;
|
|
3499
|
+
lastUpdatedAt: Generated<Date>;
|
|
3500
|
+
snapshotVersion: Generated<number>;
|
|
3501
|
+
identifiers: unknown;
|
|
3502
|
+
metadata: unknown;
|
|
3503
|
+
isDeleted: Generated<boolean>;
|
|
3504
|
+
deletedAt: Date | null;
|
|
3505
|
+
}
|
|
3506
|
+
interface SlugMappingTable {
|
|
3507
|
+
slug: string;
|
|
3508
|
+
documentId: string;
|
|
3509
|
+
scope: string;
|
|
3510
|
+
branch: string;
|
|
3511
|
+
createdAt: Generated<Date>;
|
|
3512
|
+
updatedAt: Generated<Date>;
|
|
3513
|
+
}
|
|
3514
|
+
interface ProcessorCursorTable {
|
|
3515
|
+
processorId: string;
|
|
3516
|
+
factoryId: string;
|
|
3517
|
+
driveId: string;
|
|
3518
|
+
processorIndex: number;
|
|
3519
|
+
lastOrdinal: Generated<number>;
|
|
3520
|
+
status: Generated<string>;
|
|
3521
|
+
lastError: string | null;
|
|
3522
|
+
lastErrorTimestamp: Date | null;
|
|
3523
|
+
createdAt: Generated<Date>;
|
|
3524
|
+
updatedAt: Generated<Date>;
|
|
3525
|
+
}
|
|
3526
|
+
interface DocumentViewDatabase {
|
|
3527
|
+
ViewState: ViewStateTable;
|
|
3528
|
+
DocumentSnapshot: DocumentSnapshotTable;
|
|
3529
|
+
SlugMapping: SlugMappingTable;
|
|
3530
|
+
ProcessorCursor: ProcessorCursorTable;
|
|
3531
|
+
}
|
|
3532
|
+
type InsertableDocumentSnapshot = Insertable<DocumentSnapshotTable>;
|
|
3533
|
+
//#endregion
|
|
3534
|
+
//#region src/shared/consistency-tracker.d.ts
|
|
3535
|
+
interface IConsistencyTracker {
|
|
3536
|
+
/**
|
|
3537
|
+
* Updates the tracker with new operation indexes.
|
|
3538
|
+
* When multiple coordinates have the same key, keeps the highest operationIndex.
|
|
3539
|
+
* Resolves any pending waiters whose coordinates are now satisfied.
|
|
3540
|
+
*/
|
|
3541
|
+
update(coordinates: ConsistencyCoordinate[]): void;
|
|
3542
|
+
/**
|
|
3543
|
+
* Returns the latest operation index for a given key, or undefined if not tracked.
|
|
3544
|
+
*/
|
|
3545
|
+
getLatest(key: ConsistencyKey): number | undefined;
|
|
3546
|
+
/**
|
|
3547
|
+
* Returns a promise that resolves when all coordinates are satisfied.
|
|
3548
|
+
* Rejects if the timeout is reached or the signal is aborted.
|
|
3549
|
+
*/
|
|
3550
|
+
waitFor(coordinates: ConsistencyCoordinate[], timeoutMs?: number, signal?: AbortSignal): Promise<void>;
|
|
3052
3551
|
/**
|
|
3053
3552
|
* Returns a serializable snapshot of the current state.
|
|
3054
3553
|
*/
|
|
@@ -3080,136 +3579,6 @@ declare class ConsistencyTracker implements IConsistencyTracker {
|
|
|
3080
3579
|
private removeWaiter;
|
|
3081
3580
|
}
|
|
3082
3581
|
//#endregion
|
|
3083
|
-
//#region src/storage/kysely/types.d.ts
|
|
3084
|
-
interface OperationTable {
|
|
3085
|
-
id: Generated<number>;
|
|
3086
|
-
jobId: string;
|
|
3087
|
-
opId: string;
|
|
3088
|
-
prevOpId: string;
|
|
3089
|
-
writeTimestampUtcMs: Generated<Date>;
|
|
3090
|
-
documentId: string;
|
|
3091
|
-
documentType: string;
|
|
3092
|
-
scope: string;
|
|
3093
|
-
branch: string;
|
|
3094
|
-
timestampUtcMs: Date;
|
|
3095
|
-
index: number;
|
|
3096
|
-
action: unknown;
|
|
3097
|
-
skip: number;
|
|
3098
|
-
error?: string | null;
|
|
3099
|
-
deniedReason?: string | null;
|
|
3100
|
-
hash: string;
|
|
3101
|
-
}
|
|
3102
|
-
interface KeyframeTable {
|
|
3103
|
-
id: Generated<number>;
|
|
3104
|
-
documentId: string;
|
|
3105
|
-
documentType: string;
|
|
3106
|
-
scope: string;
|
|
3107
|
-
branch: string;
|
|
3108
|
-
revision: number;
|
|
3109
|
-
document: unknown;
|
|
3110
|
-
createdAt: Generated<Date>;
|
|
3111
|
-
}
|
|
3112
|
-
interface DocumentCollectionTable {
|
|
3113
|
-
documentId: string;
|
|
3114
|
-
collectionId: string;
|
|
3115
|
-
joinedOrdinal: bigint;
|
|
3116
|
-
leftOrdinal: bigint | null;
|
|
3117
|
-
}
|
|
3118
|
-
interface OperationIndexOperationTable {
|
|
3119
|
-
ordinal: Generated<number>;
|
|
3120
|
-
opId: string;
|
|
3121
|
-
documentId: string;
|
|
3122
|
-
documentType: string;
|
|
3123
|
-
scope: string;
|
|
3124
|
-
branch: string;
|
|
3125
|
-
timestampUtcMs: string;
|
|
3126
|
-
writeTimestampUtcMs: Generated<Date>;
|
|
3127
|
-
index: number;
|
|
3128
|
-
skip: number;
|
|
3129
|
-
hash: string;
|
|
3130
|
-
action: unknown;
|
|
3131
|
-
deniedReason?: string | null;
|
|
3132
|
-
sourceRemote: Generated<string>;
|
|
3133
|
-
}
|
|
3134
|
-
interface SyncRemoteTable {
|
|
3135
|
-
name: string;
|
|
3136
|
-
collection_id: string;
|
|
3137
|
-
channel_type: string;
|
|
3138
|
-
channel_id: string;
|
|
3139
|
-
remote_name: string;
|
|
3140
|
-
channel_parameters: unknown;
|
|
3141
|
-
filter_document_ids: unknown;
|
|
3142
|
-
filter_scopes: unknown;
|
|
3143
|
-
filter_branch: string;
|
|
3144
|
-
push_state: string;
|
|
3145
|
-
push_last_success_utc_ms: string | null;
|
|
3146
|
-
push_last_failure_utc_ms: string | null;
|
|
3147
|
-
push_failure_count: number;
|
|
3148
|
-
pull_state: string;
|
|
3149
|
-
pull_last_success_utc_ms: string | null;
|
|
3150
|
-
pull_last_failure_utc_ms: string | null;
|
|
3151
|
-
pull_failure_count: number;
|
|
3152
|
-
created_at: Generated<Date>;
|
|
3153
|
-
updated_at: Generated<Date>;
|
|
3154
|
-
}
|
|
3155
|
-
interface SyncCursorTable {
|
|
3156
|
-
remote_name: string;
|
|
3157
|
-
cursor_type: string;
|
|
3158
|
-
cursor_ordinal: bigint;
|
|
3159
|
-
last_synced_at_utc_ms: string | null;
|
|
3160
|
-
updated_at: Generated<Date>;
|
|
3161
|
-
}
|
|
3162
|
-
/**
|
|
3163
|
-
* Kysely table definition for the `sync_dead_letters` table.
|
|
3164
|
-
*/
|
|
3165
|
-
interface SyncDeadLetterTable {
|
|
3166
|
-
ordinal: Generated<number>;
|
|
3167
|
-
id: string;
|
|
3168
|
-
job_id: string;
|
|
3169
|
-
job_dependencies: unknown;
|
|
3170
|
-
remote_name: string;
|
|
3171
|
-
document_id: string;
|
|
3172
|
-
scopes: unknown;
|
|
3173
|
-
branch: string;
|
|
3174
|
-
operations: unknown;
|
|
3175
|
-
error_source: string;
|
|
3176
|
-
error_message: string;
|
|
3177
|
-
created_at: Generated<Date>;
|
|
3178
|
-
}
|
|
3179
|
-
interface Database$1 {
|
|
3180
|
-
Operation: OperationTable;
|
|
3181
|
-
Keyframe: KeyframeTable;
|
|
3182
|
-
document_collections: DocumentCollectionTable;
|
|
3183
|
-
operation_index_operations: OperationIndexOperationTable;
|
|
3184
|
-
sync_remotes: SyncRemoteTable;
|
|
3185
|
-
sync_cursors: SyncCursorTable;
|
|
3186
|
-
sync_dead_letters: SyncDeadLetterTable;
|
|
3187
|
-
}
|
|
3188
|
-
interface DocumentTable {
|
|
3189
|
-
id: string;
|
|
3190
|
-
createdAt: Generated<Date>;
|
|
3191
|
-
updatedAt: Generated<Date>;
|
|
3192
|
-
}
|
|
3193
|
-
interface DocumentRelationshipTable {
|
|
3194
|
-
id: Generated<string>;
|
|
3195
|
-
sourceId: string;
|
|
3196
|
-
targetId: string;
|
|
3197
|
-
relationshipType: string;
|
|
3198
|
-
metadata: unknown;
|
|
3199
|
-
createdAt: Generated<Date>;
|
|
3200
|
-
updatedAt: Generated<Date>;
|
|
3201
|
-
}
|
|
3202
|
-
interface IndexerStateTable {
|
|
3203
|
-
id: Generated<number>;
|
|
3204
|
-
lastOperationId: number;
|
|
3205
|
-
lastOperationTimestamp: Generated<Date>;
|
|
3206
|
-
}
|
|
3207
|
-
interface DocumentIndexerDatabase {
|
|
3208
|
-
Document: DocumentTable;
|
|
3209
|
-
DocumentRelationship: DocumentRelationshipTable;
|
|
3210
|
-
IndexerState: IndexerStateTable;
|
|
3211
|
-
}
|
|
3212
|
-
//#endregion
|
|
3213
3582
|
//#region src/storage/pool-instrumentation.d.ts
|
|
3214
3583
|
/**
|
|
3215
3584
|
* Snapshot of a pg.Pool's internal counters at a point in time.
|
|
@@ -3951,12 +4320,6 @@ declare class DriveClient implements IDriveClient {
|
|
|
3951
4320
|
private removeFileNode;
|
|
3952
4321
|
}
|
|
3953
4322
|
//#endregion
|
|
3954
|
-
//#region src/cache/collection-membership-cache.d.ts
|
|
3955
|
-
interface ICollectionMembershipCache {
|
|
3956
|
-
getCollectionsForDocuments(documentIds: string[]): Promise<Record<string, string[]>>;
|
|
3957
|
-
invalidate(documentId: string): void;
|
|
3958
|
-
}
|
|
3959
|
-
//#endregion
|
|
3960
4323
|
//#region src/registry/document-model-resolver.d.ts
|
|
3961
4324
|
interface IDocumentModelResolver {
|
|
3962
4325
|
ensureModelLoaded(documentType: string): Promise<void>;
|
|
@@ -4213,984 +4576,621 @@ type ProjectionShardManagerConfig = {
|
|
|
4213
4576
|
* manager routes each shard's `pool-acquire-samples` message to the
|
|
4214
4577
|
* matching forwarder so the host's OpenTelemetry instrumentation records
|
|
4215
4578
|
* acquire-wait latencies as if each shard's pg.Pool were local.
|
|
4216
|
-
*/
|
|
4217
|
-
poolInstrumentations?: ForwardingPoolInstrumentation[];
|
|
4218
|
-
};
|
|
4219
|
-
//#endregion
|
|
4220
|
-
//#region src/signer/types.d.ts
|
|
4221
|
-
/**
|
|
4222
|
-
* Configuration for signing and verification.
|
|
4223
|
-
*/
|
|
4224
|
-
type SignerConfig = {
|
|
4225
|
-
/**
|
|
4226
|
-
* The signer used to sign actions before submission.
|
|
4227
|
-
*/
|
|
4228
|
-
signer: ISigner;
|
|
4229
|
-
/**
|
|
4230
|
-
* Optional handler for verifying signatures on incoming operations.
|
|
4231
|
-
* If not provided, signature verification will be skipped.
|
|
4232
|
-
*/
|
|
4233
|
-
verifier?: SignatureVerificationHandler;
|
|
4234
|
-
};
|
|
4235
|
-
//#endregion
|
|
4236
|
-
//#region src/storage/migrations/types.d.ts
|
|
4237
|
-
type MigrationStrategy = "auto" | "manual" | "none";
|
|
4238
|
-
interface MigrationResult {
|
|
4239
|
-
success: boolean;
|
|
4240
|
-
migrationsExecuted: string[];
|
|
4241
|
-
error?: Error;
|
|
4242
|
-
}
|
|
4243
|
-
//#endregion
|
|
4244
|
-
//#region src/sync/sync-builder.d.ts
|
|
4245
|
-
declare class SyncBuilder {
|
|
4246
|
-
private channelFactory?;
|
|
4247
|
-
private remoteStorage?;
|
|
4248
|
-
private cursorStorage?;
|
|
4249
|
-
private deadLetterStorage?;
|
|
4250
|
-
private config;
|
|
4251
|
-
withChannelFactory(factory: IChannelFactory): this;
|
|
4252
|
-
withRemoteStorage(storage: ISyncRemoteStorage): this;
|
|
4253
|
-
withCursorStorage(storage: ISyncCursorStorage): this;
|
|
4254
|
-
withDeadLetterStorage(storage: ISyncDeadLetterStorage): this;
|
|
4255
|
-
withMaxDeadLettersPerRemote(limit: number): this;
|
|
4256
|
-
withMaxInboxBatchSize(limit: number): this;
|
|
4257
|
-
build(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): ISyncManager;
|
|
4258
|
-
buildModule(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): InProcessSyncModule;
|
|
4259
|
-
}
|
|
4260
|
-
//#endregion
|
|
4261
|
-
//#region src/core/reactor-builder.d.ts
|
|
4262
|
-
/**
|
|
4263
|
-
* Dependencies provided to read-model factories registered via
|
|
4264
|
-
* `withReadModelFactory`. These are constructed inside `buildModule()`, which
|
|
4265
|
-
* is why factory-based registration is needed for read models that depend on
|
|
4266
|
-
* them (`BaseReadModel` subclasses, in particular).
|
|
4267
|
-
*/
|
|
4268
|
-
interface ReadModelFactoryDeps {
|
|
4269
|
-
documentModelRegistry: IDocumentModelRegistry;
|
|
4270
|
-
operationIndex: IOperationIndex;
|
|
4271
|
-
writeCache: IWriteCache;
|
|
4272
|
-
processorManagerConsistencyTracker: IConsistencyTracker;
|
|
4273
|
-
}
|
|
4274
|
-
/**
|
|
4275
|
-
* Factory that builds a pre-ready read model from internal reactor
|
|
4276
|
-
* dependencies once they are available. Awaited during `buildModule()`.
|
|
4277
|
-
*/
|
|
4278
|
-
type ReadModelFactory = (deps: ReadModelFactoryDeps) => IReadModel | Promise<IReadModel>;
|
|
4279
|
-
type WorkerPoolBase = {
|
|
4280
|
-
/** Number of worker threads to spawn; also the sticky-routing modulus. */numWorkers: number;
|
|
4281
|
-
/**
|
|
4282
|
-
* Factory spec the default transport's workers import to instantiate
|
|
4283
|
-
* their signature verifier. Omitted = no executor-side verification,
|
|
4284
|
-
* parity with the in-process executor's default.
|
|
4285
|
-
*/
|
|
4286
|
-
verifier?: SignatureVerifierSpec;
|
|
4287
|
-
};
|
|
4288
|
-
/**
|
|
4289
|
-
* Executor worker-pool configuration. Either `db` (default thread
|
|
4290
|
-
* transport; each worker opens its own Postgres pool) or a custom
|
|
4291
|
-
* `factory` transport is required by construction — an enabled pool
|
|
4292
|
-
* without connection info is unrepresentable.
|
|
4293
|
-
*/
|
|
4294
|
-
type WorkerPoolOptions = (WorkerPoolBase & {
|
|
4295
|
-
db: DbConfig;
|
|
4296
|
-
factory?: WorkerFactory;
|
|
4297
|
-
}) | (WorkerPoolBase & {
|
|
4298
|
-
db?: DbConfig;
|
|
4299
|
-
factory: WorkerFactory;
|
|
4300
|
-
});
|
|
4301
|
-
/**
|
|
4302
|
-
* Caller-facing config for {@link ReactorBuilder.withProjectionShards}.
|
|
4303
|
-
* When set, the builder replaces the in-process
|
|
4304
|
-
* {@link ReadModelCoordinator} with a {@link ProjectionShardManager} that
|
|
4305
|
-
* fans JOB_WRITE_READY events to N projection workers sharded by
|
|
4306
|
-
* documentId.
|
|
4307
|
-
*
|
|
4308
|
-
* @see Sharded projection workers sub-feature brief
|
|
4309
|
-
* (Powerhouse board wiki id: eb26f01f-8f68-4918-a6f6-ac7a4679b533)
|
|
4310
|
-
*/
|
|
4311
|
-
type ProjectionShardBuilderConfig = {
|
|
4312
|
-
shardCount: number;
|
|
4313
|
-
preReadyKinds: BuiltInReadModelKind[];
|
|
4314
|
-
postReadyKinds: BuiltInReadModelKind[];
|
|
4315
|
-
/**
|
|
4316
|
-
* Connection info for the projection workers' own pools. Falls back to
|
|
4317
|
-
* the executor worker pool's `db` when {@link ReactorBuilder.withWorkerPool}
|
|
4318
|
-
* is configured with one.
|
|
4319
|
-
*/
|
|
4320
|
-
db?: DbConfig;
|
|
4321
|
-
poolSize?: number;
|
|
4322
|
-
initTimeoutMs?: number;
|
|
4323
|
-
shutdownGraceMs?: number;
|
|
4324
|
-
drainTimeoutMs?: number;
|
|
4325
|
-
chainDepthReportIntervalMs?: number;
|
|
4326
|
-
};
|
|
4327
|
-
declare class ReactorBuilder {
|
|
4328
|
-
private logger?;
|
|
4329
|
-
private documentModelSources;
|
|
4330
|
-
private upgradeManifests;
|
|
4331
|
-
private features;
|
|
4332
|
-
private readModels;
|
|
4333
|
-
private readModelFactories;
|
|
4334
|
-
private executorManager;
|
|
4335
|
-
private executorConfig;
|
|
4336
|
-
private writeCacheConfig?;
|
|
4337
|
-
private migrationStrategy;
|
|
4338
|
-
private syncBuilder?;
|
|
4339
|
-
private eventBus?;
|
|
4340
|
-
private readModelCoordinator?;
|
|
4341
|
-
private signatureVerifier?;
|
|
4342
|
-
private kyselyInstance?;
|
|
4343
|
-
private signalHandlersEnabled;
|
|
4344
|
-
private queueInstance?;
|
|
4345
|
-
private channelScheme?;
|
|
4346
|
-
private jwtHandler?;
|
|
4347
|
-
private documentModelLoader?;
|
|
4348
|
-
private shutdownHooks;
|
|
4349
|
-
private driveContainerTypes;
|
|
4350
|
-
private workerPool?;
|
|
4351
|
-
private resolvedModelManifest?;
|
|
4352
|
-
private projectionShardConfig?;
|
|
4353
|
-
private projectionWorkerFactory?;
|
|
4354
|
-
private instrumentedPools;
|
|
4355
|
-
withLogger(logger: ILogger): this;
|
|
4356
|
-
/**
|
|
4357
|
-
* Register document-model sources: live modules, importable files, or
|
|
4358
|
-
* importable packages. Appends across calls. At `buildModule()` every
|
|
4359
|
-
* source is resolved host-side and registered on the registry; file and
|
|
4360
|
-
* package sources additionally form the worker manifest when the worker
|
|
4361
|
-
* pool is enabled (live modules cannot cross a thread boundary).
|
|
4362
|
-
*/
|
|
4363
|
-
withDocumentModelSources(sources: DocumentModelSource[]): this;
|
|
4364
|
-
withUpgradeManifests(manifests: UpgradeManifest<readonly number[]>[]): this;
|
|
4365
|
-
withFeatures(features: ReactorFeatures): this;
|
|
4366
|
-
withReadModel(readModel: IReadModel): this;
|
|
4367
|
-
/**
|
|
4368
|
-
* Register a factory that builds a pre-ready read model after the reactor's
|
|
4369
|
-
* internal `operationIndex`, `writeCache`, and processor-manager consistency
|
|
4370
|
-
* tracker are constructed. Use this for read models (e.g. `BaseReadModel`
|
|
4371
|
-
* subclasses) that need those dependencies and therefore cannot be built
|
|
4372
|
-
* before calling `buildModule()`.
|
|
4373
|
-
*/
|
|
4374
|
-
withReadModelFactory(factory: ReadModelFactory): this;
|
|
4375
|
-
withReadModelCoordinator(readModelCoordinator: IReadModelCoordinator): this;
|
|
4376
|
-
withExecutor(executor: IJobExecutorManager): this;
|
|
4377
|
-
withExecutorConfig(config: Partial<JobExecutorConfig>): this;
|
|
4378
|
-
withWriteCacheConfig(config: Partial<WriteCacheConfig>): this;
|
|
4379
|
-
withDriveContainerTypes(types: string[]): this;
|
|
4380
|
-
withMigrationStrategy(strategy: MigrationStrategy): this;
|
|
4381
|
-
withSync(syncBuilder: SyncBuilder): this;
|
|
4382
|
-
withEventBus(eventBus: IEventBus): this;
|
|
4383
|
-
withSignatureVerifier(verifier: SignatureVerificationHandler): this;
|
|
4384
|
-
withKysely(kysely: Kysely<Database>): this;
|
|
4385
|
-
/**
|
|
4386
|
-
* Register an externally-constructed pg.Pool's {@link PoolInstrumentation}
|
|
4387
|
-
* so it surfaces through {@link ReactorModule.pools}. Use this when the
|
|
4388
|
-
* caller built the pool itself (e.g. the in-process bench host wiring) so
|
|
4389
|
-
* pool acquire-wait and pool-stat metrics still emit. The builder also
|
|
4390
|
-
* registers any pool it constructs internally via {@link createPostgresDatabase}.
|
|
4391
|
-
*/
|
|
4392
|
-
withInstrumentedPool(instrumentation: PoolInstrumentation): this;
|
|
4393
|
-
withQueue(queue: IQueue): this;
|
|
4394
|
-
withChannelScheme(scheme: ChannelScheme): this;
|
|
4395
|
-
withJwtHandler(handler: JwtHandler): this;
|
|
4396
|
-
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4397
|
-
withSignalHandlers(): this;
|
|
4398
|
-
/**
|
|
4399
|
-
* Register an async cleanup hook to run during graceful shutdown. Hooks fire
|
|
4400
|
-
* after `reactor.kill()` resolves and before `database.destroy()`, so callers
|
|
4401
|
-
* that depend on the reactor (e.g. an HTTP API layered on top) can drain
|
|
4402
|
-
* cleanly before the underlying kysely instance is torn down. Hook errors are
|
|
4403
|
-
* logged and otherwise ignored — one bad hook cannot strand the rest of the
|
|
4404
|
-
* shutdown chain.
|
|
4405
|
-
*/
|
|
4406
|
-
withShutdownHook(hook: () => Promise<void>): this;
|
|
4407
|
-
/**
|
|
4408
|
-
* Enable the executor worker pool: N `node:worker_threads` workers with
|
|
4409
|
-
* sticky per-document routing, replacing the in-process executor. Calling
|
|
4410
|
-
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
4411
|
-
* (each worker opens its own Postgres pool; the parent database is built
|
|
4412
|
-
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
4413
|
-
* transport. `verifier` is imported by the default transport's workers;
|
|
4414
|
-
* omitted = no executor-side signature verification.
|
|
4415
|
-
*/
|
|
4416
|
-
withWorkerPool(options: WorkerPoolOptions): this;
|
|
4417
|
-
/**
|
|
4418
|
-
* Configure N sharded projection workers. When set, the builder replaces
|
|
4419
|
-
* the default in-process {@link ReadModelCoordinator} with a
|
|
4420
|
-
* {@link ProjectionShardManager}.
|
|
4421
|
-
*
|
|
4422
|
-
* Projection workers open their own Postgres pools from `config.db`,
|
|
4423
|
-
* falling back to the executor worker pool's `db` when
|
|
4424
|
-
* {@link withWorkerPool} is configured with one; only the `poolSize` is
|
|
4425
|
-
* overridden by {@link ProjectionShardBuilderConfig.poolSize}. The same
|
|
4426
|
-
* model manifest resolved from {@link withDocumentModelSources} is
|
|
4427
|
-
* forwarded.
|
|
4428
|
-
*/
|
|
4429
|
-
withProjectionShards(config: ProjectionShardBuilderConfig): this;
|
|
4430
|
-
/**
|
|
4431
|
-
* Inject a custom {@link ProjectionWorkerFactory}. When set, the builder
|
|
4432
|
-
* skips default thread-transport wiring for the projection shards and
|
|
4433
|
-
* hands the factory directly to {@link ProjectionShardManager}.
|
|
4434
|
-
*/
|
|
4435
|
-
withProjectionWorkerFactory(factory: ProjectionWorkerFactory): this;
|
|
4436
|
-
getResolvedModelManifest(): ModelManifestEntry[] | undefined;
|
|
4437
|
-
build(): Promise<IReactor>;
|
|
4438
|
-
buildModule(): Promise<InProcessReactorModule>;
|
|
4439
|
-
/**
|
|
4440
|
-
* The single Postgres config for the parent, executor workers, and
|
|
4441
|
-
* projection shards. They must share one physical database (the parent
|
|
4442
|
-
* writes operations; workers and shards read them), so divergent
|
|
4443
|
-
* worker/shard targets throw. `withKysely` overrides the parent and is not
|
|
4444
|
-
* validated against a worker/shard `db`.
|
|
4445
|
-
*/
|
|
4446
|
-
private resolveReactorDbConfig;
|
|
4447
|
-
/**
|
|
4448
|
-
* Constructs a {@link ProjectionShardManager} bound to the host event
|
|
4449
|
-
* bus. Builds the default thread-transport factory unless one was
|
|
4450
|
-
* injected via {@link withProjectionWorkerFactory}. Calls
|
|
4451
|
-
* `manager.startup()` so all N workers reach READY before the reactor
|
|
4452
|
-
* is returned to the caller.
|
|
4453
|
-
*/
|
|
4454
|
-
private createProjectionShardManager;
|
|
4455
|
-
private createDefaultProjectionWorkerFactory;
|
|
4456
|
-
/**
|
|
4457
|
-
* Default {@link WorkerFactory} used when the pool options carry no
|
|
4458
|
-
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
4459
|
-
* Worker pointing at the compiled `worker/entry.js`.
|
|
4460
|
-
*/
|
|
4461
|
-
private createDefaultWorkerFactory;
|
|
4462
|
-
/**
|
|
4463
|
-
* Builds the parent Kysely instance against a real Postgres server using
|
|
4464
|
-
* the same {@link DbConfig} the workers receive at init. Used in the
|
|
4465
|
-
* worker-pool path so the parent reactor and each worker thread share
|
|
4466
|
-
* storage; PGlite cannot be shared across threads. The constructed pool
|
|
4467
|
-
* is wrapped with {@link instrumentPgPool} and the resulting
|
|
4468
|
-
* {@link PoolInstrumentation} is pushed onto {@link instrumentedPools} so
|
|
4469
|
-
* the reactor module exposes acquire-wait and pool-stat surfaces.
|
|
4470
|
-
*/
|
|
4471
|
-
private createPostgresDatabase;
|
|
4472
|
-
private attachSignalHandlers;
|
|
4473
|
-
}
|
|
4474
|
-
//#endregion
|
|
4475
|
-
//#region src/core/reactor-client-builder.d.ts
|
|
4476
|
-
/**
|
|
4477
|
-
* Builder class for constructing ReactorClient instances with proper configuration
|
|
4478
|
-
*/
|
|
4479
|
-
declare class ReactorClientBuilder {
|
|
4480
|
-
private logger?;
|
|
4481
|
-
private reactorBuilder?;
|
|
4482
|
-
private reactor?;
|
|
4483
|
-
private eventBus?;
|
|
4484
|
-
private documentIndexer?;
|
|
4485
|
-
private documentView?;
|
|
4486
|
-
private signer?;
|
|
4487
|
-
private signatureVerifier?;
|
|
4488
|
-
private subscriptionManager?;
|
|
4489
|
-
private jobAwaiter?;
|
|
4490
|
-
private documentModelLoader?;
|
|
4491
|
-
/**
|
|
4492
|
-
* Sets the logger for the ReactorClient.
|
|
4493
|
-
* @param logger - The logger to use.
|
|
4494
|
-
* @returns The ReactorClientBuilder instance.
|
|
4495
|
-
*/
|
|
4496
|
-
withLogger(logger: ILogger): this;
|
|
4497
|
-
/**
|
|
4498
|
-
* Either this or withReactor must be set.
|
|
4499
|
-
*/
|
|
4500
|
-
withReactorBuilder(reactorBuilder: ReactorBuilder): this;
|
|
4501
|
-
/**
|
|
4502
|
-
* Either this or withReactorBuilder must be set.
|
|
4503
|
-
*/
|
|
4504
|
-
withReactor(reactor: IReactor, eventBus: IEventBus, documentIndexer: IDocumentIndexer, documentView: IDocumentView): this;
|
|
4505
|
-
/**
|
|
4506
|
-
* Sets the signer configuration for signing and verifying actions.
|
|
4507
|
-
*
|
|
4508
|
-
* @param config - Either an ISigner for signing only, or a SignerConfig for both signing and verification
|
|
4509
|
-
*/
|
|
4510
|
-
withSigner(config: ISigner | SignerConfig): this;
|
|
4511
|
-
withSubscriptionManager(subscriptionManager: IReactorSubscriptionManager): this;
|
|
4512
|
-
withJobAwaiter(jobAwaiter: IJobAwaiter): this;
|
|
4513
|
-
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4514
|
-
build(): Promise<ReactorClient>;
|
|
4515
|
-
buildModule(): Promise<InProcessReactorClientModule>;
|
|
4516
|
-
}
|
|
4517
|
-
//#endregion
|
|
4518
|
-
//#region src/core/drive-container-types.d.ts
|
|
4519
|
-
declare const DEFAULT_DRIVE_CONTAINER_TYPES: ReadonlySet<string>;
|
|
4520
|
-
//#endregion
|
|
4521
|
-
//#region src/core/reactor.d.ts
|
|
4522
|
-
/**
|
|
4523
|
-
* This class implements the IReactor interface and serves as the main entry point
|
|
4524
|
-
* for the new Reactor architecture.
|
|
4525
|
-
*/
|
|
4526
|
-
declare class Reactor implements IReactor {
|
|
4527
|
-
private logger;
|
|
4528
|
-
private documentModelRegistry;
|
|
4529
|
-
private shutdownStatus;
|
|
4530
|
-
private setShutdown;
|
|
4531
|
-
private setCompleted;
|
|
4532
|
-
private queue;
|
|
4533
|
-
private jobTracker;
|
|
4534
|
-
private readModelCoordinator;
|
|
4535
|
-
private features;
|
|
4536
|
-
private documentView;
|
|
4537
|
-
private documentIndexer;
|
|
4538
|
-
private operationStore;
|
|
4539
|
-
private eventBus;
|
|
4540
|
-
private executorManager;
|
|
4541
|
-
constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager);
|
|
4542
|
-
kill(): ShutdownStatus;
|
|
4543
|
-
getDocumentModels(namespace?: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DocumentModelModule>>;
|
|
4544
|
-
get<TDocument extends PHDocument>(id: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4545
|
-
getBySlug<TDocument extends PHDocument>(slug: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4546
|
-
getByIdOrSlug<TDocument extends PHDocument>(identifier: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4547
|
-
getOutgoingRelationships(sourceId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4548
|
-
getIncomingRelationships(targetId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4549
|
-
getOperations(documentId: string, view?: ViewFilter, filter?: OperationFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<Record<string, PagedResults<Operation>>>;
|
|
4550
|
-
find(search: SearchFilter, view?: ViewFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<PHDocument>>;
|
|
4551
|
-
create(document: PHDocument, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4552
|
-
deleteDocument(id: string, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4553
|
-
execute(docId: string, branch: string, actions: Action[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4554
|
-
load(docId: string, branch: string, operations: Operation[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4555
|
-
executeBatch(request: BatchExecutionRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchExecutionResult>;
|
|
4556
|
-
loadBatch(request: BatchLoadRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchLoadResult>;
|
|
4557
|
-
addRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4558
|
-
removeRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4559
|
-
getJobStatus(jobId: string, signal?: AbortSignal): Promise<JobInfo>;
|
|
4560
|
-
private findByIds;
|
|
4561
|
-
private findBySlugs;
|
|
4562
|
-
private findByParentId;
|
|
4563
|
-
private findByType;
|
|
4564
|
-
private emitJobPending;
|
|
4565
|
-
}
|
|
4566
|
-
//#endregion
|
|
4567
|
-
//#region src/shared/drive-url.d.ts
|
|
4568
|
-
interface ParsedDriveUrl {
|
|
4569
|
-
url: string;
|
|
4570
|
-
driveId: string;
|
|
4571
|
-
graphqlEndpoint: string;
|
|
4572
|
-
}
|
|
4573
|
-
/**
|
|
4574
|
-
* Parse a drive URL to extract drive ID and construct GraphQL endpoint.
|
|
4575
|
-
* Preserves any subpath prefix so the result is correct when the reactor is
|
|
4576
|
-
* served behind a proxy at a non-root path.
|
|
4577
|
-
* e.g., "http://localhost:4001/d/abc123" -> { driveId: "abc123", graphqlEndpoint: "http://localhost:4001/graphql/r" }
|
|
4578
|
-
* e.g., "https://example.com/api/reactor/d/abc123" -> { ..., graphqlEndpoint: "https://example.com/api/reactor/graphql/r" }
|
|
4579
|
-
*/
|
|
4580
|
-
declare function parseDriveUrl(url: string): ParsedDriveUrl;
|
|
4581
|
-
/**
|
|
4582
|
-
* Extract drive ID from a drive URL.
|
|
4583
|
-
*/
|
|
4584
|
-
declare function driveIdFromUrl(url: string): string;
|
|
4585
|
-
//#endregion
|
|
4586
|
-
//#region src/shared/factories.d.ts
|
|
4587
|
-
/**
|
|
4588
|
-
* Factory method to create a ShutdownStatus that can be updated
|
|
4589
|
-
*
|
|
4590
|
-
* @param initialState - Initial shutdown state (default: false)
|
|
4591
|
-
* @returns A tuple of [ShutdownStatus, setShutdown function, setCompleted function]
|
|
4592
|
-
*/
|
|
4593
|
-
declare function createMutableShutdownStatus(initialState?: boolean): [ShutdownStatus, (value: boolean) => void, (completed: Promise<void>) => void];
|
|
4594
|
-
//#endregion
|
|
4595
|
-
//#region src/shared/utils.d.ts
|
|
4596
|
-
type ParsedPaging = {
|
|
4597
|
-
offset: number;
|
|
4598
|
-
limit: number;
|
|
4579
|
+
*/
|
|
4580
|
+
poolInstrumentations?: ForwardingPoolInstrumentation[];
|
|
4599
4581
|
};
|
|
4600
|
-
/**
|
|
4601
|
-
* Validates PagingOptions and returns a normalized offset and limit.
|
|
4602
|
-
* Throws if the cursor is not empty and not a non-negative integer, or if
|
|
4603
|
-
* limit is less than 1. When `paging` is undefined, returns offset 0 and
|
|
4604
|
-
* the caller-supplied `defaultLimit`.
|
|
4605
|
-
*/
|
|
4606
|
-
declare function parsePagingOptions(paging: PagingOptions | undefined, defaultLimit: number): ParsedPaging;
|
|
4607
4582
|
//#endregion
|
|
4608
|
-
//#region src/
|
|
4583
|
+
//#region src/signer/types.d.ts
|
|
4609
4584
|
/**
|
|
4610
|
-
*
|
|
4611
|
-
* This ensures that errors are not silently swallowed.
|
|
4585
|
+
* Configuration for signing and verification.
|
|
4612
4586
|
*/
|
|
4613
|
-
|
|
4614
|
-
handleError(error: unknown, context: SubscriptionErrorContext): void;
|
|
4615
|
-
}
|
|
4616
|
-
//#endregion
|
|
4617
|
-
//#region src/subs/react-subscription-manager.d.ts
|
|
4618
|
-
type DocumentCreatedCallback = (result: PagedResults<string>) => void;
|
|
4619
|
-
type DocumentDeletedCallback = (documentIds: string[]) => void;
|
|
4620
|
-
type DocumentStateUpdatedCallback = (result: PagedResults<PHDocument>) => void;
|
|
4621
|
-
type RelationshipChangedCallback = (parentId: string, childId: string, changeType: RelationshipChangeType) => void;
|
|
4622
|
-
declare class ReactorSubscriptionManager implements IReactorSubscriptionManager {
|
|
4623
|
-
private createdSubscriptions;
|
|
4624
|
-
private deletedSubscriptions;
|
|
4625
|
-
private updatedSubscriptions;
|
|
4626
|
-
private relationshipSubscriptions;
|
|
4627
|
-
private subscriptionCounter;
|
|
4628
|
-
private errorHandler;
|
|
4629
|
-
constructor(errorHandler: ISubscriptionErrorHandler);
|
|
4630
|
-
onDocumentCreated(callback: DocumentCreatedCallback, search?: SearchFilter): () => void;
|
|
4631
|
-
onDocumentDeleted(callback: DocumentDeletedCallback, search?: SearchFilter): () => void;
|
|
4632
|
-
onDocumentStateUpdated(callback: DocumentStateUpdatedCallback, search?: SearchFilter, view?: ViewFilter): () => void;
|
|
4633
|
-
onRelationshipChanged(callback: RelationshipChangedCallback, search?: SearchFilter): () => void;
|
|
4634
|
-
/**
|
|
4635
|
-
* Notify subscribers about created documents
|
|
4636
|
-
*/
|
|
4637
|
-
notifyDocumentsCreated(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4638
|
-
/**
|
|
4639
|
-
* Notify subscribers about deleted documents
|
|
4640
|
-
*/
|
|
4641
|
-
notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4642
|
-
/**
|
|
4643
|
-
* Notify subscribers about updated documents
|
|
4644
|
-
*/
|
|
4645
|
-
notifyDocumentsUpdated(documents: PHDocument[]): void;
|
|
4587
|
+
type SignerConfig = {
|
|
4646
4588
|
/**
|
|
4647
|
-
*
|
|
4589
|
+
* The signer used to sign actions before submission.
|
|
4648
4590
|
*/
|
|
4649
|
-
|
|
4591
|
+
signer: ISigner;
|
|
4650
4592
|
/**
|
|
4651
|
-
*
|
|
4593
|
+
* Optional handler for verifying signatures on incoming operations.
|
|
4594
|
+
* If not provided, signature verification will be skipped.
|
|
4652
4595
|
*/
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4596
|
+
verifier?: SignatureVerificationHandler;
|
|
4597
|
+
};
|
|
4598
|
+
//#endregion
|
|
4599
|
+
//#region src/storage/migrations/types.d.ts
|
|
4600
|
+
type MigrationStrategy = "auto" | "manual" | "none";
|
|
4601
|
+
interface MigrationResult {
|
|
4602
|
+
success: boolean;
|
|
4603
|
+
migrationsExecuted: string[];
|
|
4604
|
+
error?: Error;
|
|
4657
4605
|
}
|
|
4658
4606
|
//#endregion
|
|
4659
|
-
//#region src/
|
|
4660
|
-
declare class
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4607
|
+
//#region src/sync/sync-builder.d.ts
|
|
4608
|
+
declare class SyncBuilder {
|
|
4609
|
+
private channelFactory?;
|
|
4610
|
+
private remoteStorage?;
|
|
4611
|
+
private cursorStorage?;
|
|
4612
|
+
private deadLetterStorage?;
|
|
4613
|
+
private config;
|
|
4614
|
+
withChannelFactory(factory: IChannelFactory): this;
|
|
4615
|
+
withRemoteStorage(storage: ISyncRemoteStorage): this;
|
|
4616
|
+
withCursorStorage(storage: ISyncCursorStorage): this;
|
|
4617
|
+
withDeadLetterStorage(storage: ISyncDeadLetterStorage): this;
|
|
4618
|
+
withMaxDeadLettersPerRemote(limit: number): this;
|
|
4619
|
+
withMaxInboxBatchSize(limit: number): this;
|
|
4620
|
+
build(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): ISyncManager;
|
|
4621
|
+
buildModule(reactor: IReactor, logger: ILogger, operationIndex: IOperationIndex, eventBus: IEventBus, db: Kysely<Database$1>, driveContainerTypes: ReadonlySet<string>): InProcessSyncModule;
|
|
4664
4622
|
}
|
|
4665
4623
|
//#endregion
|
|
4666
|
-
//#region src/
|
|
4624
|
+
//#region src/core/reactor-builder.d.ts
|
|
4667
4625
|
/**
|
|
4668
|
-
*
|
|
4669
|
-
*
|
|
4670
|
-
*
|
|
4671
|
-
*
|
|
4626
|
+
* Dependencies provided to read-model factories registered via
|
|
4627
|
+
* `withReadModelFactory`. These are constructed inside `buildModule()`, which
|
|
4628
|
+
* is why factory-based registration is needed for read models that depend on
|
|
4629
|
+
* them (`BaseReadModel` subclasses, in particular).
|
|
4672
4630
|
*/
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
private toErrorInfo;
|
|
4687
|
-
/**
|
|
4688
|
-
* Creates a unique key for a document/scope/branch combination
|
|
4689
|
-
*/
|
|
4690
|
-
private createQueueKey;
|
|
4691
|
-
/**
|
|
4692
|
-
* Gets or creates a queue for the given key
|
|
4693
|
-
*/
|
|
4694
|
-
private getQueue;
|
|
4695
|
-
/**
|
|
4696
|
-
* Check if a document has any jobs currently executing
|
|
4697
|
-
*/
|
|
4698
|
-
private isDocumentExecuting;
|
|
4699
|
-
/**
|
|
4700
|
-
* Mark a job as executing for its document
|
|
4701
|
-
*/
|
|
4702
|
-
private markJobExecuting;
|
|
4703
|
-
/**
|
|
4704
|
-
* Mark a job as no longer executing for its document
|
|
4705
|
-
*/
|
|
4706
|
-
private markJobComplete;
|
|
4707
|
-
/**
|
|
4708
|
-
* Check if all dependencies for a job have been completed
|
|
4709
|
-
*/
|
|
4710
|
-
private areDependenciesMet;
|
|
4711
|
-
/**
|
|
4712
|
-
* Returns the head of the sub-queue if its dependencies are met, or null.
|
|
4713
|
-
*
|
|
4714
|
-
* The dispatcher only ever considers the head — a dep-blocked head holds
|
|
4715
|
-
* the rest of its sub-queue. This preserves per-(documentId, scope, branch)
|
|
4716
|
-
* FIFO regardless of how dependencies are authored, and makes the queue's
|
|
4717
|
-
* documented "serialized per document" invariant hold even when callers
|
|
4718
|
-
* omit queueHint dependencies on jobs that share a sub-queue.
|
|
4719
|
-
*/
|
|
4720
|
-
private getNextJobWithMetDependencies;
|
|
4721
|
-
private getCreateDocumentType;
|
|
4722
|
-
enqueue(job: Job): Promise<void>;
|
|
4723
|
-
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4724
|
-
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4725
|
-
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
4726
|
-
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
4727
|
-
totalSize(): Promise<number>;
|
|
4728
|
-
remove(jobId: string): Promise<boolean>;
|
|
4729
|
-
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
4730
|
-
clearAll(): Promise<void>;
|
|
4731
|
-
hasJobs(): Promise<boolean>;
|
|
4732
|
-
completeJob(jobId: string): Promise<void>;
|
|
4733
|
-
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
4734
|
-
deferJob(jobId: string): void;
|
|
4735
|
-
retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
|
|
4631
|
+
interface ReadModelFactoryDeps {
|
|
4632
|
+
documentModelRegistry: IDocumentModelRegistry;
|
|
4633
|
+
operationIndex: IOperationIndex;
|
|
4634
|
+
writeCache: IWriteCache;
|
|
4635
|
+
processorManagerConsistencyTracker: IConsistencyTracker;
|
|
4636
|
+
}
|
|
4637
|
+
/**
|
|
4638
|
+
* Factory that builds a pre-ready read model from internal reactor
|
|
4639
|
+
* dependencies once they are available. Awaited during `buildModule()`.
|
|
4640
|
+
*/
|
|
4641
|
+
type ReadModelFactory = (deps: ReadModelFactoryDeps) => IReadModel | Promise<IReadModel>;
|
|
4642
|
+
type WorkerPoolBase = {
|
|
4643
|
+
/** Number of worker threads to spawn; also the sticky-routing modulus. */numWorkers: number;
|
|
4736
4644
|
/**
|
|
4737
|
-
*
|
|
4645
|
+
* Factory spec the default transport's workers import to instantiate
|
|
4646
|
+
* their signature verifier. Omitted = no executor-side verification,
|
|
4647
|
+
* parity with the in-process executor's default.
|
|
4738
4648
|
*/
|
|
4739
|
-
|
|
4649
|
+
verifier?: SignatureVerifierSpec;
|
|
4650
|
+
};
|
|
4651
|
+
/**
|
|
4652
|
+
* Executor worker-pool configuration. Either `db` (default thread
|
|
4653
|
+
* transport; each worker opens its own Postgres pool) or a custom
|
|
4654
|
+
* `factory` transport is required by construction — an enabled pool
|
|
4655
|
+
* without connection info is unrepresentable.
|
|
4656
|
+
*/
|
|
4657
|
+
type WorkerPoolOptions = (WorkerPoolBase & {
|
|
4658
|
+
db: DbConfig;
|
|
4659
|
+
factory?: WorkerFactory;
|
|
4660
|
+
}) | (WorkerPoolBase & {
|
|
4661
|
+
db?: DbConfig;
|
|
4662
|
+
factory: WorkerFactory;
|
|
4663
|
+
});
|
|
4664
|
+
/**
|
|
4665
|
+
* Caller-facing config for {@link ReactorBuilder.withProjectionShards}.
|
|
4666
|
+
* When set, the builder replaces the in-process
|
|
4667
|
+
* {@link ReadModelCoordinator} with a {@link ProjectionShardManager} that
|
|
4668
|
+
* fans JOB_WRITE_READY events to N projection workers sharded by
|
|
4669
|
+
* documentId.
|
|
4670
|
+
*
|
|
4671
|
+
* @see Sharded projection workers sub-feature brief
|
|
4672
|
+
* (Powerhouse board wiki id: eb26f01f-8f68-4918-a6f6-ac7a4679b533)
|
|
4673
|
+
*/
|
|
4674
|
+
type ProjectionShardBuilderConfig = {
|
|
4675
|
+
shardCount: number;
|
|
4676
|
+
preReadyKinds: BuiltInReadModelKind[];
|
|
4677
|
+
postReadyKinds: BuiltInReadModelKind[];
|
|
4740
4678
|
/**
|
|
4741
|
-
*
|
|
4679
|
+
* Connection info for the projection workers' own pools. Falls back to
|
|
4680
|
+
* the executor worker pool's `db` when {@link ReactorBuilder.withWorkerPool}
|
|
4681
|
+
* is configured with one.
|
|
4742
4682
|
*/
|
|
4743
|
-
|
|
4683
|
+
db?: DbConfig;
|
|
4684
|
+
poolSize?: number;
|
|
4685
|
+
initTimeoutMs?: number;
|
|
4686
|
+
shutdownGraceMs?: number;
|
|
4687
|
+
drainTimeoutMs?: number;
|
|
4688
|
+
chainDepthReportIntervalMs?: number;
|
|
4689
|
+
};
|
|
4690
|
+
declare class ReactorBuilder {
|
|
4691
|
+
private logger?;
|
|
4692
|
+
private documentModelSources;
|
|
4693
|
+
private upgradeManifests;
|
|
4694
|
+
private features;
|
|
4695
|
+
private readModels;
|
|
4696
|
+
private readModelFactories;
|
|
4697
|
+
private executorManager;
|
|
4698
|
+
private executorConfig;
|
|
4699
|
+
private writeCacheConfig?;
|
|
4700
|
+
private migrationStrategy;
|
|
4701
|
+
private syncBuilder?;
|
|
4702
|
+
private eventBus?;
|
|
4703
|
+
private readModelCoordinator?;
|
|
4704
|
+
private signatureVerifier?;
|
|
4705
|
+
private kyselyInstance?;
|
|
4706
|
+
private signalHandlersEnabled;
|
|
4707
|
+
private queueInstance?;
|
|
4708
|
+
private channelScheme?;
|
|
4709
|
+
private jwtHandler?;
|
|
4710
|
+
private documentModelLoader?;
|
|
4711
|
+
private shutdownHooks;
|
|
4712
|
+
private driveContainerTypes;
|
|
4713
|
+
private workerPool?;
|
|
4714
|
+
private resolvedModelManifest?;
|
|
4715
|
+
private projectionShardConfig?;
|
|
4716
|
+
private projectionWorkerFactory?;
|
|
4717
|
+
private instrumentedPools;
|
|
4718
|
+
withLogger(logger: ILogger): this;
|
|
4744
4719
|
/**
|
|
4745
|
-
*
|
|
4746
|
-
*
|
|
4720
|
+
* Register document-model sources: live modules, importable files, or
|
|
4721
|
+
* importable packages. Appends across calls. At `buildModule()` every
|
|
4722
|
+
* source is resolved host-side and registered on the registry; file and
|
|
4723
|
+
* package sources additionally form the worker manifest when the worker
|
|
4724
|
+
* pool is enabled (live modules cannot cross a thread boundary).
|
|
4747
4725
|
*/
|
|
4748
|
-
|
|
4726
|
+
withDocumentModelSources(sources: DocumentModelSource[]): this;
|
|
4727
|
+
withUpgradeManifests(manifests: UpgradeManifest<readonly number[]>[]): this;
|
|
4728
|
+
withFeatures(features: ReactorFeatures): this;
|
|
4729
|
+
withReadModel(readModel: IReadModel): this;
|
|
4749
4730
|
/**
|
|
4750
|
-
*
|
|
4731
|
+
* Register a factory that builds a pre-ready read model after the reactor's
|
|
4732
|
+
* internal `operationIndex`, `writeCache`, and processor-manager consistency
|
|
4733
|
+
* tracker are constructed. Use this for read models (e.g. `BaseReadModel`
|
|
4734
|
+
* subclasses) that need those dependencies and therefore cannot be built
|
|
4735
|
+
* before calling `buildModule()`.
|
|
4751
4736
|
*/
|
|
4752
|
-
|
|
4737
|
+
withReadModelFactory(factory: ReadModelFactory): this;
|
|
4738
|
+
withReadModelCoordinator(readModelCoordinator: IReadModelCoordinator): this;
|
|
4739
|
+
withExecutor(executor: IJobExecutorManager): this;
|
|
4740
|
+
withExecutorConfig(config: Partial<JobExecutorConfig>): this;
|
|
4741
|
+
withWriteCacheConfig(config: Partial<WriteCacheConfig>): this;
|
|
4742
|
+
withDriveContainerTypes(types: string[]): this;
|
|
4743
|
+
withMigrationStrategy(strategy: MigrationStrategy): this;
|
|
4744
|
+
withSync(syncBuilder: SyncBuilder): this;
|
|
4745
|
+
withEventBus(eventBus: IEventBus): this;
|
|
4746
|
+
withSignatureVerifier(verifier: SignatureVerificationHandler): this;
|
|
4747
|
+
withKysely(kysely: Kysely<Database>): this;
|
|
4753
4748
|
/**
|
|
4754
|
-
*
|
|
4749
|
+
* Register an externally-constructed pg.Pool's {@link PoolInstrumentation}
|
|
4750
|
+
* so it surfaces through {@link ReactorModule.pools}. Use this when the
|
|
4751
|
+
* caller built the pool itself (e.g. the in-process bench host wiring) so
|
|
4752
|
+
* pool acquire-wait and pool-stat metrics still emit. The builder also
|
|
4753
|
+
* registers any pool it constructs internally via {@link createPostgresDatabase}.
|
|
4755
4754
|
*/
|
|
4756
|
-
|
|
4755
|
+
withInstrumentedPool(instrumentation: PoolInstrumentation): this;
|
|
4756
|
+
withQueue(queue: IQueue): this;
|
|
4757
|
+
withChannelScheme(scheme: ChannelScheme): this;
|
|
4758
|
+
withJwtHandler(handler: JwtHandler): this;
|
|
4759
|
+
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4760
|
+
withSignalHandlers(): this;
|
|
4757
4761
|
/**
|
|
4758
|
-
*
|
|
4762
|
+
* Register an async cleanup hook to run during graceful shutdown. Hooks fire
|
|
4763
|
+
* after `reactor.kill()` resolves and before `database.destroy()`, so callers
|
|
4764
|
+
* that depend on the reactor (e.g. an HTTP API layered on top) can drain
|
|
4765
|
+
* cleanly before the underlying kysely instance is torn down. Hook errors are
|
|
4766
|
+
* logged and otherwise ignored — one bad hook cannot strand the rest of the
|
|
4767
|
+
* shutdown chain.
|
|
4759
4768
|
*/
|
|
4760
|
-
|
|
4769
|
+
withShutdownHook(hook: () => Promise<void>): this;
|
|
4761
4770
|
/**
|
|
4762
|
-
*
|
|
4771
|
+
* Enable the executor worker pool: N `node:worker_threads` workers with
|
|
4772
|
+
* sticky per-document routing, replacing the in-process executor. Calling
|
|
4773
|
+
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
4774
|
+
* (each worker opens its own Postgres pool; the parent database is built
|
|
4775
|
+
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
4776
|
+
* transport. `verifier` is imported by the default transport's workers;
|
|
4777
|
+
* omitted = no executor-side signature verification.
|
|
4763
4778
|
*/
|
|
4764
|
-
|
|
4779
|
+
withWorkerPool(options: WorkerPoolOptions): this;
|
|
4765
4780
|
/**
|
|
4766
|
-
*
|
|
4781
|
+
* Configure N sharded projection workers. When set, the builder replaces
|
|
4782
|
+
* the default in-process {@link ReadModelCoordinator} with a
|
|
4783
|
+
* {@link ProjectionShardManager}.
|
|
4784
|
+
*
|
|
4785
|
+
* Projection workers open their own Postgres pools from `config.db`,
|
|
4786
|
+
* falling back to the executor worker pool's `db` when
|
|
4787
|
+
* {@link withWorkerPool} is configured with one; only the `poolSize` is
|
|
4788
|
+
* overridden by {@link ProjectionShardBuilderConfig.poolSize}. The same
|
|
4789
|
+
* model manifest resolved from {@link withDocumentModelSources} is
|
|
4790
|
+
* forwarded.
|
|
4767
4791
|
*/
|
|
4768
|
-
|
|
4792
|
+
withProjectionShards(config: ProjectionShardBuilderConfig): this;
|
|
4769
4793
|
/**
|
|
4770
|
-
*
|
|
4794
|
+
* Inject a custom {@link ProjectionWorkerFactory}. When set, the builder
|
|
4795
|
+
* skips default thread-transport wiring for the projection shards and
|
|
4796
|
+
* hands the factory directly to {@link ProjectionShardManager}.
|
|
4771
4797
|
*/
|
|
4772
|
-
|
|
4798
|
+
withProjectionWorkerFactory(factory: ProjectionWorkerFactory): this;
|
|
4799
|
+
getResolvedModelManifest(): ModelManifestEntry[] | undefined;
|
|
4800
|
+
build(): Promise<IReactor>;
|
|
4801
|
+
buildModule(): Promise<InProcessReactorModule>;
|
|
4773
4802
|
/**
|
|
4774
|
-
*
|
|
4803
|
+
* The single Postgres config for the parent, executor workers, and
|
|
4804
|
+
* projection shards. They must share one physical database (the parent
|
|
4805
|
+
* writes operations; workers and shards read them), so divergent
|
|
4806
|
+
* worker/shard targets throw. `withKysely` overrides the parent and is not
|
|
4807
|
+
* validated against a worker/shard `db`.
|
|
4775
4808
|
*/
|
|
4776
|
-
|
|
4777
|
-
}
|
|
4778
|
-
//#endregion
|
|
4779
|
-
//#region src/job-tracker/in-memory-job-tracker.d.ts
|
|
4780
|
-
/**
|
|
4781
|
-
* In-memory implementation of IJobTracker.
|
|
4782
|
-
* Maintains job status in a Map for synchronous access.
|
|
4783
|
-
* Subscribes to operation events to update job states.
|
|
4784
|
-
*/
|
|
4785
|
-
declare class InMemoryJobTracker implements IJobTracker {
|
|
4786
|
-
private eventBus;
|
|
4787
|
-
private jobs;
|
|
4788
|
-
private unsubscribers;
|
|
4789
|
-
constructor(eventBus: IEventBus);
|
|
4790
|
-
private subscribeToEvents;
|
|
4791
|
-
private handleWriteReady;
|
|
4792
|
-
private handleReadReady;
|
|
4793
|
-
private handleJobFailed;
|
|
4794
|
-
shutdown(): void;
|
|
4795
|
-
registerJob(jobInfo: JobInfo): void;
|
|
4796
|
-
markRunning(jobId: string): void;
|
|
4797
|
-
markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
|
|
4798
|
-
getJobStatus(jobId: string): JobInfo | null;
|
|
4799
|
-
}
|
|
4800
|
-
//#endregion
|
|
4801
|
-
//#region src/executor/simple-job-executor-manager.d.ts
|
|
4802
|
-
type JobExecutorFactory = () => IJobExecutor;
|
|
4803
|
-
/**
|
|
4804
|
-
* Manages multiple job executors and coordinates job distribution.
|
|
4805
|
-
* Listens for job available events and dispatches jobs to executors.
|
|
4806
|
-
*/
|
|
4807
|
-
declare class SimpleJobExecutorManager implements IJobExecutorManager {
|
|
4808
|
-
private executorFactory;
|
|
4809
|
-
private eventBus;
|
|
4810
|
-
private queue;
|
|
4811
|
-
private jobTracker;
|
|
4812
|
-
private logger;
|
|
4813
|
-
private resolver;
|
|
4814
|
-
private executors;
|
|
4815
|
-
private isRunning;
|
|
4816
|
-
private activeJobs;
|
|
4817
|
-
private totalJobsProcessed;
|
|
4818
|
-
private unsubscribe?;
|
|
4819
|
-
private deferredJobs;
|
|
4820
|
-
private resultHandler;
|
|
4821
|
-
private jobTimeoutMs;
|
|
4822
|
-
constructor(executorFactory: JobExecutorFactory, eventBus: IEventBus, queue: IQueue, jobTracker: IJobTracker, logger: ILogger, resolver: IDocumentModelResolver, jobTimeoutMs?: number);
|
|
4823
|
-
start(numExecutors: number): Promise<void>;
|
|
4824
|
-
stop(graceful?: boolean): Promise<void>;
|
|
4825
|
-
getExecutors(): IJobExecutor[];
|
|
4826
|
-
getStatus(): ExecutorManagerStatus;
|
|
4827
|
-
private processNextJob;
|
|
4828
|
-
private checkForMoreJobs;
|
|
4829
|
-
private processExistingJobs;
|
|
4830
|
-
private flushDeferredJobs;
|
|
4831
|
-
}
|
|
4832
|
-
//#endregion
|
|
4833
|
-
//#region src/cache/document-meta-cache-types.d.ts
|
|
4834
|
-
/**
|
|
4835
|
-
* Cached document metadata from the "document" scope.
|
|
4836
|
-
*
|
|
4837
|
-
* This lightweight structure holds essential document information needed by
|
|
4838
|
-
* the job executor without fetching full scope state. It provides an explicit
|
|
4839
|
-
* cross-scope contract for accessing document scope metadata.
|
|
4840
|
-
*/
|
|
4841
|
-
type CachedDocumentMeta = {
|
|
4809
|
+
private resolveReactorDbConfig;
|
|
4842
4810
|
/**
|
|
4843
|
-
*
|
|
4844
|
-
*
|
|
4811
|
+
* Constructs a {@link ProjectionShardManager} bound to the host event
|
|
4812
|
+
* bus. Builds the default thread-transport factory unless one was
|
|
4813
|
+
* injected via {@link withProjectionWorkerFactory}. Calls
|
|
4814
|
+
* `manager.startup()` so all N workers reach READY before the reactor
|
|
4815
|
+
* is returned to the caller.
|
|
4845
4816
|
*/
|
|
4846
|
-
|
|
4817
|
+
private createProjectionShardManager;
|
|
4818
|
+
private createDefaultProjectionWorkerFactory;
|
|
4847
4819
|
/**
|
|
4848
|
-
*
|
|
4820
|
+
* Default {@link WorkerFactory} used when the pool options carry no
|
|
4821
|
+
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
4822
|
+
* Worker pointing at the compiled `worker/entry.js`.
|
|
4849
4823
|
*/
|
|
4850
|
-
|
|
4824
|
+
private createDefaultWorkerFactory;
|
|
4851
4825
|
/**
|
|
4852
|
-
*
|
|
4853
|
-
*
|
|
4826
|
+
* Builds the parent Kysely instance against a real Postgres server using
|
|
4827
|
+
* the same {@link DbConfig} the workers receive at init. Used in the
|
|
4828
|
+
* worker-pool path so the parent reactor and each worker thread share
|
|
4829
|
+
* storage; PGlite cannot be shared across threads. The constructed pool
|
|
4830
|
+
* is wrapped with {@link instrumentPgPool} and the resulting
|
|
4831
|
+
* {@link PoolInstrumentation} is pushed onto {@link instrumentedPools} so
|
|
4832
|
+
* the reactor module exposes acquire-wait and pool-stat surfaces.
|
|
4854
4833
|
*/
|
|
4855
|
-
|
|
4856
|
-
|
|
4834
|
+
private createPostgresDatabase;
|
|
4835
|
+
private attachSignalHandlers;
|
|
4836
|
+
}
|
|
4837
|
+
//#endregion
|
|
4838
|
+
//#region src/core/reactor-client-builder.d.ts
|
|
4857
4839
|
/**
|
|
4858
|
-
*
|
|
4859
|
-
*
|
|
4860
|
-
* This cache provides an explicit cross-scope contract for accessing document
|
|
4861
|
-
* scope metadata. It solves the problem where job execution in one scope (e.g.,
|
|
4862
|
-
* "global") needs access to document scope state (version, isDeleted, etc.)
|
|
4863
|
-
* which may be stale in scope-specific caches or keyframes.
|
|
4864
|
-
*
|
|
4865
|
-
* The cache supports:
|
|
4866
|
-
* - Latest metadata retrieval with LRU caching
|
|
4867
|
-
* - Historical metadata reconstruction for reshuffling scenarios
|
|
4868
|
-
* - Eager updates after document scope operations
|
|
4840
|
+
* Builder class for constructing ReactorClient instances with proper configuration
|
|
4869
4841
|
*/
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
* @throws {Error} "Operation aborted" if signal is aborted
|
|
4883
|
-
* @throws {Error} If document not found (no CREATE_DOCUMENT operation)
|
|
4884
|
-
*/
|
|
4885
|
-
getDocumentMeta(documentId: string, branch: string, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
4886
|
-
/**
|
|
4887
|
-
* Rebuilds document metadata at a SPECIFIC revision (always rebuilds, no caching).
|
|
4888
|
-
*
|
|
4889
|
-
* Used during reshuffling when operations need to be inserted at a previous
|
|
4890
|
-
* revision and we need the document scope state as of that point in time.
|
|
4891
|
-
*
|
|
4892
|
-
* @param documentId - The document identifier
|
|
4893
|
-
* @param branch - Branch name
|
|
4894
|
-
* @param targetRevision - The document scope revision to reconstruct up to
|
|
4895
|
-
* @param signal - Optional abort signal to cancel the operation
|
|
4896
|
-
* @returns Document metadata as of the target revision
|
|
4897
|
-
* @throws {Error} "Operation aborted" if signal is aborted
|
|
4898
|
-
* @throws {Error} If document not found
|
|
4899
|
-
*/
|
|
4900
|
-
rebuildAtRevision(documentId: string, branch: string, targetRevision: number, signal?: AbortSignal): Promise<CachedDocumentMeta>;
|
|
4901
|
-
/**
|
|
4902
|
-
* Eagerly updates cached metadata after document scope operations.
|
|
4903
|
-
*
|
|
4904
|
-
* Called by the job executor after CREATE_DOCUMENT, UPGRADE_DOCUMENT, or
|
|
4905
|
-
* DELETE_DOCUMENT operations to keep the cache current.
|
|
4906
|
-
*
|
|
4907
|
-
* @param documentId - The document identifier
|
|
4908
|
-
* @param branch - Branch name
|
|
4909
|
-
* @param meta - The new metadata to cache
|
|
4910
|
-
*/
|
|
4911
|
-
putDocumentMeta(documentId: string, branch: string, meta: CachedDocumentMeta): void;
|
|
4842
|
+
declare class ReactorClientBuilder {
|
|
4843
|
+
private logger?;
|
|
4844
|
+
private reactorBuilder?;
|
|
4845
|
+
private reactor?;
|
|
4846
|
+
private eventBus?;
|
|
4847
|
+
private documentIndexer?;
|
|
4848
|
+
private documentView?;
|
|
4849
|
+
private signer?;
|
|
4850
|
+
private signatureVerifier?;
|
|
4851
|
+
private subscriptionManager?;
|
|
4852
|
+
private jobAwaiter?;
|
|
4853
|
+
private documentModelLoader?;
|
|
4912
4854
|
/**
|
|
4913
|
-
*
|
|
4914
|
-
*
|
|
4915
|
-
*
|
|
4916
|
-
* when document state may have changed externally.
|
|
4917
|
-
*
|
|
4918
|
-
* @param documentId - The document identifier
|
|
4919
|
-
* @param branch - Optional branch to narrow invalidation (if omitted, all branches)
|
|
4920
|
-
* @returns Number of entries invalidated
|
|
4855
|
+
* Sets the logger for the ReactorClient.
|
|
4856
|
+
* @param logger - The logger to use.
|
|
4857
|
+
* @returns The ReactorClientBuilder instance.
|
|
4921
4858
|
*/
|
|
4922
|
-
|
|
4859
|
+
withLogger(logger: ILogger): this;
|
|
4923
4860
|
/**
|
|
4924
|
-
*
|
|
4861
|
+
* Either this or withReactor must be set.
|
|
4925
4862
|
*/
|
|
4926
|
-
|
|
4863
|
+
withReactorBuilder(reactorBuilder: ReactorBuilder): this;
|
|
4927
4864
|
/**
|
|
4928
|
-
*
|
|
4865
|
+
* Either this or withReactorBuilder must be set.
|
|
4929
4866
|
*/
|
|
4930
|
-
|
|
4867
|
+
withReactor(reactor: IReactor, eventBus: IEventBus, documentIndexer: IDocumentIndexer, documentView: IDocumentView): this;
|
|
4931
4868
|
/**
|
|
4932
|
-
*
|
|
4869
|
+
* Sets the signer configuration for signing and verifying actions.
|
|
4870
|
+
*
|
|
4871
|
+
* @param config - Either an ISigner for signing only, or a SignerConfig for both signing and verification
|
|
4933
4872
|
*/
|
|
4934
|
-
|
|
4873
|
+
withSigner(config: ISigner | SignerConfig): this;
|
|
4874
|
+
withSubscriptionManager(subscriptionManager: IReactorSubscriptionManager): this;
|
|
4875
|
+
withJobAwaiter(jobAwaiter: IJobAwaiter): this;
|
|
4876
|
+
withDocumentModelLoader(loader: IDocumentModelLoader): this;
|
|
4877
|
+
build(): Promise<ReactorClient>;
|
|
4878
|
+
buildModule(): Promise<InProcessReactorClientModule>;
|
|
4935
4879
|
}
|
|
4936
4880
|
//#endregion
|
|
4937
|
-
//#region src/
|
|
4881
|
+
//#region src/core/drive-container-types.d.ts
|
|
4882
|
+
declare const DEFAULT_DRIVE_CONTAINER_TYPES: ReadonlySet<string>;
|
|
4883
|
+
//#endregion
|
|
4884
|
+
//#region src/core/reactor.d.ts
|
|
4938
4885
|
/**
|
|
4939
|
-
*
|
|
4940
|
-
*
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4886
|
+
* This class implements the IReactor interface and serves as the main entry point
|
|
4887
|
+
* for the new Reactor architecture.
|
|
4888
|
+
*/
|
|
4889
|
+
declare class Reactor implements IReactor {
|
|
4890
|
+
private logger;
|
|
4891
|
+
private documentModelRegistry;
|
|
4892
|
+
private shutdownStatus;
|
|
4893
|
+
private setShutdown;
|
|
4894
|
+
private setCompleted;
|
|
4895
|
+
private queue;
|
|
4896
|
+
private jobTracker;
|
|
4897
|
+
private readModelCoordinator;
|
|
4898
|
+
private features;
|
|
4899
|
+
private documentView;
|
|
4900
|
+
private documentIndexer;
|
|
4901
|
+
private operationStore;
|
|
4902
|
+
private eventBus;
|
|
4903
|
+
private executorManager;
|
|
4904
|
+
constructor(logger: ILogger, documentModelRegistry: IDocumentModelRegistry, queue: IQueue, jobTracker: IJobTracker, readModelCoordinator: IReadModelCoordinator, features: ReactorFeatures, documentView: IDocumentView, documentIndexer: IDocumentIndexer, operationStore: IOperationStore, eventBus: IEventBus, executorManager: IJobExecutorManager);
|
|
4905
|
+
kill(): ShutdownStatus;
|
|
4906
|
+
getDocumentModels(namespace?: string, paging?: PagingOptions, signal?: AbortSignal): Promise<PagedResults<DocumentModelModule>>;
|
|
4907
|
+
get<TDocument extends PHDocument>(id: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4908
|
+
getBySlug<TDocument extends PHDocument>(slug: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4909
|
+
getByIdOrSlug<TDocument extends PHDocument>(identifier: string, view?: ViewFilter, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
4910
|
+
getOutgoingRelationships(sourceId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4911
|
+
getIncomingRelationships(targetId: string, relationshipType: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
4912
|
+
getOperations(documentId: string, view?: ViewFilter, filter?: OperationFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<Record<string, PagedResults<Operation>>>;
|
|
4913
|
+
find(search: SearchFilter, view?: ViewFilter, paging?: PagingOptions, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<PagedResults<PHDocument>>;
|
|
4914
|
+
create(document: PHDocument, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4915
|
+
deleteDocument(id: string, signer?: ISigner, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4916
|
+
execute(docId: string, branch: string, actions: Action[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4917
|
+
load(docId: string, branch: string, operations: Operation[], signal?: AbortSignal, meta?: Record<string, unknown>): Promise<JobInfo>;
|
|
4918
|
+
executeBatch(request: BatchExecutionRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchExecutionResult>;
|
|
4919
|
+
loadBatch(request: BatchLoadRequest, signal?: AbortSignal, meta?: Record<string, unknown>): Promise<BatchLoadResult>;
|
|
4920
|
+
addRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4921
|
+
removeRelationship(sourceId: string, targetId: string, relationshipType: string, branch?: string, signer?: ISigner, signal?: AbortSignal): Promise<JobInfo>;
|
|
4922
|
+
getJobStatus(jobId: string, signal?: AbortSignal): Promise<JobInfo>;
|
|
4923
|
+
private findByIds;
|
|
4924
|
+
private findBySlugs;
|
|
4925
|
+
private findByParentId;
|
|
4926
|
+
private findByType;
|
|
4927
|
+
private emitJobPending;
|
|
4928
|
+
}
|
|
4929
|
+
//#endregion
|
|
4930
|
+
//#region src/shared/drive-url.d.ts
|
|
4931
|
+
interface ParsedDriveUrl {
|
|
4932
|
+
url: string;
|
|
4933
|
+
driveId: string;
|
|
4934
|
+
graphqlEndpoint: string;
|
|
4935
|
+
}
|
|
4936
|
+
/**
|
|
4937
|
+
* Parse a drive URL to extract drive ID and construct GraphQL endpoint.
|
|
4938
|
+
* Preserves any subpath prefix so the result is correct when the reactor is
|
|
4939
|
+
* served behind a proxy at a non-root path.
|
|
4940
|
+
* e.g., "http://localhost:4001/d/abc123" -> { driveId: "abc123", graphqlEndpoint: "http://localhost:4001/graphql/r" }
|
|
4941
|
+
* e.g., "https://example.com/api/reactor/d/abc123" -> { ..., graphqlEndpoint: "https://example.com/api/reactor/graphql/r" }
|
|
4942
|
+
*/
|
|
4943
|
+
declare function parseDriveUrl(url: string): ParsedDriveUrl;
|
|
4944
|
+
/**
|
|
4945
|
+
* Extract drive ID from a drive URL.
|
|
4946
|
+
*/
|
|
4947
|
+
declare function driveIdFromUrl(url: string): string;
|
|
4948
|
+
//#endregion
|
|
4949
|
+
//#region src/shared/factories.d.ts
|
|
4950
|
+
/**
|
|
4951
|
+
* Factory method to create a ShutdownStatus that can be updated
|
|
4944
4952
|
*
|
|
4945
|
-
* @
|
|
4953
|
+
* @param initialState - Initial shutdown state (default: false)
|
|
4954
|
+
* @returns A tuple of [ShutdownStatus, setShutdown function, setCompleted function]
|
|
4946
4955
|
*/
|
|
4947
|
-
declare
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4956
|
+
declare function createMutableShutdownStatus(initialState?: boolean): [ShutdownStatus, (value: boolean) => void, (completed: Promise<void>) => void];
|
|
4957
|
+
//#endregion
|
|
4958
|
+
//#region src/shared/utils.d.ts
|
|
4959
|
+
type ParsedPaging = {
|
|
4960
|
+
offset: number;
|
|
4961
|
+
limit: number;
|
|
4962
|
+
};
|
|
4963
|
+
/**
|
|
4964
|
+
* Validates PagingOptions and returns a normalized offset and limit.
|
|
4965
|
+
* Throws if the cursor is not empty and not a non-negative integer, or if
|
|
4966
|
+
* limit is less than 1. When `paging` is undefined, returns offset 0 and
|
|
4967
|
+
* the caller-supplied `defaultLimit`.
|
|
4968
|
+
*/
|
|
4969
|
+
declare function parsePagingOptions(paging: PagingOptions | undefined, defaultLimit: number): ParsedPaging;
|
|
4970
|
+
//#endregion
|
|
4971
|
+
//#region src/subs/default-error-handler.d.ts
|
|
4972
|
+
/**
|
|
4973
|
+
* Default error handler that re-throws subscription errors.
|
|
4974
|
+
* This ensures that errors are not silently swallowed.
|
|
4975
|
+
*/
|
|
4976
|
+
declare class DefaultSubscriptionErrorHandler implements ISubscriptionErrorHandler {
|
|
4977
|
+
handleError(error: unknown, context: SubscriptionErrorContext): void;
|
|
4978
|
+
}
|
|
4979
|
+
//#endregion
|
|
4980
|
+
//#region src/subs/react-subscription-manager.d.ts
|
|
4981
|
+
type DocumentCreatedCallback = (result: PagedResults<string>) => void;
|
|
4982
|
+
type DocumentDeletedCallback = (documentIds: string[]) => void;
|
|
4983
|
+
type DocumentStateUpdatedCallback = (result: PagedResults<PHDocument>) => void;
|
|
4984
|
+
type RelationshipChangedCallback = (parentId: string, childId: string, changeType: RelationshipChangeType) => void;
|
|
4985
|
+
declare class ReactorSubscriptionManager implements IReactorSubscriptionManager {
|
|
4986
|
+
private createdSubscriptions;
|
|
4987
|
+
private deletedSubscriptions;
|
|
4988
|
+
private updatedSubscriptions;
|
|
4989
|
+
private relationshipSubscriptions;
|
|
4990
|
+
private subscriptionCounter;
|
|
4991
|
+
private errorHandler;
|
|
4992
|
+
constructor(errorHandler: ISubscriptionErrorHandler);
|
|
4993
|
+
onDocumentCreated(callback: DocumentCreatedCallback, search?: SearchFilter): () => void;
|
|
4994
|
+
onDocumentDeleted(callback: DocumentDeletedCallback, search?: SearchFilter): () => void;
|
|
4995
|
+
onDocumentStateUpdated(callback: DocumentStateUpdatedCallback, search?: SearchFilter, view?: ViewFilter): () => void;
|
|
4996
|
+
onRelationshipChanged(callback: RelationshipChangedCallback, search?: SearchFilter): () => void;
|
|
4953
4997
|
/**
|
|
4954
|
-
*
|
|
4955
|
-
*
|
|
4956
|
-
* @param item - The item to add
|
|
4998
|
+
* Notify subscribers about created documents
|
|
4957
4999
|
*/
|
|
4958
|
-
|
|
5000
|
+
notifyDocumentsCreated(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4959
5001
|
/**
|
|
4960
|
-
*
|
|
4961
|
-
*
|
|
4962
|
-
* @returns Array of items in insertion order
|
|
5002
|
+
* Notify subscribers about deleted documents
|
|
4963
5003
|
*/
|
|
4964
|
-
|
|
5004
|
+
notifyDocumentsDeleted(documentIds: string[], documentTypes?: Map<string, string>, parentIds?: Map<string, string | null>): void;
|
|
4965
5005
|
/**
|
|
4966
|
-
*
|
|
5006
|
+
* Notify subscribers about updated documents
|
|
4967
5007
|
*/
|
|
4968
|
-
|
|
5008
|
+
notifyDocumentsUpdated(documents: PHDocument[]): void;
|
|
4969
5009
|
/**
|
|
4970
|
-
*
|
|
5010
|
+
* Notify subscribers about relationship changes
|
|
4971
5011
|
*/
|
|
4972
|
-
|
|
5012
|
+
notifyRelationshipChanged(parentId: string, childId: string, changeType: RelationshipChangeType, childType?: string): void;
|
|
5013
|
+
/**
|
|
5014
|
+
* Clear all subscriptions
|
|
5015
|
+
*/
|
|
5016
|
+
clearAll(): void;
|
|
5017
|
+
private filterDocumentIds;
|
|
5018
|
+
private filterDocuments;
|
|
5019
|
+
private matchesRelationshipFilter;
|
|
4973
5020
|
}
|
|
4974
5021
|
//#endregion
|
|
4975
|
-
//#region src/
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
5022
|
+
//#region src/events/event-bus.d.ts
|
|
5023
|
+
declare class EventBus implements IEventBus {
|
|
5024
|
+
readonly eventTypeToSubscribers: Map<number, Subscriber[]>;
|
|
5025
|
+
subscribe<K>(type: number, subscriber: (type: number, event: K) => void | Promise<void>): Unsubscribe;
|
|
5026
|
+
emit(type: number, data: any): Promise<void>;
|
|
5027
|
+
}
|
|
5028
|
+
//#endregion
|
|
5029
|
+
//#region src/queue/queue.d.ts
|
|
4980
5030
|
/**
|
|
4981
|
-
* In-memory
|
|
4982
|
-
*
|
|
4983
|
-
*
|
|
4984
|
-
*
|
|
4985
|
-
*
|
|
4986
|
-
* **Performance Characteristics:**
|
|
4987
|
-
* - Cache hit: O(1) lookup in ring buffer
|
|
4988
|
-
* - Cold miss: O(n) where n is total operation count, or O(k) where k is operations since keyframe
|
|
4989
|
-
* - Warm miss: O(m) where m is operations since cached revision
|
|
4990
|
-
* - Eviction: O(1) for LRU tracking and removal
|
|
4991
|
-
*
|
|
4992
|
-
* **Thread Safety:**
|
|
4993
|
-
* Not thread-safe. Designed for single-threaded job executor environment.
|
|
4994
|
-
* External synchronization required for concurrent access across multiple executors.
|
|
4995
|
-
*
|
|
4996
|
-
* **Example:**
|
|
4997
|
-
* ```typescript
|
|
4998
|
-
* const cache = new KyselyWriteCache(
|
|
4999
|
-
* keyframeStore,
|
|
5000
|
-
* operationStore,
|
|
5001
|
-
* registry,
|
|
5002
|
-
* { maxDocuments: 1000, ringBufferSize: 10, keyframeInterval: 10 }
|
|
5003
|
-
* );
|
|
5004
|
-
*
|
|
5005
|
-
* await cache.startup();
|
|
5006
|
-
*
|
|
5007
|
-
* // Retrieve or rebuild document
|
|
5008
|
-
* const doc = await cache.getState(docId, docType, scope, branch, revision);
|
|
5009
|
-
*
|
|
5010
|
-
* // Cache result after job execution
|
|
5011
|
-
* cache.putState(docId, docType, scope, branch, newRevision, updatedDoc);
|
|
5012
|
-
*
|
|
5013
|
-
* await cache.shutdown();
|
|
5014
|
-
* ```
|
|
5031
|
+
* In-memory implementation of the IQueue interface.
|
|
5032
|
+
* Organizes jobs by documentId, scope, and branch to ensure proper ordering.
|
|
5033
|
+
* Ensures serial execution per document by tracking executing jobs.
|
|
5034
|
+
* Implements dependency management through queue hints.
|
|
5015
5035
|
*/
|
|
5016
|
-
declare class
|
|
5017
|
-
private
|
|
5018
|
-
private
|
|
5019
|
-
private
|
|
5020
|
-
private
|
|
5021
|
-
private
|
|
5022
|
-
private
|
|
5023
|
-
|
|
5024
|
-
|
|
5036
|
+
declare class InMemoryQueue implements IQueue {
|
|
5037
|
+
private eventBus;
|
|
5038
|
+
private resolver;
|
|
5039
|
+
private queues;
|
|
5040
|
+
private jobIdToQueueKey;
|
|
5041
|
+
private docIdToJobId;
|
|
5042
|
+
private jobIdToDocId;
|
|
5043
|
+
private completedJobs;
|
|
5044
|
+
private jobIndex;
|
|
5045
|
+
private isBlocked;
|
|
5046
|
+
private onDrainedCallback?;
|
|
5047
|
+
private isPausedFlag;
|
|
5048
|
+
constructor(eventBus: IEventBus, resolver: IDocumentModelResolver);
|
|
5049
|
+
private toErrorInfo;
|
|
5050
|
+
/**
|
|
5051
|
+
* Creates a unique key for a document/scope/branch combination
|
|
5052
|
+
*/
|
|
5053
|
+
private createQueueKey;
|
|
5054
|
+
/**
|
|
5055
|
+
* Gets or creates a queue for the given key
|
|
5056
|
+
*/
|
|
5057
|
+
private getQueue;
|
|
5025
5058
|
/**
|
|
5026
|
-
*
|
|
5027
|
-
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
5059
|
+
* Check if a document has any jobs currently executing
|
|
5028
5060
|
*/
|
|
5029
|
-
|
|
5061
|
+
private isDocumentExecuting;
|
|
5030
5062
|
/**
|
|
5031
|
-
*
|
|
5032
|
-
* Currently a no-op as keyframe store lifecycle is managed externally.
|
|
5063
|
+
* Mark a job as executing for its document
|
|
5033
5064
|
*/
|
|
5034
|
-
|
|
5065
|
+
private markJobExecuting;
|
|
5035
5066
|
/**
|
|
5036
|
-
*
|
|
5037
|
-
*
|
|
5038
|
-
* Note: this returns a _shallow_ copy of the document.
|
|
5039
|
-
*
|
|
5040
|
-
* Cache hit path: Returns cached snapshot if available (O(1))
|
|
5041
|
-
* Warm miss path: Rebuilds from cached base revision + incremental ops
|
|
5042
|
-
* Cold miss path: Rebuilds from keyframe or from scratch using all operations
|
|
5043
|
-
*
|
|
5044
|
-
* @param documentId - The document identifier
|
|
5045
|
-
* @param scope - The operation scope
|
|
5046
|
-
* @param branch - The operation branch
|
|
5047
|
-
* @param targetRevision - The target revision, or undefined for newest
|
|
5048
|
-
* @param signal - Optional abort signal to cancel the operation
|
|
5049
|
-
* @returns The document at the target revision
|
|
5050
|
-
* @throws {Error} "Operation aborted" if signal is aborted
|
|
5051
|
-
* @throws {ModuleNotFoundError} If document type not registered in registry
|
|
5052
|
-
* @throws {Error} "Failed to rebuild document" if operation store fails
|
|
5053
|
-
* @throws {Error} If reducer throws during operation application
|
|
5054
|
-
* @throws {Error} If document serialization fails
|
|
5067
|
+
* Mark a job as no longer executing for its document
|
|
5055
5068
|
*/
|
|
5056
|
-
|
|
5069
|
+
private markJobComplete;
|
|
5057
5070
|
/**
|
|
5058
|
-
*
|
|
5059
|
-
*
|
|
5060
|
-
* The cached document is a shallow copy of the input with its operation history
|
|
5061
|
-
* truncated to the last operation per scope and its clipboard cleared. This keeps
|
|
5062
|
-
* memory use and copy costs constant regardless of operation count. Consumers of
|
|
5063
|
-
* getState() must not rely on the full operation history being present; the only
|
|
5064
|
-
* guaranteed invariant is that operations[scope].at(-1) reflects the latest
|
|
5065
|
-
* operation index for each scope.
|
|
5066
|
-
*
|
|
5067
|
-
* Updates LRU tracker and may evict least recently used stream if at capacity.
|
|
5068
|
-
* Asynchronously persists keyframes at configured intervals (fire-and-forget).
|
|
5069
|
-
*
|
|
5070
|
-
* @param documentId - The document identifier
|
|
5071
|
-
* @param scope - The operation scope
|
|
5072
|
-
* @param branch - The operation branch
|
|
5073
|
-
* @param revision - The revision number
|
|
5074
|
-
* @param document - The document to cache
|
|
5075
|
-
* @throws {Error} If document serialization fails
|
|
5071
|
+
* Check if all dependencies for a job have been completed
|
|
5076
5072
|
*/
|
|
5077
|
-
|
|
5078
|
-
private store;
|
|
5073
|
+
private areDependenciesMet;
|
|
5079
5074
|
/**
|
|
5080
|
-
*
|
|
5081
|
-
*
|
|
5082
|
-
* Supports three invalidation scopes:
|
|
5083
|
-
* - Document-level: invalidate(documentId) - removes all streams for document
|
|
5084
|
-
* - Scope-level: invalidate(documentId, scope) - removes all branches for scope
|
|
5085
|
-
* - Stream-level: invalidate(documentId, scope, branch) - removes specific stream
|
|
5075
|
+
* Returns the head of the sub-queue if its dependencies are met, or null.
|
|
5086
5076
|
*
|
|
5087
|
-
*
|
|
5088
|
-
*
|
|
5089
|
-
*
|
|
5090
|
-
*
|
|
5077
|
+
* The dispatcher only ever considers the head — a dep-blocked head holds
|
|
5078
|
+
* the rest of its sub-queue. This preserves per-(documentId, scope, branch)
|
|
5079
|
+
* FIFO regardless of how dependencies are authored, and makes the queue's
|
|
5080
|
+
* documented "serialized per document" invariant hold even when callers
|
|
5081
|
+
* omit queueHint dependencies on jobs that share a sub-queue.
|
|
5091
5082
|
*/
|
|
5092
|
-
|
|
5083
|
+
private getNextJobWithMetDependencies;
|
|
5084
|
+
private getCreateDocumentType;
|
|
5085
|
+
enqueue(job: Job): Promise<void>;
|
|
5086
|
+
dequeue(documentId: string, scope: string, branch: string, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5087
|
+
dequeueNext(signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5088
|
+
dequeueNextMatching(predicate: (meta: JobRoutingMeta) => boolean, signal?: AbortSignal): Promise<IJobExecutionHandle | null>;
|
|
5089
|
+
size(documentId: string, scope: string, branch: string): Promise<number>;
|
|
5090
|
+
totalSize(): Promise<number>;
|
|
5091
|
+
remove(jobId: string): Promise<boolean>;
|
|
5092
|
+
clear(documentId: string, scope: string, branch: string): Promise<void>;
|
|
5093
|
+
clearAll(): Promise<void>;
|
|
5094
|
+
hasJobs(): Promise<boolean>;
|
|
5095
|
+
completeJob(jobId: string): Promise<void>;
|
|
5096
|
+
failJob(jobId: string, error?: ErrorInfo$1): Promise<void>;
|
|
5097
|
+
deferJob(jobId: string): void;
|
|
5098
|
+
retryJob(jobId: string, error?: ErrorInfo$1, accounting?: RetryAccounting): Promise<void>;
|
|
5093
5099
|
/**
|
|
5094
|
-
*
|
|
5095
|
-
* Resets LRU tracking state. This operation always succeeds.
|
|
5100
|
+
* Check if the queue is drained and call the callback if it is
|
|
5096
5101
|
*/
|
|
5097
|
-
|
|
5102
|
+
private checkDrained;
|
|
5098
5103
|
/**
|
|
5099
|
-
*
|
|
5100
|
-
* for testing, but not on the interface.
|
|
5101
|
-
*
|
|
5102
|
-
* @internal
|
|
5104
|
+
* Returns true if and only if all jobs have been resolved.
|
|
5103
5105
|
*/
|
|
5104
|
-
|
|
5105
|
-
private findNearestKeyframe;
|
|
5106
|
-
private coldMissRebuild;
|
|
5106
|
+
get isDrained(): boolean;
|
|
5107
5107
|
/**
|
|
5108
|
-
*
|
|
5109
|
-
*
|
|
5108
|
+
* Blocks the queue from accepting new jobs.
|
|
5109
|
+
* @param onDrained - Optional callback to call when the queue is drained
|
|
5110
5110
|
*/
|
|
5111
|
-
|
|
5112
|
-
/** The stored operation at `index`, or undefined if it is no longer there. */
|
|
5113
|
-
private operationAt;
|
|
5111
|
+
block(onDrained?: () => void): void;
|
|
5114
5112
|
/**
|
|
5115
|
-
*
|
|
5116
|
-
*
|
|
5117
|
-
* Uses the validated-upgrade boundary rules from D7:
|
|
5118
|
-
* - If `input.revision` is present: op.index < revision[scope] → before the upgrade boundary
|
|
5119
|
-
* - Otherwise: timestamp fallback
|
|
5120
|
-
* - Falls back to final module version when neither is decidable
|
|
5113
|
+
* Unblocks the queue from accepting new jobs.
|
|
5121
5114
|
*/
|
|
5122
|
-
|
|
5123
|
-
private warmMissRebuild;
|
|
5124
|
-
private findNearestOlderSnapshot;
|
|
5125
|
-
private makeStreamKey;
|
|
5126
|
-
private getOrCreateStream;
|
|
5127
|
-
private isKeyframeRevision;
|
|
5128
|
-
}
|
|
5129
|
-
//#endregion
|
|
5130
|
-
//#region src/storage/kysely/store.d.ts
|
|
5131
|
-
declare class KyselyOperationStore implements IOperationStore {
|
|
5132
|
-
private db;
|
|
5133
|
-
private trx?;
|
|
5134
|
-
constructor(db: Kysely<Database$1>);
|
|
5135
|
-
private get queryExecutor();
|
|
5136
|
-
withTransaction(trx: Transaction<Database$1>): KyselyOperationStore;
|
|
5137
|
-
apply(documentId: string, documentType: string, scope: string, branch: string, revision: number, fn: (txn: AtomicTxn) => void | Promise<void>, signal?: AbortSignal, condition?: AppendCondition): Promise<Operation[]>;
|
|
5138
|
-
private resolveUniqueConstraint;
|
|
5139
|
-
private executeApply;
|
|
5115
|
+
unblock(): void;
|
|
5140
5116
|
/**
|
|
5141
|
-
*
|
|
5142
|
-
* so that overlapping concurrent appends serialize rather than deadlock.
|
|
5143
|
-
* The locks are still taken one row at a time, so the query preserves that
|
|
5144
|
-
* order. It must stay separate from the guarded insert, which would
|
|
5145
|
-
* otherwise read a snapshot taken before the locks were held.
|
|
5117
|
+
* Pauses job dequeuing. Jobs can still be enqueued but dequeueNext() will return null.
|
|
5146
5118
|
*/
|
|
5147
|
-
|
|
5119
|
+
pause(): void;
|
|
5148
5120
|
/**
|
|
5149
|
-
*
|
|
5150
|
-
* NOT EXISTS guard, making the check and the append one statement. Returns
|
|
5151
|
-
* the rows inserted; zero means the guard failed and nothing was written.
|
|
5121
|
+
* Resumes job dequeuing and emits JOB_AVAILABLE events for pending jobs to wake up executors.
|
|
5152
5122
|
*/
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5123
|
+
resume(): Promise<void>;
|
|
5124
|
+
/**
|
|
5125
|
+
* Returns whether job dequeuing is paused.
|
|
5126
|
+
*/
|
|
5127
|
+
get paused(): boolean;
|
|
5128
|
+
/**
|
|
5129
|
+
* Returns all pending jobs across all queues.
|
|
5130
|
+
*/
|
|
5131
|
+
getPendingJobs(): Job[];
|
|
5132
|
+
/**
|
|
5133
|
+
* Returns a map of document IDs to sets of executing job IDs.
|
|
5134
|
+
*/
|
|
5135
|
+
getExecutingJobIds(): Map<string, Set<string>>;
|
|
5136
|
+
/**
|
|
5137
|
+
* Returns a job by ID from the job index.
|
|
5138
|
+
*/
|
|
5139
|
+
getJob(jobId: string): Job | undefined;
|
|
5161
5140
|
}
|
|
5162
5141
|
//#endregion
|
|
5163
|
-
//#region src/
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5142
|
+
//#region src/job-tracker/in-memory-job-tracker.d.ts
|
|
5143
|
+
/**
|
|
5144
|
+
* In-memory implementation of IJobTracker.
|
|
5145
|
+
* Maintains job status in a Map for synchronous access.
|
|
5146
|
+
* Subscribes to operation events to update job states.
|
|
5147
|
+
*/
|
|
5148
|
+
declare class InMemoryJobTracker implements IJobTracker {
|
|
5149
|
+
private eventBus;
|
|
5150
|
+
private jobs;
|
|
5151
|
+
private unsubscribers;
|
|
5152
|
+
constructor(eventBus: IEventBus);
|
|
5153
|
+
private subscribeToEvents;
|
|
5154
|
+
private handleWriteReady;
|
|
5155
|
+
private handleReadReady;
|
|
5156
|
+
private handleJobFailed;
|
|
5157
|
+
shutdown(): void;
|
|
5158
|
+
registerJob(jobInfo: JobInfo): void;
|
|
5159
|
+
markRunning(jobId: string): void;
|
|
5160
|
+
markFailed(jobId: string, error: ErrorInfo$1, job?: Job): void;
|
|
5161
|
+
getJobStatus(jobId: string): JobInfo | null;
|
|
5182
5162
|
}
|
|
5183
5163
|
//#endregion
|
|
5184
|
-
//#region src/executor/
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5164
|
+
//#region src/executor/simple-job-executor-manager.d.ts
|
|
5165
|
+
type JobExecutorFactory = () => IJobExecutor;
|
|
5166
|
+
/**
|
|
5167
|
+
* Manages multiple job executors and coordinates job distribution.
|
|
5168
|
+
* Listens for job available events and dispatches jobs to executors.
|
|
5169
|
+
*/
|
|
5170
|
+
declare class SimpleJobExecutorManager implements IJobExecutorManager {
|
|
5171
|
+
private executorFactory;
|
|
5172
|
+
private eventBus;
|
|
5173
|
+
private queue;
|
|
5174
|
+
private jobTracker;
|
|
5175
|
+
private logger;
|
|
5176
|
+
private resolver;
|
|
5177
|
+
private executors;
|
|
5178
|
+
private isRunning;
|
|
5179
|
+
private activeJobs;
|
|
5180
|
+
private totalJobsProcessed;
|
|
5181
|
+
private unsubscribe?;
|
|
5182
|
+
private deferredJobs;
|
|
5183
|
+
private resultHandler;
|
|
5184
|
+
private jobTimeoutMs;
|
|
5185
|
+
constructor(executorFactory: JobExecutorFactory, eventBus: IEventBus, queue: IQueue, jobTracker: IJobTracker, logger: ILogger, resolver: IDocumentModelResolver, jobTimeoutMs?: number);
|
|
5186
|
+
start(numExecutors: number): Promise<void>;
|
|
5187
|
+
stop(graceful?: boolean): Promise<void>;
|
|
5188
|
+
getExecutors(): IJobExecutor[];
|
|
5189
|
+
getStatus(): ExecutorManagerStatus;
|
|
5190
|
+
private processNextJob;
|
|
5191
|
+
private checkForMoreJobs;
|
|
5192
|
+
private processExistingJobs;
|
|
5193
|
+
private flushDeferredJobs;
|
|
5194
5194
|
}
|
|
5195
5195
|
//#endregion
|
|
5196
5196
|
//#region src/executor/simple-job-executor.d.ts
|
|
@@ -5221,6 +5221,13 @@ declare class SimpleJobExecutor implements IJobExecutor {
|
|
|
5221
5221
|
private getCollectionMembershipsForOperations;
|
|
5222
5222
|
private processActions;
|
|
5223
5223
|
private executeRegularAction;
|
|
5224
|
+
/**
|
|
5225
|
+
* Orders a write by timestamp. The caller supplies the timestamp, so a write
|
|
5226
|
+
* can belong before operations already stored, and appending it at the tail
|
|
5227
|
+
* would leave the scope out of order. The operations it belongs before are
|
|
5228
|
+
* re-appended alongside it, the way a load reshuffles.
|
|
5229
|
+
*/
|
|
5230
|
+
private positionByTimestamp;
|
|
5224
5231
|
/**
|
|
5225
5232
|
* Re-evaluates the document when a write meets both criteria: it was written
|
|
5226
5233
|
* to a stream the model reads, and it is timestamped before an operation
|