@powerhousedao/reactor 6.2.2-dev.2 → 6.2.2-dev.20
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-BDrPlCJl.js → build-worker-executor-CE-Yyezb.js} +3 -3
- package/dist/{build-worker-executor-BDrPlCJl.js.map → build-worker-executor-CE-Yyezb.js.map} +1 -1
- package/dist/{document-indexer-FGJmRAdX.js → document-indexer-BY-mPXJF.js} +10 -3
- package/dist/document-indexer-BY-mPXJF.js.map +1 -0
- package/dist/{drive-container-types-DpJp2AmE.js → drive-container-types-DrQMmpCa.js} +156 -40
- package/dist/drive-container-types-DrQMmpCa.js.map +1 -0
- package/dist/entry.js +2 -2
- package/dist/index.d.ts +221 -68
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +326 -117
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +3 -3
- package/dist/{worker-DBJOv8Gp.js → worker-BEzk4Q1I.js} +2 -2
- package/dist/{worker-DBJOv8Gp.js.map → worker-BEzk4Q1I.js.map} +1 -1
- package/dist/worker-handle-B1w03nRA.js.map +1 -1
- package/package.json +4 -4
- package/dist/document-indexer-FGJmRAdX.js.map +0 -1
- package/dist/drive-container-types-DpJp2AmE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as DocumentNotFoundError, C as RevisionMismatchError, D as ModuleNotFoundError, E as InvalidModuleError, M as parsePagingOptions, N as throwIfAborted, O as AuthorizationDeniedError, S as OptimisticLockError, T as DuplicateModuleError, _ as createConsistencyToken, a as createForwardingPoolInstrumentation, b as AppendConditionFailedError, c as KyselyKeyframeStore, d as DriveCollectionId, f as KyselyExecutionScope, g as DocumentMetaCache, h as KyselyOperationIndex, i as runMigrations, j as matchesScope, k as DocumentDeletedError, l as DocumentModelRegistry, m as KyselyWriteCache, n as REACTOR_SCHEMA, o as instrumentPgPool, p as EventBus, r as getMigrationStatus, s as KyselyOperationStore, t as DEFAULT_DRIVE_CONTAINER_TYPES, u as SimpleJobExecutor, v as createEmptyConsistencyToken, w as DuplicateManifestError, x as DuplicateOperationError, y as CollectionMembershipCache } from "./drive-container-types-DrQMmpCa.js";
|
|
2
2
|
import { n as ReactorEventTypes, t as EventBusAggregateError } from "./types-DMKLa0Ok.js";
|
|
3
3
|
import { i as WorkerInitFailedError, r as WorkerExitedError, t as WorkerAbortTimeoutError } from "./errors-D3S6Eysd.js";
|
|
4
|
-
import { a as ReadModelCoordinator, i as KyselyDocumentView, n as ConsistencyTracker, o as BaseReadModel, r as makeConsistencyKey, t as KyselyDocumentIndexer } from "./document-indexer-
|
|
4
|
+
import { a as ReadModelCoordinator, i as KyselyDocumentView, n as ConsistencyTracker, o as BaseReadModel, r as makeConsistencyKey, t as KyselyDocumentIndexer } from "./document-indexer-BY-mPXJF.js";
|
|
5
5
|
import { n as errorToInfo, r as sanitizeArg, t as createForwardingLogger } from "./forwarding-logger-BBkMSxuJ.js";
|
|
6
|
-
import { t as workerEntryPath } from "./worker-
|
|
7
|
-
import { actions, actions as documentActions, createPresignedHeader, generateId, hashDocumentStateForScope, replayDocument } from "@powerhousedao/shared/document-model";
|
|
6
|
+
import { t as workerEntryPath } from "./worker-BEzk4Q1I.js";
|
|
7
|
+
import { actions, actions as documentActions, createPresignedHeader, decide, generateId, hashDocumentStateForScope, replayDocument } from "@powerhousedao/shared/document-model";
|
|
8
8
|
import { addFile, addFolder, copyNode, deleteNode, driveCreateDocument, generateNodesCopy, getDescendants, handleTargetNameCollisions, isFileNode, isFolderNode, moveNode, updateNode } from "@powerhousedao/shared/document-drive";
|
|
9
9
|
import { v4 } from "uuid";
|
|
10
10
|
import { ConsoleLogger, childLogger } from "document-model";
|
|
@@ -680,6 +680,39 @@ let DocumentChangeType = /* @__PURE__ */ function(DocumentChangeType) {
|
|
|
680
680
|
return DocumentChangeType;
|
|
681
681
|
}({});
|
|
682
682
|
//#endregion
|
|
683
|
+
//#region src/client/util.ts
|
|
684
|
+
const ALWAYS_READABLE_SCOPES = new Set(["auth", "document"]);
|
|
685
|
+
function authSubjectFromSigner(signer) {
|
|
686
|
+
return {
|
|
687
|
+
address: signer.user?.address,
|
|
688
|
+
key: signer.app?.key
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function canReadScope(auth, subject, scope) {
|
|
692
|
+
return ALWAYS_READABLE_SCOPES.has(scope) || decide(auth, subject, {
|
|
693
|
+
verb: "read",
|
|
694
|
+
scope
|
|
695
|
+
}) === "allow";
|
|
696
|
+
}
|
|
697
|
+
function withAuthScope(view) {
|
|
698
|
+
if (view?.scopes && view.scopes.length > 0) return {
|
|
699
|
+
...view,
|
|
700
|
+
scopes: [...new Set([...view.scopes, "auth"])]
|
|
701
|
+
};
|
|
702
|
+
return view;
|
|
703
|
+
}
|
|
704
|
+
function filterReadableScopes(document, subject) {
|
|
705
|
+
const state = document.state;
|
|
706
|
+
if (!state) return document;
|
|
707
|
+
const auth = document.state.auth;
|
|
708
|
+
const filtered = {};
|
|
709
|
+
for (const scope of Object.keys(state)) if (canReadScope(auth, subject, scope)) filtered[scope] = state[scope];
|
|
710
|
+
return {
|
|
711
|
+
...document,
|
|
712
|
+
state: filtered
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
//#endregion
|
|
683
716
|
//#region src/client/reactor-client.ts
|
|
684
717
|
/**
|
|
685
718
|
* ReactorClient implementation that wraps lower-level APIs to provide
|
|
@@ -711,6 +744,9 @@ var ReactorClient = class {
|
|
|
711
744
|
this.drives = new DriveClient(this, logger, reactor, signer);
|
|
712
745
|
this.logger.verbose("ReactorClient initialized");
|
|
713
746
|
}
|
|
747
|
+
readSubject(subject) {
|
|
748
|
+
return subject ?? authSubjectFromSigner(this.signer);
|
|
749
|
+
}
|
|
714
750
|
/**
|
|
715
751
|
* Retrieves a list of document model modules.
|
|
716
752
|
*/
|
|
@@ -734,7 +770,7 @@ var ReactorClient = class {
|
|
|
734
770
|
*/
|
|
735
771
|
async get(identifier, view, signal) {
|
|
736
772
|
this.logger.verbose("get(@identifier, @view)", identifier, view);
|
|
737
|
-
return await this.reactor.getByIdOrSlug(identifier, view, void 0, signal);
|
|
773
|
+
return filterReadableScopes(await this.reactor.getByIdOrSlug(identifier, withAuthScope(view), void 0, signal), this.readSubject(view?.subject));
|
|
738
774
|
}
|
|
739
775
|
/**
|
|
740
776
|
* Resolves an identifier (id or slug) to the canonical document id, using the
|
|
@@ -750,8 +786,15 @@ var ReactorClient = class {
|
|
|
750
786
|
async getOperations(documentIdentifier, view, filter, paging, signal) {
|
|
751
787
|
this.logger.verbose("getOperations(@documentIdentifier, @view, @filter, @paging)", documentIdentifier, view, filter, paging);
|
|
752
788
|
const documentId = await this.documentView.resolveIdOrSlug(documentIdentifier, view, void 0, signal);
|
|
753
|
-
|
|
789
|
+
const authDoc = await this.reactor.getByIdOrSlug(documentId, {
|
|
790
|
+
scopes: ["auth"],
|
|
791
|
+
branch: view?.branch
|
|
792
|
+
}, void 0, signal);
|
|
793
|
+
const subject = this.readSubject(view?.subject);
|
|
794
|
+
const canRead = (scope) => canReadScope(authDoc?.state.auth, subject, scope);
|
|
795
|
+
if (paging?.cursor && isCompositeCursor(paging.cursor)) return this.getOperationsWithCompositeCursor(documentId, view, filter, paging, signal, canRead);
|
|
754
796
|
const operationsByScope = await this.reactor.getOperations(documentId, view, filter, paging, void 0, signal);
|
|
797
|
+
for (const scope of Object.keys(operationsByScope)) if (!canRead(scope)) delete operationsByScope[scope];
|
|
755
798
|
const scopeEntries = Object.entries(operationsByScope);
|
|
756
799
|
const effectivePaging = paging || {
|
|
757
800
|
cursor: "0",
|
|
@@ -779,11 +822,12 @@ var ReactorClient = class {
|
|
|
779
822
|
nextCursor: Object.keys(activeCursors).length > 0 ? encodeCompositeCursor(activeCursors) : void 0
|
|
780
823
|
};
|
|
781
824
|
}
|
|
782
|
-
async getOperationsWithCompositeCursor(documentId, view, filter, paging, signal) {
|
|
825
|
+
async getOperationsWithCompositeCursor(documentId, view, filter, paging, signal, canRead) {
|
|
783
826
|
const scopeCursors = decodeCompositeCursor(paging.cursor);
|
|
784
827
|
const allOperations = [];
|
|
785
828
|
const activeCursors = {};
|
|
786
829
|
for (const [scopeName, cursor] of Object.entries(scopeCursors)) {
|
|
830
|
+
if (!canRead(scopeName)) continue;
|
|
787
831
|
const scopeView = {
|
|
788
832
|
...view,
|
|
789
833
|
scopes: [scopeName]
|
|
@@ -817,7 +861,7 @@ var ReactorClient = class {
|
|
|
817
861
|
limit: 0
|
|
818
862
|
}
|
|
819
863
|
};
|
|
820
|
-
return this.
|
|
864
|
+
return this.find({ ids: targetIds }, view, paging, signal);
|
|
821
865
|
}
|
|
822
866
|
/**
|
|
823
867
|
* Retrieves incoming relationships of a given type to a target document.
|
|
@@ -833,14 +877,19 @@ var ReactorClient = class {
|
|
|
833
877
|
limit: 0
|
|
834
878
|
}
|
|
835
879
|
};
|
|
836
|
-
return this.
|
|
880
|
+
return this.find({ ids: sourceIds }, view, paging, signal);
|
|
837
881
|
}
|
|
838
882
|
/**
|
|
839
883
|
* Filters documents by criteria and returns a list of them
|
|
840
884
|
*/
|
|
841
885
|
async find(search, view, paging, signal) {
|
|
842
886
|
this.logger.verbose("find(@search, @view, @paging)", search, view, paging);
|
|
843
|
-
|
|
887
|
+
const results = await this.reactor.find(search, withAuthScope(view), paging, void 0, signal);
|
|
888
|
+
const readSubject = this.readSubject(view?.subject);
|
|
889
|
+
return {
|
|
890
|
+
...results,
|
|
891
|
+
results: results.results.map((doc) => filterReadableScopes(doc, readSubject))
|
|
892
|
+
};
|
|
844
893
|
}
|
|
845
894
|
/**
|
|
846
895
|
* Creates a document and waits for completion
|
|
@@ -1144,6 +1193,18 @@ let JobQueueState = /* @__PURE__ */ function(JobQueueState) {
|
|
|
1144
1193
|
return JobQueueState;
|
|
1145
1194
|
}({});
|
|
1146
1195
|
/**
|
|
1196
|
+
* How a retry is accounted against the job's retry limit.
|
|
1197
|
+
* - `CountAgainstLimit` (default): a fault; the job eventually exhausts its
|
|
1198
|
+
* retries and fails terminally.
|
|
1199
|
+
* - `ExemptFromLimit`: not a fault, so the attempt is not charged to the job.
|
|
1200
|
+
* Used for concurrency conflicts, where the retry does new work.
|
|
1201
|
+
*/
|
|
1202
|
+
let RetryAccounting = /* @__PURE__ */ function(RetryAccounting) {
|
|
1203
|
+
RetryAccounting["CountAgainstLimit"] = "count-against-limit";
|
|
1204
|
+
RetryAccounting["ExemptFromLimit"] = "exempt-from-limit";
|
|
1205
|
+
return RetryAccounting;
|
|
1206
|
+
}({});
|
|
1207
|
+
/**
|
|
1147
1208
|
* Event types for the queue system
|
|
1148
1209
|
*/
|
|
1149
1210
|
const QueueEventTypes = { JOB_AVAILABLE: 1e4 };
|
|
@@ -1187,12 +1248,19 @@ var JobResultHandler = class {
|
|
|
1187
1248
|
} catch {}
|
|
1188
1249
|
}
|
|
1189
1250
|
}
|
|
1251
|
+
if (result.error && AppendConditionFailedError.isError(result.error)) {
|
|
1252
|
+
const errorInfo = toErrorInfo(result.error);
|
|
1253
|
+
try {
|
|
1254
|
+
await this.queue.retryJob(handle.job.id, errorInfo, RetryAccounting.ExemptFromLimit);
|
|
1255
|
+
return;
|
|
1256
|
+
} catch {}
|
|
1257
|
+
}
|
|
1190
1258
|
if (result.error && DocumentNotFoundError.isError(result.error)) {
|
|
1191
1259
|
handle.defer();
|
|
1192
1260
|
callbacks.deferJob(handle.job.documentId, handle.job);
|
|
1193
1261
|
return;
|
|
1194
1262
|
}
|
|
1195
|
-
if (result.error && DocumentDeletedError.isError(result.error)) {
|
|
1263
|
+
if (result.error && (DocumentDeletedError.isError(result.error) || AuthorizationDeniedError.isError(result.error))) {
|
|
1196
1264
|
const errorInfo = toErrorInfo(result.error);
|
|
1197
1265
|
this.jobTracker.markFailed(handle.job.id, errorInfo, handle.job);
|
|
1198
1266
|
this.eventBus.emit(ReactorEventTypes.JOB_FAILED, {
|
|
@@ -2587,7 +2655,7 @@ var InMemoryQueue = class {
|
|
|
2587
2655
|
if (documentId) this.markJobComplete(jobId, documentId);
|
|
2588
2656
|
this.jobIndex.delete(jobId);
|
|
2589
2657
|
}
|
|
2590
|
-
async retryJob(jobId, error) {
|
|
2658
|
+
async retryJob(jobId, error, accounting = RetryAccounting.CountAgainstLimit) {
|
|
2591
2659
|
const job = this.jobIndex.get(jobId);
|
|
2592
2660
|
if (!job) return;
|
|
2593
2661
|
job.lastError = error;
|
|
@@ -2596,9 +2664,10 @@ var InMemoryQueue = class {
|
|
|
2596
2664
|
this.jobIndex.delete(jobId);
|
|
2597
2665
|
this.jobIdToQueueKey.delete(jobId);
|
|
2598
2666
|
if (error) job.errorHistory.push(error);
|
|
2667
|
+
const retryCount = job.retryCount || 0;
|
|
2599
2668
|
const updatedJob = {
|
|
2600
2669
|
...job,
|
|
2601
|
-
retryCount:
|
|
2670
|
+
retryCount: accounting === RetryAccounting.CountAgainstLimit ? retryCount + 1 : retryCount,
|
|
2602
2671
|
lastError: error
|
|
2603
2672
|
};
|
|
2604
2673
|
await this.enqueue(updatedJob);
|
|
@@ -2686,6 +2755,98 @@ var InMemoryQueue = class {
|
|
|
2686
2755
|
}
|
|
2687
2756
|
};
|
|
2688
2757
|
//#endregion
|
|
2758
|
+
//#region src/core/model-sources.ts
|
|
2759
|
+
function modelSourceKey(module) {
|
|
2760
|
+
return `${module.documentModel.global.id}@${module.version ?? 1}`;
|
|
2761
|
+
}
|
|
2762
|
+
function isDocumentModelModule(value) {
|
|
2763
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2764
|
+
const candidate = value;
|
|
2765
|
+
return typeof candidate.reducer === "function" && typeof candidate.documentModel?.global?.id === "string";
|
|
2766
|
+
}
|
|
2767
|
+
/**
|
|
2768
|
+
* Resolves every source to live modules by importing file/package sources
|
|
2769
|
+
* host-side and scanning their exports, so the host registry and the worker
|
|
2770
|
+
* manifest are derived from one list and cannot diverge.
|
|
2771
|
+
*/
|
|
2772
|
+
async function resolveModelSources(sources) {
|
|
2773
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
2774
|
+
for (const source of sources) {
|
|
2775
|
+
if (isDocumentModelModule(source)) {
|
|
2776
|
+
addEntry(resolved, {
|
|
2777
|
+
module: source,
|
|
2778
|
+
spec: null
|
|
2779
|
+
});
|
|
2780
|
+
continue;
|
|
2781
|
+
}
|
|
2782
|
+
for (const entry of await resolveImportableSource(source)) addEntry(resolved, entry);
|
|
2783
|
+
}
|
|
2784
|
+
const modules = [];
|
|
2785
|
+
const manifest = [];
|
|
2786
|
+
const moduleOnlyKeys = [];
|
|
2787
|
+
for (const [key, entry] of resolved) {
|
|
2788
|
+
modules.push(entry.module);
|
|
2789
|
+
if (entry.spec) manifest.push({
|
|
2790
|
+
documentType: entry.module.documentModel.global.id,
|
|
2791
|
+
version: String(entry.module.version ?? 1),
|
|
2792
|
+
spec: entry.spec
|
|
2793
|
+
});
|
|
2794
|
+
else moduleOnlyKeys.push(key);
|
|
2795
|
+
}
|
|
2796
|
+
return {
|
|
2797
|
+
modules,
|
|
2798
|
+
manifest,
|
|
2799
|
+
moduleOnlyKeys
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
function addEntry(map, entry) {
|
|
2803
|
+
const key = modelSourceKey(entry.module);
|
|
2804
|
+
const existing = map.get(key);
|
|
2805
|
+
if (!existing) {
|
|
2806
|
+
map.set(key, entry);
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
if (!existing.spec && entry.spec) existing.spec = entry.spec;
|
|
2810
|
+
}
|
|
2811
|
+
async function resolveImportableSource(source) {
|
|
2812
|
+
const isFile = "filePath" in source;
|
|
2813
|
+
const specifier = isFile ? new URL(`file://${source.filePath}`).href : source.subpath ? `${source.packageName}/${source.subpath}` : source.packageName;
|
|
2814
|
+
const moduleRef = isFile ? { filePath: source.filePath } : { packageName: specifier };
|
|
2815
|
+
let moduleNs;
|
|
2816
|
+
try {
|
|
2817
|
+
moduleNs = await import(
|
|
2818
|
+
/* @vite-ignore */
|
|
2819
|
+
specifier
|
|
2820
|
+
);
|
|
2821
|
+
} catch (error) {
|
|
2822
|
+
throw new Error(`Failed to import document-model source "${describeSource(source)}"`, { cause: error });
|
|
2823
|
+
}
|
|
2824
|
+
if (source.exportName !== void 0) {
|
|
2825
|
+
const value = moduleNs[source.exportName];
|
|
2826
|
+
if (!isDocumentModelModule(value)) throw new Error(`Export "${source.exportName}" of document-model source "${describeSource(source)}" is not a DocumentModelModule`);
|
|
2827
|
+
return [{
|
|
2828
|
+
module: value,
|
|
2829
|
+
spec: { module: {
|
|
2830
|
+
...moduleRef,
|
|
2831
|
+
exportName: source.exportName
|
|
2832
|
+
} }
|
|
2833
|
+
}];
|
|
2834
|
+
}
|
|
2835
|
+
const entries = [];
|
|
2836
|
+
for (const [exportName, value] of Object.entries(moduleNs)) if (isDocumentModelModule(value)) entries.push({
|
|
2837
|
+
module: value,
|
|
2838
|
+
spec: { module: {
|
|
2839
|
+
...moduleRef,
|
|
2840
|
+
exportName
|
|
2841
|
+
} }
|
|
2842
|
+
});
|
|
2843
|
+
if (entries.length === 0) throw new Error(`Document-model source "${describeSource(source)}" has no DocumentModelModule exports`);
|
|
2844
|
+
return entries;
|
|
2845
|
+
}
|
|
2846
|
+
function describeSource(source) {
|
|
2847
|
+
return "filePath" in source ? source.filePath : source.subpath ? `${source.packageName}/${source.subpath}` : source.packageName;
|
|
2848
|
+
}
|
|
2849
|
+
//#endregion
|
|
2689
2850
|
//#region src/registry/document-model-resolver.ts
|
|
2690
2851
|
/**
|
|
2691
2852
|
* Encapsulates the logic for resolving document model modules on demand.
|
|
@@ -2743,10 +2904,11 @@ var DocumentModelResolver = class {
|
|
|
2743
2904
|
return loadPromise;
|
|
2744
2905
|
}
|
|
2745
2906
|
async loadRegisterAndBroadcast(documentType) {
|
|
2746
|
-
const
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2907
|
+
const resolved = await resolveModelSources([await this.loader.load(documentType)]);
|
|
2908
|
+
if (!resolved.modules.some((module) => module.documentModel.global.id === documentType)) throw new Error(`Loader source resolved no module for document type: ${documentType}`);
|
|
2909
|
+
const results = this.registry.registerModules(...resolved.modules);
|
|
2910
|
+
for (const result of results) if (result.status === "error" && !DuplicateModuleError.isError(result.error)) throw result.error;
|
|
2911
|
+
if (this.broadcastHook) for (const entry of resolved.manifest) await this.broadcastHook(entry);
|
|
2750
2912
|
}
|
|
2751
2913
|
async notifyPeersModelLoaded(documentType) {
|
|
2752
2914
|
if (!this.modelLoadedHook) return;
|
|
@@ -2756,12 +2918,6 @@ var DocumentModelResolver = class {
|
|
|
2756
2918
|
this.logger.warn(`MODEL_LOADED hook failed: ${documentType}`, error);
|
|
2757
2919
|
}
|
|
2758
2920
|
}
|
|
2759
|
-
async broadcastIfPossible(documentType) {
|
|
2760
|
-
if (!this.broadcastHook || !this.loader.resolveSpec) return;
|
|
2761
|
-
const entry = await this.loader.resolveSpec(documentType);
|
|
2762
|
-
if (!entry) return;
|
|
2763
|
-
await this.broadcastHook(entry);
|
|
2764
|
-
}
|
|
2765
2921
|
};
|
|
2766
2922
|
/**
|
|
2767
2923
|
* No-op resolver used when no document model loader is configured.
|
|
@@ -6478,9 +6634,12 @@ var Reactor = class {
|
|
|
6478
6634
|
};
|
|
6479
6635
|
//#endregion
|
|
6480
6636
|
//#region src/core/reactor-builder.ts
|
|
6637
|
+
function sameDatabaseTarget(a, b) {
|
|
6638
|
+
return a.host === b.host && a.port === b.port && a.database === b.database;
|
|
6639
|
+
}
|
|
6481
6640
|
var ReactorBuilder = class {
|
|
6482
6641
|
logger;
|
|
6483
|
-
|
|
6642
|
+
documentModelSources = [];
|
|
6484
6643
|
upgradeManifests = [];
|
|
6485
6644
|
features = { legacyStorageEnabled: false };
|
|
6486
6645
|
readModels = [];
|
|
@@ -6501,12 +6660,8 @@ var ReactorBuilder = class {
|
|
|
6501
6660
|
documentModelLoader;
|
|
6502
6661
|
shutdownHooks = [];
|
|
6503
6662
|
driveContainerTypes = DEFAULT_DRIVE_CONTAINER_TYPES;
|
|
6504
|
-
|
|
6505
|
-
workerPoolConfig;
|
|
6663
|
+
workerPool;
|
|
6506
6664
|
resolvedModelManifest;
|
|
6507
|
-
workerDbConfig;
|
|
6508
|
-
workerSignatureVerifierSpec;
|
|
6509
|
-
workerFactory;
|
|
6510
6665
|
projectionShardConfig;
|
|
6511
6666
|
projectionWorkerFactory;
|
|
6512
6667
|
instrumentedPools = [];
|
|
@@ -6514,8 +6669,15 @@ var ReactorBuilder = class {
|
|
|
6514
6669
|
this.logger = logger;
|
|
6515
6670
|
return this;
|
|
6516
6671
|
}
|
|
6517
|
-
|
|
6518
|
-
|
|
6672
|
+
/**
|
|
6673
|
+
* Register document-model sources: live modules, importable files, or
|
|
6674
|
+
* importable packages. Appends across calls. At `buildModule()` every
|
|
6675
|
+
* source is resolved host-side and registered on the registry; file and
|
|
6676
|
+
* package sources additionally form the worker manifest when the worker
|
|
6677
|
+
* pool is enabled (live modules cannot cross a thread boundary).
|
|
6678
|
+
*/
|
|
6679
|
+
withDocumentModelSources(sources) {
|
|
6680
|
+
this.documentModelSources.push(...sources);
|
|
6519
6681
|
return this;
|
|
6520
6682
|
}
|
|
6521
6683
|
withUpgradeManifests(manifests) {
|
|
@@ -6630,58 +6792,30 @@ var ReactorBuilder = class {
|
|
|
6630
6792
|
this.shutdownHooks.push(hook);
|
|
6631
6793
|
return this;
|
|
6632
6794
|
}
|
|
6633
|
-
withDocumentModelSpecs(specs) {
|
|
6634
|
-
this.documentModelSpecs = specs;
|
|
6635
|
-
return this;
|
|
6636
|
-
}
|
|
6637
|
-
/**
|
|
6638
|
-
* Stores the worker-pool configuration. When `config.enabled === true` the
|
|
6639
|
-
* builder constructs a {@link WorkerPoolJobExecutorManager} in place of the
|
|
6640
|
-
* in-process {@link SimpleJobExecutorManager}.
|
|
6641
|
-
*/
|
|
6642
|
-
withWorkerPool(config) {
|
|
6643
|
-
this.workerPoolConfig = config;
|
|
6644
|
-
return this;
|
|
6645
|
-
}
|
|
6646
|
-
/**
|
|
6647
|
-
* Postgres connection info forwarded to each worker so it can open its own
|
|
6648
|
-
* pool. Required when `workerPool.enabled === true` unless a custom
|
|
6649
|
-
* `withWorkerFactory` or `withExecutor` is provided.
|
|
6650
|
-
*/
|
|
6651
|
-
withWorkerDbConfig(db) {
|
|
6652
|
-
this.workerDbConfig = db;
|
|
6653
|
-
return this;
|
|
6654
|
-
}
|
|
6655
|
-
/**
|
|
6656
|
-
* Factory spec the worker imports to instantiate its signature verifier.
|
|
6657
|
-
* Required when `workerPool.enabled === true` unless a custom
|
|
6658
|
-
* `withWorkerFactory` or `withExecutor` is provided.
|
|
6659
|
-
*/
|
|
6660
|
-
withWorkerSignatureVerifierSpec(spec) {
|
|
6661
|
-
this.workerSignatureVerifierSpec = spec;
|
|
6662
|
-
return this;
|
|
6663
|
-
}
|
|
6664
6795
|
/**
|
|
6665
|
-
*
|
|
6666
|
-
*
|
|
6667
|
-
*
|
|
6668
|
-
* (
|
|
6796
|
+
* Enable the executor worker pool: N `node:worker_threads` workers with
|
|
6797
|
+
* sticky per-document routing, replacing the in-process executor. Calling
|
|
6798
|
+
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
6799
|
+
* (each worker opens its own Postgres pool; the parent database is built
|
|
6800
|
+
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
6801
|
+
* transport. `verifier` is imported by the default transport's workers;
|
|
6802
|
+
* omitted = no executor-side signature verification.
|
|
6669
6803
|
*/
|
|
6670
|
-
|
|
6671
|
-
this.
|
|
6804
|
+
withWorkerPool(options) {
|
|
6805
|
+
this.workerPool = options;
|
|
6672
6806
|
return this;
|
|
6673
6807
|
}
|
|
6674
6808
|
/**
|
|
6675
6809
|
* Configure N sharded projection workers. When set, the builder replaces
|
|
6676
6810
|
* the default in-process {@link ReadModelCoordinator} with a
|
|
6677
|
-
* {@link ProjectionShardManager}.
|
|
6678
|
-
* {@link withWorkerDbConfig} is reused for the projection workers'
|
|
6679
|
-
* connection info; only the `poolSize` is overridden by
|
|
6680
|
-
* {@link ProjectionShardBuilderConfig.poolSize}.
|
|
6811
|
+
* {@link ProjectionShardManager}.
|
|
6681
6812
|
*
|
|
6682
|
-
*
|
|
6683
|
-
*
|
|
6684
|
-
*
|
|
6813
|
+
* Projection workers open their own Postgres pools from `config.db`,
|
|
6814
|
+
* falling back to the executor worker pool's `db` when
|
|
6815
|
+
* {@link withWorkerPool} is configured with one; only the `poolSize` is
|
|
6816
|
+
* overridden by {@link ProjectionShardBuilderConfig.poolSize}. The same
|
|
6817
|
+
* model manifest resolved from {@link withDocumentModelSources} is
|
|
6818
|
+
* forwarded.
|
|
6685
6819
|
*/
|
|
6686
6820
|
withProjectionShards(config) {
|
|
6687
6821
|
this.projectionShardConfig = config;
|
|
@@ -6704,41 +6838,24 @@ var ReactorBuilder = class {
|
|
|
6704
6838
|
}
|
|
6705
6839
|
async buildModule() {
|
|
6706
6840
|
if (!this.logger) this.logger = new ConsoleLogger(["reactor"]);
|
|
6707
|
-
if (this.
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
if (
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
if (this.documentModelSpecs.length > 0) this.resolvedModelManifest = this.documentModelSpecs.map((input) => {
|
|
6715
|
-
if ("filePath" in input) return {
|
|
6716
|
-
documentType: "<unresolved>",
|
|
6717
|
-
version: "<unresolved>",
|
|
6718
|
-
spec: { module: {
|
|
6719
|
-
filePath: input.filePath,
|
|
6720
|
-
exportName: "documentModel"
|
|
6721
|
-
} }
|
|
6722
|
-
};
|
|
6723
|
-
return {
|
|
6724
|
-
documentType: "<unresolved>",
|
|
6725
|
-
version: input.version,
|
|
6726
|
-
spec: { module: {
|
|
6727
|
-
packageName: input.packageName,
|
|
6728
|
-
exportName: "documentModel"
|
|
6729
|
-
} }
|
|
6730
|
-
};
|
|
6731
|
-
});
|
|
6841
|
+
if (this.projectionShardConfig !== void 0 && this.readModelFactories.length > 0) throw new Error("withProjectionShards does not support read models registered through withReadModelFactory; projection workers cannot receive host-only factory dependencies");
|
|
6842
|
+
const resolvedSources = await resolveModelSources(this.documentModelSources);
|
|
6843
|
+
if (this.workerPool) {
|
|
6844
|
+
if (resolvedSources.manifest.length === 0) throw new Error("withWorkerPool requires at least one worker-importable document-model source ({ filePath } or { packageName }).");
|
|
6845
|
+
if (resolvedSources.moduleOnlyKeys.length > 0) throw new Error(`withWorkerPool requires worker-importable sources, but these models were registered only as live modules: ${resolvedSources.moduleOnlyKeys.join(", ")}. Provide a { filePath } or { packageName } source for each.`);
|
|
6846
|
+
}
|
|
6847
|
+
this.resolvedModelManifest = resolvedSources.manifest.length > 0 ? resolvedSources.manifest : void 0;
|
|
6732
6848
|
const documentModelRegistry = new DocumentModelRegistry();
|
|
6733
6849
|
if (this.upgradeManifests.length > 0) {
|
|
6734
6850
|
const results = documentModelRegistry.registerUpgradeManifests(...this.upgradeManifests);
|
|
6735
6851
|
for (const result of results) if (result.status === "error") this.logger.error("Failed to register upgrade manifest: @error", result.error.message);
|
|
6736
6852
|
}
|
|
6737
|
-
if (
|
|
6738
|
-
const results = documentModelRegistry.registerModules(...
|
|
6853
|
+
if (resolvedSources.modules.length > 0) {
|
|
6854
|
+
const results = documentModelRegistry.registerModules(...resolvedSources.modules);
|
|
6739
6855
|
for (const result of results) if (result.status === "error") this.logger.error("Failed to register document model: @error", result.error.message);
|
|
6740
6856
|
}
|
|
6741
|
-
const
|
|
6857
|
+
const reactorDbConfig = this.resolveReactorDbConfig();
|
|
6858
|
+
const baseDatabase = this.kyselyInstance ?? (reactorDbConfig ? await this.createPostgresDatabase(reactorDbConfig) : await createDefaultDatabase());
|
|
6742
6859
|
if (this.migrationStrategy === "auto") {
|
|
6743
6860
|
const result = await runMigrations(baseDatabase, REACTOR_SCHEMA);
|
|
6744
6861
|
if (!result.success && result.error) throw new Error(`Database migration failed: ${result.error.message}`);
|
|
@@ -6764,10 +6881,16 @@ var ReactorBuilder = class {
|
|
|
6764
6881
|
const executionScope = new KyselyExecutionScope(database, operationStore, operationIndex, keyframeStore, writeCache, documentMetaCache, collectionMembershipCache);
|
|
6765
6882
|
let executorManager = this.executorManager;
|
|
6766
6883
|
let executorStartCount = this.executorConfig.maxConcurrency ?? 1;
|
|
6767
|
-
if (!executorManager) if (this.
|
|
6768
|
-
const
|
|
6884
|
+
if (!executorManager) if (this.workerPool) {
|
|
6885
|
+
const pool = this.workerPool;
|
|
6886
|
+
let factory = pool.factory;
|
|
6887
|
+
if (!factory) {
|
|
6888
|
+
if (pool.db === void 0) throw new Error("unreachable: worker pool configured without db or factory");
|
|
6889
|
+
factory = await this.createDefaultWorkerFactory(pool.numWorkers, pool.db, pool.verifier);
|
|
6890
|
+
}
|
|
6891
|
+
const poolManager = new WorkerPoolJobExecutorManager(factory, eventBus, queue, jobTracker, this.logger, resolver, collectionMembershipCache, this.executorConfig.jobTimeoutMs);
|
|
6769
6892
|
executorManager = poolManager;
|
|
6770
|
-
executorStartCount =
|
|
6893
|
+
executorStartCount = pool.numWorkers;
|
|
6771
6894
|
if (resolver instanceof DocumentModelResolver) resolver.setBroadcastHook((entry) => poolManager.loadModel(entry));
|
|
6772
6895
|
} else executorManager = new SimpleJobExecutorManager(() => new SimpleJobExecutor(this.logger, documentModelRegistry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, this.driveContainerTypes, this.executorConfig, this.signatureVerifier, executionScope), eventBus, queue, jobTracker, this.logger, resolver, this.executorConfig.jobTimeoutMs);
|
|
6773
6896
|
await executorManager.start(executorStartCount);
|
|
@@ -6799,6 +6922,7 @@ var ReactorBuilder = class {
|
|
|
6799
6922
|
}
|
|
6800
6923
|
for (const factory of this.readModelFactories) {
|
|
6801
6924
|
const readModel = await factory({
|
|
6925
|
+
documentModelRegistry,
|
|
6802
6926
|
operationIndex,
|
|
6803
6927
|
writeCache,
|
|
6804
6928
|
processorManagerConsistencyTracker
|
|
@@ -6843,6 +6967,19 @@ var ReactorBuilder = class {
|
|
|
6843
6967
|
return module;
|
|
6844
6968
|
}
|
|
6845
6969
|
/**
|
|
6970
|
+
* The single Postgres config for the parent, executor workers, and
|
|
6971
|
+
* projection shards. They must share one physical database (the parent
|
|
6972
|
+
* writes operations; workers and shards read them), so divergent
|
|
6973
|
+
* worker/shard targets throw. `withKysely` overrides the parent and is not
|
|
6974
|
+
* validated against a worker/shard `db`.
|
|
6975
|
+
*/
|
|
6976
|
+
resolveReactorDbConfig() {
|
|
6977
|
+
const workerDb = this.workerPool?.db;
|
|
6978
|
+
const projectionDb = this.projectionShardConfig?.db;
|
|
6979
|
+
if (workerDb && projectionDb && !sameDatabaseTarget(workerDb, projectionDb)) throw new Error("withWorkerPool({ db }) and withProjectionShards({ db }) must address the same Postgres database (same host, port, and database); the parent writes operations there and the projection shards read them.");
|
|
6980
|
+
return workerDb ?? projectionDb;
|
|
6981
|
+
}
|
|
6982
|
+
/**
|
|
6846
6983
|
* Constructs a {@link ProjectionShardManager} bound to the host event
|
|
6847
6984
|
* bus. Builds the default thread-transport factory unless one was
|
|
6848
6985
|
* injected via {@link withProjectionWorkerFactory}. Calls
|
|
@@ -6850,11 +6987,12 @@ var ReactorBuilder = class {
|
|
|
6850
6987
|
* is returned to the caller.
|
|
6851
6988
|
*/
|
|
6852
6989
|
async createProjectionShardManager(config, eventBus) {
|
|
6853
|
-
|
|
6990
|
+
const baseDb = this.resolveReactorDbConfig();
|
|
6991
|
+
if (!baseDb) throw new Error("withProjectionShards requires a db (or an executor worker pool configured with one); projection workers need connection info to open their own pools.");
|
|
6854
6992
|
const models = this.resolvedModelManifest ?? [];
|
|
6855
6993
|
const db = {
|
|
6856
|
-
...
|
|
6857
|
-
poolSize: config.poolSize ??
|
|
6994
|
+
...baseDb,
|
|
6995
|
+
poolSize: config.poolSize ?? baseDb.poolSize,
|
|
6858
6996
|
applicationName: "reactor-projection-shard"
|
|
6859
6997
|
};
|
|
6860
6998
|
const factory = this.projectionWorkerFactory ?? await this.createDefaultProjectionWorkerFactory();
|
|
@@ -6889,18 +7027,21 @@ var ReactorBuilder = class {
|
|
|
6889
7027
|
return () => createProjectionThreadTransport(projectionWorkerEntryPath);
|
|
6890
7028
|
}
|
|
6891
7029
|
/**
|
|
6892
|
-
* Default {@link WorkerFactory} used when
|
|
6893
|
-
*
|
|
6894
|
-
*
|
|
7030
|
+
* Default {@link WorkerFactory} used when the pool options carry no
|
|
7031
|
+
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
7032
|
+
* Worker pointing at the compiled `worker/entry.js`.
|
|
6895
7033
|
*/
|
|
6896
|
-
async createDefaultWorkerFactory(
|
|
7034
|
+
async createDefaultWorkerFactory(numWorkers, db, signatureVerifier) {
|
|
6897
7035
|
const [{ WorkerHandle }, { createThreadTransport }, { workerEntryPath }] = await Promise.all([
|
|
6898
7036
|
import("./worker-handle-B1w03nRA.js"),
|
|
6899
7037
|
import("./transport-ByGviWdZ.js"),
|
|
6900
|
-
import("./worker-
|
|
7038
|
+
import("./worker-BEzk4Q1I.js").then((n) => n.n)
|
|
6901
7039
|
]);
|
|
6902
|
-
const
|
|
6903
|
-
|
|
7040
|
+
const poolConfig = {
|
|
7041
|
+
enabled: true,
|
|
7042
|
+
numWorkers,
|
|
7043
|
+
workerType: "thread"
|
|
7044
|
+
};
|
|
6904
7045
|
const models = this.resolvedModelManifest ?? [];
|
|
6905
7046
|
const logger = this.logger;
|
|
6906
7047
|
return (index) => {
|
|
@@ -7155,6 +7296,74 @@ function driveIdFromUrl(url) {
|
|
|
7155
7296
|
return url.split("/").pop() ?? "";
|
|
7156
7297
|
}
|
|
7157
7298
|
//#endregion
|
|
7299
|
+
//#region src/decision/build-decision-model.ts
|
|
7300
|
+
/**
|
|
7301
|
+
* Reads each projection's stream through the write cache, recording the
|
|
7302
|
+
* revision observed. Static projections resolve first; derived projections
|
|
7303
|
+
* see only those and contribute a map from document id to state. Each
|
|
7304
|
+
* distinct stream is read once and yields one append condition entry.
|
|
7305
|
+
*/
|
|
7306
|
+
async function buildDecisionModel(cache, definition, target, signal) {
|
|
7307
|
+
const decisionModel = definition(target);
|
|
7308
|
+
const projections = Object.entries(decisionModel.projections);
|
|
7309
|
+
const reads = /* @__PURE__ */ new Map();
|
|
7310
|
+
const model = {};
|
|
7311
|
+
for (const [key, projection] of projections) {
|
|
7312
|
+
if (typeof projection.query === "function") continue;
|
|
7313
|
+
model[key] = (await readStream(cache, projection.query, reads, signal)).state;
|
|
7314
|
+
}
|
|
7315
|
+
const staticModel = { ...model };
|
|
7316
|
+
for (const [key, projection] of projections) {
|
|
7317
|
+
if (typeof projection.query !== "function") continue;
|
|
7318
|
+
const queries = projection.query(staticModel);
|
|
7319
|
+
const value = {};
|
|
7320
|
+
for (const query of queries) {
|
|
7321
|
+
const read = await readStream(cache, query, reads, signal);
|
|
7322
|
+
value[query.documentId] = read.state;
|
|
7323
|
+
}
|
|
7324
|
+
model[key] = value;
|
|
7325
|
+
}
|
|
7326
|
+
return {
|
|
7327
|
+
model,
|
|
7328
|
+
appendCondition: { streams: [...reads.values()].map((read) => read.stream) }
|
|
7329
|
+
};
|
|
7330
|
+
}
|
|
7331
|
+
async function readStream(cache, query, reads, signal) {
|
|
7332
|
+
const key = `${query.documentId}:${query.scope}:${query.branch}`;
|
|
7333
|
+
const existing = reads.get(key);
|
|
7334
|
+
if (existing) return existing;
|
|
7335
|
+
const document = await cache.getState(query.documentId, query.scope, query.branch, void 0, signal);
|
|
7336
|
+
const read = {
|
|
7337
|
+
state: document.state[query.scope],
|
|
7338
|
+
stream: {
|
|
7339
|
+
documentId: query.documentId,
|
|
7340
|
+
scope: query.scope,
|
|
7341
|
+
branch: query.branch,
|
|
7342
|
+
revision: observedRevision(document, query.scope)
|
|
7343
|
+
}
|
|
7344
|
+
};
|
|
7345
|
+
reads.set(key, read);
|
|
7346
|
+
return read;
|
|
7347
|
+
}
|
|
7348
|
+
/**
|
|
7349
|
+
* The highest operation index the document reflects for the scope, or -1 if
|
|
7350
|
+
* empty. The last operation's index is the one invariant the write cache
|
|
7351
|
+
* guarantees; header.revision (next-index semantics) is the fallback.
|
|
7352
|
+
*/
|
|
7353
|
+
function observedRevision(document, scope) {
|
|
7354
|
+
if (scope in document.operations) {
|
|
7355
|
+
const operations = document.operations[scope];
|
|
7356
|
+
if (operations.length > 0) return operations[operations.length - 1].index;
|
|
7357
|
+
}
|
|
7358
|
+
if (!(scope in document.header.revision)) return -1;
|
|
7359
|
+
return document.header.revision[scope] - 1;
|
|
7360
|
+
}
|
|
7361
|
+
//#endregion
|
|
7362
|
+
//#region src/read-models/interfaces.ts
|
|
7363
|
+
function supportsLiveReadModelRegistration(coordinator) {
|
|
7364
|
+
return "addReadModel" in coordinator && typeof coordinator.addReadModel === "function";
|
|
7365
|
+
}
|
|
7366
|
+
//#endregion
|
|
7158
7367
|
//#region src/admin/passthrough-keyframe-store.ts
|
|
7159
7368
|
const passthroughKeyframeStore = {
|
|
7160
7369
|
putKeyframe: () => Promise.resolve(),
|
|
@@ -7264,6 +7473,6 @@ var DocumentIntegrityService = class {
|
|
|
7264
7473
|
}
|
|
7265
7474
|
};
|
|
7266
7475
|
//#endregion
|
|
7267
|
-
export { BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, batchOperationsByDocument, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, removeRelationshipAction, runMigrations, sanitizeArg, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
7476
|
+
export { AppendConditionFailedError, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RetryAccounting, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, batchOperationsByDocument, buildDecisionModel, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, removeRelationshipAction, runMigrations, sanitizeArg, supportsLiveReadModelRegistration, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
7268
7477
|
|
|
7269
7478
|
//# sourceMappingURL=index.js.map
|