@powerhousedao/reactor 6.2.3-dev.0 → 6.2.3-dev.10
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-DnU3ZU4H.js → build-worker-executor-_x-U7e_A.js} +2 -2
- package/dist/{build-worker-executor-DnU3ZU4H.js.map → build-worker-executor-_x-U7e_A.js.map} +1 -1
- package/dist/{document-indexer-C5Gsa1B3.js → document-indexer-BRqfWhe1.js} +10 -4
- package/dist/document-indexer-BRqfWhe1.js.map +1 -0
- package/dist/{drive-container-types-yZrksiJR.js → drive-container-types-CE7dxz0_.js} +75 -7
- package/dist/drive-container-types-CE7dxz0_.js.map +1 -0
- package/dist/entry.js +2 -2
- package/dist/index.d.ts +249 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +338 -36
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +3 -3
- package/dist/types-DMKLa0Ok.js.map +1 -1
- package/dist/{worker-HPysBfhx.js → worker-B12tBZmr.js} +2 -2
- package/dist/{worker-HPysBfhx.js.map → worker-B12tBZmr.js.map} +1 -1
- package/package.json +4 -4
- package/dist/document-indexer-C5Gsa1B3.js.map +0 -1
- package/dist/drive-container-types-yZrksiJR.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { $ as parsePagingOptions, A as targetDocumentId, B as DuplicateOperationError, C as InvalidModuleError, D as createEmptyConsistencyToken, E as createConsistencyToken, F as buildDecisionModel, G as AuthorizationDeniedError, H as RevisionMismatchError, I as APPEND_CONDITION_FAILED_PREFIX, J as ExcessiveReshuffleError, K as DocumentDeletedError, L as AppendConditionFailedError, M as selectDecisionModel, N as documentDecisionModel, O as submittedActionIds, P as authDecisionModel, Q as matchesScope, R as DocumentAlreadyExistsError, S as DuplicateModuleError, T as GATED_DOCUMENT_ACTIONS, U as AuthEnforcementDisabledError, V as OptimisticLockError, W as AuthTimestampNotMonotonicError, X as RelationshipNotFoundError, Y as InvalidOperationTimestampError, Z as UpgradePreconditionFailedError, _ as DocumentMetaCache, a as createForwardingPoolInstrumentation, b as JobExecutorEventTypes, c as KyselyKeyframeStore, d as DriveCollectionId, et as throwIfAborted, f as KyselyExecutionScope, g as KyselyOperationIndex, h as KyselyWriteCache, i as runMigrations, j as decideAtHead, k as summarizeSubmittedActions, l as DocumentModelRegistry, m as EventBus, n as REACTOR_SCHEMA, o as instrumentPgPool, p as resolveFeatureFlags, q as DocumentNotFoundError, r as getMigrationStatus, s as KyselyOperationStore, t as DEFAULT_DRIVE_CONTAINER_TYPES, u as SimpleJobExecutor, v as CollectionMembershipCache, w as ModuleNotFoundError, x as DuplicateManifestError, y as DEFAULT_DEFERRED_JOB_TTL_MS, z as DocumentExistence } from "./drive-container-types-CE7dxz0_.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 DOCUMENT_INDEXER_READ_MODEL, c as BaseReadModel, i as KyselyDocumentView, n as ConsistencyTracker, o as DOCUMENT_VIEW_READ_MODEL, r as makeConsistencyKey, s as ReadModelCoordinator, t as KyselyDocumentIndexer } from "./document-indexer-
|
|
4
|
+
import { a as DOCUMENT_INDEXER_READ_MODEL, c as BaseReadModel, i as KyselyDocumentView, n as ConsistencyTracker, o as DOCUMENT_VIEW_READ_MODEL, r as makeConsistencyKey, s as ReadModelCoordinator, t as KyselyDocumentIndexer } from "./document-indexer-BRqfWhe1.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-
|
|
6
|
+
import { t as workerEntryPath } from "./worker-B12tBZmr.js";
|
|
7
7
|
import { DowngradeNotSupportedError, MAX_AUTH_GRANTS, UnsupportedDocumentModelVersionError, actions, actions as documentActions, createPresignedHeader, decide, deserializeSignature, garbageCollect, generateId, groupDocumentType, groupMembershipActionTypes, hashDocumentStateForScope, normalizeDocumentModelVersion, sortOperations, toTransportAction } 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";
|
|
@@ -1248,6 +1248,79 @@ var ReactorClient = class {
|
|
|
1248
1248
|
return this.find({ ids: sourceIds }, view, paging, signal);
|
|
1249
1249
|
}
|
|
1250
1250
|
/**
|
|
1251
|
+
* Retrieves the outgoing relationship edges of a source document, carrying the
|
|
1252
|
+
* metadata and timestamps the far-end documents do not.
|
|
1253
|
+
*/
|
|
1254
|
+
async getOutgoingRelationshipEdges(sourceIdentifier, relationshipType, view, paging, signal) {
|
|
1255
|
+
this.logger.verbose("getOutgoingRelationshipEdges(@sourceIdentifier, @relationshipType, @view, @paging)", sourceIdentifier, relationshipType, view, paging);
|
|
1256
|
+
const sourceId = await this.documentView.resolveIdOrSlug(sourceIdentifier, view, void 0, signal);
|
|
1257
|
+
const edges = await this.reactor.getOutgoingRelationshipEdges(sourceId, relationshipType, paging, void 0, signal);
|
|
1258
|
+
return this.gateEdges(edges, "targetId", view, signal);
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Retrieves the incoming relationship edges of a target document, carrying the
|
|
1262
|
+
* metadata and timestamps the far-end documents do not.
|
|
1263
|
+
*/
|
|
1264
|
+
async getIncomingRelationshipEdges(targetIdentifier, relationshipType, view, paging, signal) {
|
|
1265
|
+
this.logger.verbose("getIncomingRelationshipEdges(@targetIdentifier, @relationshipType, @view, @paging)", targetIdentifier, relationshipType, view, paging);
|
|
1266
|
+
const targetId = await this.documentView.resolveIdOrSlug(targetIdentifier, view, void 0, signal);
|
|
1267
|
+
const edges = await this.reactor.getIncomingRelationshipEdges(targetId, relationshipType, paging, void 0, signal);
|
|
1268
|
+
return this.gateEdges(edges, "sourceId", view, signal);
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Drops the edges whose far-end document the subject may read no domain scope
|
|
1272
|
+
* of. An edge is withheld whole rather than stripped of its metadata: the
|
|
1273
|
+
* document-shaped relationship reads already answer with the far end stripped
|
|
1274
|
+
* to the scopes the gate allows, so the far end's existence is disclosed
|
|
1275
|
+
* either way, but an edge's metadata is content about the pair that the far
|
|
1276
|
+
* end's own reads would refuse. An edge to a far end stripped to nothing
|
|
1277
|
+
* therefore carries content past a refusal, and there is no useful shell to
|
|
1278
|
+
* hand back in its place.
|
|
1279
|
+
*
|
|
1280
|
+
* `nextCursor` and `options` are left as the underlying stream reported them,
|
|
1281
|
+
* because a caller must feed them back to resume from the right position. A
|
|
1282
|
+
* gated page can therefore be shorter than the limit it asked for.
|
|
1283
|
+
*/
|
|
1284
|
+
async gateEdges(page, farEnd, view, signal) {
|
|
1285
|
+
const ids = [...new Set(page.results.map((edge) => edge[farEnd]))];
|
|
1286
|
+
if (ids.length === 0) return page;
|
|
1287
|
+
const farEndView = {
|
|
1288
|
+
subject: view?.subject,
|
|
1289
|
+
branch: view?.branch
|
|
1290
|
+
};
|
|
1291
|
+
const documents = await this.reactor.find({ ids }, farEndView, {
|
|
1292
|
+
cursor: "0",
|
|
1293
|
+
limit: ids.length
|
|
1294
|
+
}, void 0, signal);
|
|
1295
|
+
const readable = new Map(await Promise.all(documents.results.map(async (doc) => {
|
|
1296
|
+
const allows = await this.readableScopes(doc, view, signal);
|
|
1297
|
+
const domainScopes = Object.keys(doc.state).filter((scope) => !ALWAYS_READABLE_SCOPES.has(scope));
|
|
1298
|
+
return [doc.header.id, domainScopes.length === 0 || domainScopes.some(allows)];
|
|
1299
|
+
})));
|
|
1300
|
+
const results = page.results.filter((edge) => readable.get(edge[farEnd]) !== false);
|
|
1301
|
+
if (results.length === page.results.length) return page;
|
|
1302
|
+
const nextPage = page.next;
|
|
1303
|
+
return {
|
|
1304
|
+
...page,
|
|
1305
|
+
results,
|
|
1306
|
+
next: nextPage ? async () => this.gateEdges(await nextPage(), farEnd, view, signal) : void 0
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
/**
|
|
1310
|
+
* One relationship edge, or undefined when it does not exist. A point lookup:
|
|
1311
|
+
* the pair is filtered in SQL rather than scanned out of the source's edge
|
|
1312
|
+
* list, which on a drive with thousands of children is the difference between
|
|
1313
|
+
* one query and dozens.
|
|
1314
|
+
*/
|
|
1315
|
+
async readRelationshipEdge(sourceIdentifier, targetIdentifier, relationshipType, view, signal) {
|
|
1316
|
+
const sourceId = await this.documentView.resolveIdOrSlug(sourceIdentifier, view, void 0, signal);
|
|
1317
|
+
const targetId = await this.documentView.resolveIdOrSlug(targetIdentifier, view, void 0, signal);
|
|
1318
|
+
return (await this.documentIndexer.getDirectedRelationships(sourceId, targetId, [relationshipType], {
|
|
1319
|
+
cursor: "0",
|
|
1320
|
+
limit: 1
|
|
1321
|
+
}, void 0, signal)).results[0];
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1251
1324
|
* Filters documents by criteria and returns a list of them
|
|
1252
1325
|
*/
|
|
1253
1326
|
async find(search, view, paging, signal) {
|
|
@@ -1515,9 +1588,21 @@ var ReactorClient = class {
|
|
|
1515
1588
|
/**
|
|
1516
1589
|
* Adds multiple documents as children to another and waits for completion
|
|
1517
1590
|
*/
|
|
1518
|
-
async addRelationship(sourceIdentifier, targetIdentifier, relationshipType, branch = "main", signal) {
|
|
1519
|
-
this.logger.verbose("addRelationship(@sourceIdentifier, @targetIdentifier, @relationshipType, @branch)", sourceIdentifier, targetIdentifier, relationshipType, branch);
|
|
1520
|
-
const jobInfo = await this.reactor.addRelationship(sourceIdentifier, targetIdentifier, relationshipType, branch, this.signer, signal);
|
|
1591
|
+
async addRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch = "main", signal) {
|
|
1592
|
+
this.logger.verbose("addRelationship(@sourceIdentifier, @targetIdentifier, @relationshipType, @metadata, @branch)", sourceIdentifier, targetIdentifier, relationshipType, metadata, branch);
|
|
1593
|
+
const jobInfo = await this.reactor.addRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1594
|
+
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1595
|
+
if (completedJob.status === JobStatus.FAILED) throw new Error(completedJob.error?.message);
|
|
1596
|
+
const result = await this.reactor.getByIdOrSlug(sourceIdentifier, { branch }, completedJob.consistencyToken, signal);
|
|
1597
|
+
return this.gateDocument(result, { branch }, signal);
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Replaces the metadata of an existing relationship and waits for completion.
|
|
1601
|
+
*/
|
|
1602
|
+
async updateRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch = "main", signal) {
|
|
1603
|
+
this.logger.verbose("updateRelationship(@sourceIdentifier, @targetIdentifier, @relationshipType, @metadata, @branch)", sourceIdentifier, targetIdentifier, relationshipType, metadata, branch);
|
|
1604
|
+
if (!await this.readRelationshipEdge(sourceIdentifier, targetIdentifier, relationshipType, { branch }, signal)) throw new RelationshipNotFoundError(sourceIdentifier, targetIdentifier, relationshipType);
|
|
1605
|
+
const jobInfo = await this.reactor.updateRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1521
1606
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1522
1607
|
if (completedJob.status === JobStatus.FAILED) throw new Error(completedJob.error?.message);
|
|
1523
1608
|
const result = await this.reactor.getByIdOrSlug(sourceIdentifier, { branch }, completedJob.consistencyToken, signal);
|
|
@@ -1539,10 +1624,11 @@ var ReactorClient = class {
|
|
|
1539
1624
|
*/
|
|
1540
1625
|
async moveRelationship(sourceParentIdentifier, targetParentIdentifier, targetIdentifier, relationshipType, branch = "main", signal) {
|
|
1541
1626
|
this.logger.verbose("moveRelationship(@sourceParentIdentifier, @targetParentIdentifier, @targetIdentifier, @relationshipType, @branch)", sourceParentIdentifier, targetParentIdentifier, targetIdentifier, relationshipType, branch);
|
|
1627
|
+
const metadata = (await this.readRelationshipEdge(sourceParentIdentifier, targetIdentifier, relationshipType, { branch }, signal))?.metadata;
|
|
1542
1628
|
const removeJobInfo = await this.reactor.removeRelationship(sourceParentIdentifier, targetIdentifier, relationshipType, branch, this.signer, signal);
|
|
1543
1629
|
const removeCompletedJob = await this.waitForJob(removeJobInfo, signal);
|
|
1544
1630
|
if (removeCompletedJob.status === JobStatus.FAILED) throw new Error(removeCompletedJob.error?.message);
|
|
1545
|
-
const addJobInfo = await this.reactor.addRelationship(targetParentIdentifier, targetIdentifier, relationshipType, branch, this.signer, signal);
|
|
1631
|
+
const addJobInfo = await this.reactor.addRelationship(targetParentIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1546
1632
|
const addCompletedJob = await this.waitForJob(addJobInfo, signal);
|
|
1547
1633
|
if (addCompletedJob.status === JobStatus.FAILED) throw new Error(addCompletedJob.error?.message);
|
|
1548
1634
|
const sourceResult = await this.reactor.getByIdOrSlug(sourceParentIdentifier, { branch }, removeCompletedJob.consistencyToken, signal);
|
|
@@ -2212,6 +2298,7 @@ var WorkerPoolJobExecutorManager = class {
|
|
|
2212
2298
|
jobId: job.id,
|
|
2213
2299
|
operations: payload.operations,
|
|
2214
2300
|
jobMeta: payload.jobMeta,
|
|
2301
|
+
submittedActionIds: submittedActionIds(job),
|
|
2215
2302
|
collectionMemberships
|
|
2216
2303
|
};
|
|
2217
2304
|
try {
|
|
@@ -2495,7 +2582,8 @@ var InMemoryJobTracker = class {
|
|
|
2495
2582
|
this.jobs.set(jobId, {
|
|
2496
2583
|
...job,
|
|
2497
2584
|
status: JobStatus.WRITE_READY,
|
|
2498
|
-
consistencyToken
|
|
2585
|
+
consistencyToken,
|
|
2586
|
+
result: summarizeSubmittedActions(event.operations, event.submittedActionIds)
|
|
2499
2587
|
});
|
|
2500
2588
|
}
|
|
2501
2589
|
}
|
|
@@ -4229,9 +4317,35 @@ const DRIVE_AUTH_ERROR_MESSAGES = {
|
|
|
4229
4317
|
forbidden: "Forbidden: insufficient permissions",
|
|
4230
4318
|
authenticationRequired: "Forbidden: authentication required"
|
|
4231
4319
|
};
|
|
4320
|
+
/**
|
|
4321
|
+
* A non-GraphQL HTTP failure against a drive endpoint.
|
|
4322
|
+
*
|
|
4323
|
+
* Drive discovery (`GET <base>/d/:drive`) is REST, not GraphQL, so its
|
|
4324
|
+
* failures cannot be a `GraphQLRequestError` without the name lying about
|
|
4325
|
+
* what was called. It carries the status for the same reason that one does:
|
|
4326
|
+
* `isDriveAuthError` is what decides whether a failure prompts a login, and a
|
|
4327
|
+
* bare `Error` tells it nothing.
|
|
4328
|
+
*/
|
|
4329
|
+
var DriveRequestError = class extends Error {
|
|
4330
|
+
statusCode;
|
|
4331
|
+
constructor(message, statusCode) {
|
|
4332
|
+
super(message);
|
|
4333
|
+
this.name = "DriveRequestError";
|
|
4334
|
+
this.statusCode = statusCode;
|
|
4335
|
+
}
|
|
4336
|
+
};
|
|
4232
4337
|
/** True when the remote rejected the caller as unauthenticated/unauthorized:
|
|
4233
|
-
* an HTTP 401/403, or a Forbidden/Unauthorized GraphQL error.
|
|
4338
|
+
* an HTTP 401/403, or a Forbidden/Unauthorized GraphQL error.
|
|
4339
|
+
*
|
|
4340
|
+
* 403 and 401 only — NOT 404. The drive info endpoint answers a drive the
|
|
4341
|
+
* caller may not read with the same 404 it gives a drive that does not exist,
|
|
4342
|
+
* so that an unauthorized caller cannot enumerate drives by probing slugs.
|
|
4343
|
+
* That is deliberate, and it costs exactly this: a protected drive is
|
|
4344
|
+
* indistinguishable from a typo, and prompting for a login on every 404 would
|
|
4345
|
+
* fire on every mistyped URL. See the `WWW-Authenticate` note on the endpoint
|
|
4346
|
+
* for the signal that would let a client tell the two apart. */
|
|
4234
4347
|
function isDriveAuthError(error) {
|
|
4348
|
+
if (error instanceof DriveRequestError) return error.statusCode === 401 || error.statusCode === 403;
|
|
4235
4349
|
if (!(error instanceof GraphQLRequestError)) return false;
|
|
4236
4350
|
if (error.category === "http") return error.statusCode === 401 || error.statusCode === 403;
|
|
4237
4351
|
if (error.category === "graphql") return Object.values(DRIVE_AUTH_ERROR_MESSAGES).some((m) => error.message.includes(m));
|
|
@@ -5028,6 +5142,10 @@ var GqlRequestChannel = class {
|
|
|
5028
5142
|
if (this.isShutdown) return;
|
|
5029
5143
|
this.pollTimer.triggerNow();
|
|
5030
5144
|
}
|
|
5145
|
+
/** This channel polls a remote itself; it has no holder to hear from. */
|
|
5146
|
+
notePoll() {}
|
|
5147
|
+
/** No holder, so nothing this channel reports may strand one. */
|
|
5148
|
+
lastHolderPollUtcMs() {}
|
|
5031
5149
|
/**
|
|
5032
5150
|
* Initializes the channel by registering it on the remote server and starting polling.
|
|
5033
5151
|
*/
|
|
@@ -5611,6 +5729,7 @@ var GqlResponseChannel = class {
|
|
|
5611
5729
|
lastPersistedOutboxOrdinal = 0;
|
|
5612
5730
|
evictedOutboxFloor = Number.POSITIVE_INFINITY;
|
|
5613
5731
|
appliedOutboxOrdinal = 0;
|
|
5732
|
+
lastPollUtcMs = Date.now();
|
|
5614
5733
|
connectionState = "connecting";
|
|
5615
5734
|
connectionStateCallbacks = /* @__PURE__ */ new Set();
|
|
5616
5735
|
constructor(logger, channelId, remoteName, cursorStorage) {
|
|
@@ -5653,7 +5772,7 @@ var GqlResponseChannel = class {
|
|
|
5653
5772
|
return {
|
|
5654
5773
|
state: this.connectionState,
|
|
5655
5774
|
failureCount: 0,
|
|
5656
|
-
lastSuccessUtcMs:
|
|
5775
|
+
lastSuccessUtcMs: this.lastPollUtcMs,
|
|
5657
5776
|
lastFailureUtcMs: 0,
|
|
5658
5777
|
pushBlocked: false,
|
|
5659
5778
|
pushFailureCount: 0,
|
|
@@ -5669,6 +5788,13 @@ var GqlResponseChannel = class {
|
|
|
5669
5788
|
}
|
|
5670
5789
|
/** Response channels are push-driven; resolvers populate mailboxes directly. */
|
|
5671
5790
|
triggerPull() {}
|
|
5791
|
+
notePoll() {
|
|
5792
|
+
this.lastPollUtcMs = Date.now();
|
|
5793
|
+
}
|
|
5794
|
+
/** This channel is served: its holder's polls are the liveness it reports. */
|
|
5795
|
+
lastHolderPollUtcMs() {
|
|
5796
|
+
return this.lastPollUtcMs;
|
|
5797
|
+
}
|
|
5672
5798
|
async init() {
|
|
5673
5799
|
const cursors = await this.cursorStorage.list(this.remoteName);
|
|
5674
5800
|
const inboxOrdinal = cursors.find((c) => c.cursorType === "inbox")?.cursorOrdinal ?? 0;
|
|
@@ -6348,9 +6474,19 @@ var OutboxMode = /* @__PURE__ */ function(OutboxMode) {
|
|
|
6348
6474
|
const defaultSyncManagerConfig = {
|
|
6349
6475
|
maxDeadLettersPerRemote: 100,
|
|
6350
6476
|
maxInboxBatchSize: 32,
|
|
6351
|
-
maxHeldOperationsPerRemote: 1e4
|
|
6477
|
+
maxHeldOperationsPerRemote: 1e4,
|
|
6478
|
+
staleRemotePollWindowMs: 5 * 6e4
|
|
6352
6479
|
};
|
|
6353
6480
|
const PLAN_KEY_TO_JOB_UUID_CAP = 1e4;
|
|
6481
|
+
/**
|
|
6482
|
+
* Whether a channel failure says the caller could not authenticate or could not
|
|
6483
|
+
* reach the remote, rather than that the remote itself is misconfigured. The
|
|
6484
|
+
* remote record stays on disk for these so a retry after sign-in can re-add it.
|
|
6485
|
+
*/
|
|
6486
|
+
function isCredentialOrNetworkError(error) {
|
|
6487
|
+
if (isDriveAuthError(error)) return true;
|
|
6488
|
+
return error instanceof GraphQLRequestError && error.category === "network";
|
|
6489
|
+
}
|
|
6354
6490
|
/** Where a sync operation's run of ordinals begins. */
|
|
6355
6491
|
function firstOrdinalOf(syncOp) {
|
|
6356
6492
|
return syncOp.operations.length > 0 ? syncOp.operations[0].context.ordinal : 0;
|
|
@@ -6379,6 +6515,11 @@ var SyncManager = class {
|
|
|
6379
6515
|
backfillAbortControllers = /* @__PURE__ */ new Map();
|
|
6380
6516
|
planKeyToJobUuid = /* @__PURE__ */ new Map();
|
|
6381
6517
|
evictedOutboxFloors = /* @__PURE__ */ new Map();
|
|
6518
|
+
prunePending = /* @__PURE__ */ new Set();
|
|
6519
|
+
pruneChain = Promise.resolve();
|
|
6520
|
+
derivingOutboxes = 0;
|
|
6521
|
+
pruneDrainDeferred = false;
|
|
6522
|
+
removing = /* @__PURE__ */ new Set();
|
|
6382
6523
|
lastEnqueuedJobIdByKey = /* @__PURE__ */ new Map();
|
|
6383
6524
|
inboxChunkChain = Promise.resolve();
|
|
6384
6525
|
constructor(logger, remoteStorage, cursorStorage, deadLetterStorage, channelFactory, operationIndex, reactor, eventBus, driveContainerTypes, config = {}) {
|
|
@@ -6430,7 +6571,7 @@ var SyncManager = class {
|
|
|
6430
6571
|
await channel.init();
|
|
6431
6572
|
} catch (error) {
|
|
6432
6573
|
this.logger.error("Error initializing channel for remote (@name, @error)", record.name, error instanceof Error ? error.message : String(error));
|
|
6433
|
-
this.
|
|
6574
|
+
await this.dropRemoteAfterFailedInit(remote, false);
|
|
6434
6575
|
continue;
|
|
6435
6576
|
}
|
|
6436
6577
|
const outboxAckOrdinal = remote.channel.outbox.ackOrdinal;
|
|
@@ -6442,6 +6583,7 @@ var SyncManager = class {
|
|
|
6442
6583
|
this.logger.error("Backfill failed for remote @RemoteName: @Error", remote.meta.name, error instanceof Error ? error : new Error(String(error)));
|
|
6443
6584
|
}).finally(() => {
|
|
6444
6585
|
this.backfillAbortControllers.delete(record.name);
|
|
6586
|
+
this.drainPrunes();
|
|
6445
6587
|
});
|
|
6446
6588
|
}
|
|
6447
6589
|
}
|
|
@@ -6455,6 +6597,8 @@ var SyncManager = class {
|
|
|
6455
6597
|
this.backfillAbortControllers.clear();
|
|
6456
6598
|
this.planKeyToJobUuid.clear();
|
|
6457
6599
|
this.lastEnqueuedJobIdByKey.clear();
|
|
6600
|
+
this.prunePending.clear();
|
|
6601
|
+
this.pruneDrainDeferred = false;
|
|
6458
6602
|
this.batchAggregator.clear();
|
|
6459
6603
|
if (this.eventUnsubscribe) {
|
|
6460
6604
|
this.eventUnsubscribe();
|
|
@@ -6548,8 +6692,7 @@ var SyncManager = class {
|
|
|
6548
6692
|
try {
|
|
6549
6693
|
await channel.init();
|
|
6550
6694
|
} catch (error) {
|
|
6551
|
-
this.
|
|
6552
|
-
await this.remoteStorage.remove(name);
|
|
6695
|
+
await this.dropRemoteAfterFailedInit(remote, !isCredentialOrNetworkError(error));
|
|
6553
6696
|
throw error;
|
|
6554
6697
|
}
|
|
6555
6698
|
const backfillController = new AbortController();
|
|
@@ -6559,6 +6702,7 @@ var SyncManager = class {
|
|
|
6559
6702
|
this.logger.error("Backfill failed for remote @RemoteName: @Error", remote.meta.name, error instanceof Error ? error : new Error(String(error)));
|
|
6560
6703
|
}).finally(() => {
|
|
6561
6704
|
this.backfillAbortControllers.delete(name);
|
|
6705
|
+
this.drainPrunes();
|
|
6562
6706
|
});
|
|
6563
6707
|
return remote;
|
|
6564
6708
|
}
|
|
@@ -6570,21 +6714,62 @@ var SyncManager = class {
|
|
|
6570
6714
|
async remove(name) {
|
|
6571
6715
|
const remote = this.remotes.get(name);
|
|
6572
6716
|
if (!remote) throw new Error(`Remote with name '${name}' does not exist`);
|
|
6717
|
+
this.removing.add(name);
|
|
6718
|
+
try {
|
|
6719
|
+
await this.teardownRemoteResources(remote);
|
|
6720
|
+
await this.remoteStorage.remove(name);
|
|
6721
|
+
await this.cursorStorage.remove(name);
|
|
6722
|
+
} finally {
|
|
6723
|
+
this.remotes.delete(name);
|
|
6724
|
+
this.removing.delete(name);
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6727
|
+
/**
|
|
6728
|
+
* Drops a remote whose channel.init() rejected, optionally removing its
|
|
6729
|
+
* stored record. Ordered like remove(): the registry slot is released last,
|
|
6730
|
+
* so a concurrent add of the same name cannot slip in and have its record
|
|
6731
|
+
* deleted by the removal below. A failure to tear down must not replace the
|
|
6732
|
+
* init error the caller has to classify.
|
|
6733
|
+
*/
|
|
6734
|
+
async dropRemoteAfterFailedInit(remote, removeStorageRecord) {
|
|
6735
|
+
const name = remote.meta.name;
|
|
6736
|
+
this.removing.add(name);
|
|
6737
|
+
try {
|
|
6738
|
+
await this.teardownRemoteResources(remote);
|
|
6739
|
+
if (removeStorageRecord) await this.remoteStorage.remove(name);
|
|
6740
|
+
} catch (error) {
|
|
6741
|
+
this.logger.error("Error tearing down remote after failed init (@name, @error)", name, error instanceof Error ? error.message : String(error));
|
|
6742
|
+
} finally {
|
|
6743
|
+
this.remotes.delete(name);
|
|
6744
|
+
this.removing.delete(name);
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
/**
|
|
6748
|
+
* Releases everything wiring a remote up holds: the in-flight backfill, the
|
|
6749
|
+
* channel, the status tracker entry and the connection-state subscription.
|
|
6750
|
+
* The registry slot is deliberately NOT released here -- the caller holds it
|
|
6751
|
+
* until any storage removal has finished, so a concurrent add of the same
|
|
6752
|
+
* name is refused for the whole teardown.
|
|
6753
|
+
*/
|
|
6754
|
+
async teardownRemoteResources(remote) {
|
|
6755
|
+
const name = remote.meta.name;
|
|
6573
6756
|
const backfillController = this.backfillAbortControllers.get(name);
|
|
6574
6757
|
if (backfillController) {
|
|
6575
6758
|
backfillController.abort();
|
|
6576
6759
|
this.backfillAbortControllers.delete(name);
|
|
6577
6760
|
}
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6761
|
+
try {
|
|
6762
|
+
await remote.channel.shutdown();
|
|
6763
|
+
} finally {
|
|
6764
|
+
this.syncStatusTracker.untrackRemote(name);
|
|
6765
|
+
const unsub = this.connectionStateUnsubscribes.get(name);
|
|
6766
|
+
if (unsub) {
|
|
6767
|
+
unsub();
|
|
6768
|
+
this.connectionStateUnsubscribes.delete(name);
|
|
6769
|
+
}
|
|
6770
|
+
this.evictedOutboxFloors.delete(name);
|
|
6771
|
+
this.prunePending.delete(name);
|
|
6586
6772
|
}
|
|
6587
|
-
this.remotes.delete(name);
|
|
6588
6773
|
}
|
|
6589
6774
|
list() {
|
|
6590
6775
|
return Array.from(this.remotes.values());
|
|
@@ -6679,7 +6864,7 @@ var SyncManager = class {
|
|
|
6679
6864
|
this.logger.debug("Loaded @count persisted dead letters for remote @name", records.length, remote.meta.name);
|
|
6680
6865
|
}
|
|
6681
6866
|
getRemotesForCollection(collectionId) {
|
|
6682
|
-
return Array.from(this.remotes.values()).filter((remote) => remote.meta.collectionId.key === collectionId);
|
|
6867
|
+
return Array.from(this.remotes.values()).filter((remote) => remote.meta.collectionId.key === collectionId && !this.removing.has(remote.meta.name));
|
|
6683
6868
|
}
|
|
6684
6869
|
async processCompleteBatch(batch) {
|
|
6685
6870
|
if (this.isShutdown) return;
|
|
@@ -6690,7 +6875,11 @@ var SyncManager = class {
|
|
|
6690
6875
|
for (const remote of remotes) if (!affectedRemotes.includes(remote)) affectedRemotes.push(remote);
|
|
6691
6876
|
}
|
|
6692
6877
|
for (const remote of affectedRemotes) trimMailboxFromBatch(remote.channel.inbox, batch);
|
|
6693
|
-
for (const remote of affectedRemotes)
|
|
6878
|
+
for (const remote of affectedRemotes) {
|
|
6879
|
+
if (!this.remotes.has(remote.meta.name) || this.removing.has(remote.meta.name)) continue;
|
|
6880
|
+
await this.updateOutbox(remote, remote.channel.outbox.latestOrdinal, OutboxMode.BatchTriggered);
|
|
6881
|
+
}
|
|
6882
|
+
await this.drainPrunes();
|
|
6694
6883
|
}
|
|
6695
6884
|
handleInboxAdded(remote, syncOps) {
|
|
6696
6885
|
if (this.isShutdown) return;
|
|
@@ -6891,15 +7080,95 @@ var SyncManager = class {
|
|
|
6891
7080
|
const floor = firstOrdinalOf(evicted[0]);
|
|
6892
7081
|
const known = this.evictedOutboxFloors.get(remote.meta.name);
|
|
6893
7082
|
this.evictedOutboxFloors.set(remote.meta.name, known === void 0 ? floor : Math.min(known, floor));
|
|
6894
|
-
this.
|
|
7083
|
+
const staleMs = this.stalePollAgeMs(remote);
|
|
7084
|
+
if (staleMs !== void 0) {
|
|
7085
|
+
let held = kept;
|
|
7086
|
+
for (const syncOp of evicted) held += syncOp.operations.length;
|
|
7087
|
+
if (!this.prunePending.has(remote.meta.name)) {
|
|
7088
|
+
this.prunePending.add(remote.meta.name);
|
|
7089
|
+
this.logger.warn("Outbox for @RemoteName (@Collection) is past its bound of @Cap operations holding @Held, and it has not been polled for @StaleMs ms; marking the channel for removal once this derivation ends", remote.meta.name, remote.meta.collectionId.key, cap, held, staleMs);
|
|
7090
|
+
}
|
|
7091
|
+
} else this.logger.warn("Outbox for @RemoteName is past its bound of @Cap operations; evicting @Count entries from ordinal @Floor, to be derived again once it drains", remote.meta.name, cap, evicted.length, floor);
|
|
6895
7092
|
remote.channel.outbox.remove(...evicted);
|
|
6896
7093
|
}
|
|
7094
|
+
/**
|
|
7095
|
+
* How long a served remote's holder has been silent, if past the window.
|
|
7096
|
+
*
|
|
7097
|
+
* The channel is asked, rather than its config inspected: SyncManager serves
|
|
7098
|
+
* and subscribes with the same interface, both kinds report lastSuccessUtcMs,
|
|
7099
|
+
* and the caller-supplied channelConfig.type is a free-form string the
|
|
7100
|
+
* factories do not read -- so neither could tell a dead served channel from a
|
|
7101
|
+
* client whose switchboard is merely unreachable. Only a channel that claims
|
|
7102
|
+
* a holder by reporting when it last heard from one can be removed for that
|
|
7103
|
+
* holder's silence; a channel that reports nothing (or 0) is never pruned.
|
|
7104
|
+
*/
|
|
7105
|
+
stalePollAgeMs(remote) {
|
|
7106
|
+
const last = remote.channel.lastHolderPollUtcMs();
|
|
7107
|
+
if (last === void 0 || last <= 0) return;
|
|
7108
|
+
const age = Date.now() - last;
|
|
7109
|
+
return age >= this.config.staleRemotePollWindowMs ? age : void 0;
|
|
7110
|
+
}
|
|
7111
|
+
/**
|
|
7112
|
+
* Removes the remotes marked stale during eviction.
|
|
7113
|
+
*
|
|
7114
|
+
* Removing a remote that a derivation is still iterating would pull its
|
|
7115
|
+
* mailboxes out from under it, so a drain that arrives during one is deferred
|
|
7116
|
+
* rather than run; the last derivation to finish re-arms it.
|
|
7117
|
+
*/
|
|
7118
|
+
drainPrunes() {
|
|
7119
|
+
if (this.derivingOutboxes > 0) {
|
|
7120
|
+
this.pruneDrainDeferred = true;
|
|
7121
|
+
return Promise.resolve();
|
|
7122
|
+
}
|
|
7123
|
+
const next = this.pruneChain.then(async () => {
|
|
7124
|
+
if (this.isShutdown) return;
|
|
7125
|
+
for (const name of [...this.prunePending]) {
|
|
7126
|
+
if (this.derivingOutboxes > 0) {
|
|
7127
|
+
this.pruneDrainDeferred = true;
|
|
7128
|
+
return;
|
|
7129
|
+
}
|
|
7130
|
+
this.prunePending.delete(name);
|
|
7131
|
+
const remote = this.remotes.get(name);
|
|
7132
|
+
if (!remote) continue;
|
|
7133
|
+
if (this.stalePollAgeMs(remote) === void 0) {
|
|
7134
|
+
this.logger.info("Stale removal of @name revoked: its holder polled while the outbox was being derived", name);
|
|
7135
|
+
continue;
|
|
7136
|
+
}
|
|
7137
|
+
try {
|
|
7138
|
+
await this.remove(name);
|
|
7139
|
+
} catch (error) {
|
|
7140
|
+
this.logger.error("Failed to remove stale remote (@name, @error)", name, error instanceof Error ? error.message : String(error));
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
});
|
|
7144
|
+
this.pruneChain = next.catch(() => {});
|
|
7145
|
+
return next;
|
|
7146
|
+
}
|
|
6897
7147
|
outboxOperationCount(remote) {
|
|
6898
7148
|
let count = 0;
|
|
6899
7149
|
for (const syncOp of remote.channel.outbox.items) count += syncOp.operations.length;
|
|
6900
7150
|
return count;
|
|
6901
7151
|
}
|
|
7152
|
+
/**
|
|
7153
|
+
* Derives this remote's outbox, holding off prunes for the duration.
|
|
7154
|
+
*
|
|
7155
|
+
* A backfill elsewhere can finish at any await in here and drain the prunes
|
|
7156
|
+
* it marked; the count is what keeps that drain from removing the remote this
|
|
7157
|
+
* call is still adding to.
|
|
7158
|
+
*/
|
|
6902
7159
|
async updateOutbox(remote, ackOrdinal, mode = OutboxMode.Backfill, signal) {
|
|
7160
|
+
this.derivingOutboxes++;
|
|
7161
|
+
try {
|
|
7162
|
+
await this.deriveOutbox(remote, ackOrdinal, mode, signal);
|
|
7163
|
+
} finally {
|
|
7164
|
+
this.derivingOutboxes--;
|
|
7165
|
+
if (this.derivingOutboxes === 0 && this.pruneDrainDeferred) {
|
|
7166
|
+
this.pruneDrainDeferred = false;
|
|
7167
|
+
this.drainPrunes();
|
|
7168
|
+
}
|
|
7169
|
+
}
|
|
7170
|
+
}
|
|
7171
|
+
async deriveOutbox(remote, ackOrdinal, mode, signal) {
|
|
6903
7172
|
const composedSignal = signal ? AbortSignal.any([signal, this.abortController.signal]) : this.abortController.signal;
|
|
6904
7173
|
const startOrdinal = this.refillOrdinal(remote, ackOrdinal);
|
|
6905
7174
|
let maxOrdinal = startOrdinal;
|
|
@@ -7001,6 +7270,10 @@ var SyncBuilder = class {
|
|
|
7001
7270
|
this.config.maxHeldOperationsPerRemote = limit;
|
|
7002
7271
|
return this;
|
|
7003
7272
|
}
|
|
7273
|
+
withStaleRemotePollWindowMs(windowMs) {
|
|
7274
|
+
this.config.staleRemotePollWindowMs = windowMs;
|
|
7275
|
+
return this;
|
|
7276
|
+
}
|
|
7004
7277
|
build(reactor, logger, operationIndex, eventBus, db, driveContainerTypes) {
|
|
7005
7278
|
return this.buildModule(reactor, logger, operationIndex, eventBus, db, driveContainerTypes).syncManager;
|
|
7006
7279
|
}
|
|
@@ -7166,6 +7439,16 @@ var Reactor = class {
|
|
|
7166
7439
|
throwIfAborted(signal, () => new AbortError());
|
|
7167
7440
|
return relationships.results.map((rel) => rel.sourceId);
|
|
7168
7441
|
}
|
|
7442
|
+
async getOutgoingRelationshipEdges(sourceId, relationshipType, paging, consistencyToken, signal) {
|
|
7443
|
+
const relationships = await this.documentIndexer.getOutgoing(sourceId, relationshipType ? [relationshipType] : void 0, paging, consistencyToken, signal);
|
|
7444
|
+
throwIfAborted(signal, () => new AbortError());
|
|
7445
|
+
return relationships;
|
|
7446
|
+
}
|
|
7447
|
+
async getIncomingRelationshipEdges(targetId, relationshipType, paging, consistencyToken, signal) {
|
|
7448
|
+
const relationships = await this.documentIndexer.getIncoming(targetId, relationshipType ? [relationshipType] : void 0, paging, consistencyToken, signal);
|
|
7449
|
+
throwIfAborted(signal, () => new AbortError());
|
|
7450
|
+
return relationships;
|
|
7451
|
+
}
|
|
7169
7452
|
async getOperations(documentId, view, filter, paging, consistencyToken, signal) {
|
|
7170
7453
|
this.logger.verbose("getOperations(@documentId, @view, @filter, @paging)", documentId, view, filter, paging);
|
|
7171
7454
|
const branch = view?.branch || "main";
|
|
@@ -7528,10 +7811,17 @@ var Reactor = class {
|
|
|
7528
7811
|
}
|
|
7529
7812
|
return { jobs: Object.fromEntries(jobInfos) };
|
|
7530
7813
|
}
|
|
7531
|
-
async addRelationship(sourceId, targetId, relationshipType, branch = "main", signer, signal) {
|
|
7532
|
-
this.logger.verbose("addRelationship(@sourceId, @targetId, @relationshipType, @branch)", sourceId, targetId, relationshipType, branch);
|
|
7814
|
+
async addRelationship(sourceId, targetId, relationshipType, metadata, branch = "main", signer, signal) {
|
|
7815
|
+
this.logger.verbose("addRelationship(@sourceId, @targetId, @relationshipType, @metadata, @branch)", sourceId, targetId, relationshipType, metadata, branch);
|
|
7533
7816
|
throwIfAborted(signal, () => new AbortError());
|
|
7534
|
-
let actions = [addRelationshipAction(sourceId, targetId, relationshipType)];
|
|
7817
|
+
let actions = [addRelationshipAction(sourceId, targetId, relationshipType, metadata)];
|
|
7818
|
+
if (signer) actions = await signActions(actions, signer, signal);
|
|
7819
|
+
return await this.execute(sourceId, branch, actions, signal);
|
|
7820
|
+
}
|
|
7821
|
+
async updateRelationship(sourceId, targetId, relationshipType, metadata, branch = "main", signer, signal) {
|
|
7822
|
+
this.logger.verbose("updateRelationship(@sourceId, @targetId, @relationshipType, @metadata, @branch)", sourceId, targetId, relationshipType, metadata, branch);
|
|
7823
|
+
throwIfAborted(signal, () => new AbortError());
|
|
7824
|
+
let actions = [updateRelationshipAction(sourceId, targetId, relationshipType, metadata)];
|
|
7535
7825
|
if (signer) actions = await signActions(actions, signer, signal);
|
|
7536
7826
|
return await this.execute(sourceId, branch, actions, signal);
|
|
7537
7827
|
}
|
|
@@ -7903,19 +8193,27 @@ var ReactorBuilder = class {
|
|
|
7903
8193
|
} 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, this.executorConfig.deferredJobTtlMs);
|
|
7904
8194
|
await executorManager.start(executorStartCount);
|
|
7905
8195
|
const callerReadModels = Array.from(new Set([...this.readModels]));
|
|
8196
|
+
const degradedComponents = [];
|
|
8197
|
+
const startDegraded = (component, error) => {
|
|
8198
|
+
degradedComponents.push({
|
|
8199
|
+
component,
|
|
8200
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
8201
|
+
});
|
|
8202
|
+
this.logger?.error("Reactor component started degraded: @component", component, error);
|
|
8203
|
+
};
|
|
7906
8204
|
const documentViewConsistencyTracker = new ConsistencyTracker();
|
|
7907
8205
|
const documentView = new KyselyDocumentView(database, operationStore, operationIndex, writeCache, documentViewConsistencyTracker, featureFlags.documentDecisions);
|
|
7908
8206
|
try {
|
|
7909
8207
|
await documentView.init();
|
|
7910
8208
|
} catch (error) {
|
|
7911
|
-
|
|
8209
|
+
startDegraded("document view", error);
|
|
7912
8210
|
}
|
|
7913
8211
|
const documentIndexerConsistencyTracker = new ConsistencyTracker();
|
|
7914
8212
|
const documentIndexer = new KyselyDocumentIndexer(database, operationIndex, writeCache, documentIndexerConsistencyTracker);
|
|
7915
8213
|
try {
|
|
7916
8214
|
await documentIndexer.init();
|
|
7917
8215
|
} catch (error) {
|
|
7918
|
-
|
|
8216
|
+
startDegraded("document indexer", error);
|
|
7919
8217
|
}
|
|
7920
8218
|
const subscriptionManager = new ReactorSubscriptionManager(new DefaultSubscriptionErrorHandler());
|
|
7921
8219
|
const subscriptionNotificationReadModel = new SubscriptionNotificationReadModel(subscriptionManager, documentView);
|
|
@@ -7924,9 +8222,9 @@ var ReactorBuilder = class {
|
|
|
7924
8222
|
try {
|
|
7925
8223
|
await processorManager.init();
|
|
7926
8224
|
} catch (error) {
|
|
7927
|
-
|
|
8225
|
+
startDegraded("processor manager", error);
|
|
7928
8226
|
}
|
|
7929
|
-
for (const factory of this.readModelFactories) {
|
|
8227
|
+
for (const [index, factory] of this.readModelFactories.entries()) try {
|
|
7930
8228
|
const readModel = await factory({
|
|
7931
8229
|
documentModelRegistry,
|
|
7932
8230
|
operationIndex,
|
|
@@ -7934,6 +8232,8 @@ var ReactorBuilder = class {
|
|
|
7934
8232
|
processorManagerConsistencyTracker
|
|
7935
8233
|
});
|
|
7936
8234
|
callerReadModels.push(readModel);
|
|
8235
|
+
} catch (error) {
|
|
8236
|
+
startDegraded(`read model ${index}${factory.name ? ` (${factory.name})` : ""}`, error);
|
|
7937
8237
|
}
|
|
7938
8238
|
const readModelInstances = [
|
|
7939
8239
|
...callerReadModels,
|
|
@@ -7993,8 +8293,10 @@ var ReactorBuilder = class {
|
|
|
7993
8293
|
syncModule,
|
|
7994
8294
|
reactor,
|
|
7995
8295
|
groupReevaluationTrigger,
|
|
7996
|
-
pools: this.instrumentedPools
|
|
8296
|
+
pools: this.instrumentedPools,
|
|
8297
|
+
degradedComponents
|
|
7997
8298
|
};
|
|
8299
|
+
if (degradedComponents.length > 0) this.logger.warn("Reactor started with @count degraded component(s): @components", degradedComponents.length, degradedComponents.map(({ component }) => component).join(", "));
|
|
7998
8300
|
if (this.signalHandlersEnabled) this.attachSignalHandlers(module);
|
|
7999
8301
|
return module;
|
|
8000
8302
|
}
|
|
@@ -8098,7 +8400,7 @@ var ReactorBuilder = class {
|
|
|
8098
8400
|
const [{ WorkerHandle }, { createThreadTransport }, { workerEntryPath }] = await Promise.all([
|
|
8099
8401
|
import("./worker-handle-CrERzl8s.js"),
|
|
8100
8402
|
import("./transport-ByGviWdZ.js"),
|
|
8101
|
-
import("./worker-
|
|
8403
|
+
import("./worker-B12tBZmr.js").then((n) => n.n)
|
|
8102
8404
|
]);
|
|
8103
8405
|
const poolConfig = {
|
|
8104
8406
|
enabled: true,
|
|
@@ -8792,6 +9094,6 @@ var DocumentIntegrityService = class {
|
|
|
8792
9094
|
}
|
|
8793
9095
|
};
|
|
8794
9096
|
//#endregion
|
|
8795
|
-
export { ALWAYS_READABLE_SCOPES, APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, AuthEnforcementDisabledError, BareReadGate, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DOCUMENT_INDEXER_READ_MODEL, DOCUMENT_VIEW_READ_MODEL, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentAlreadyExistsError, DocumentChangeType, DocumentExistence, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, HybridProjectionCoordinator, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModelReadGate, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, RECOVERABLE_GRAPHQL_ERROR_CODES, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RetryAccounting, RevisionMismatchError, SeededStateReader, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncScopeGate, SyncStatus, SyncStatusTracker, addRelationshipAction, authDecisionModel, batchOperationsByDocument, buildDecisionModel, classifyJobFailure, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createHybridProjectionCoordinatorFactory, createMutableShutdownStatus, createReactorHostModuleBase, createRelationalDb, decideAtHead, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, isRecoverableGraphQLError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, readDecisionModel, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
9097
|
+
export { ALWAYS_READABLE_SCOPES, APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, AuthEnforcementDisabledError, BareReadGate, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DOCUMENT_INDEXER_READ_MODEL, DOCUMENT_VIEW_READ_MODEL, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentAlreadyExistsError, DocumentChangeType, DocumentExistence, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DriveRequestError, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, HybridProjectionCoordinator, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModelReadGate, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, RECOVERABLE_GRAPHQL_ERROR_CODES, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RelationshipNotFoundError, RetryAccounting, RevisionMismatchError, SeededStateReader, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncScopeGate, SyncStatus, SyncStatusTracker, addRelationshipAction, authDecisionModel, batchOperationsByDocument, buildDecisionModel, classifyJobFailure, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createHybridProjectionCoordinatorFactory, createMutableShutdownStatus, createReactorHostModuleBase, createRelationalDb, decideAtHead, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, isRecoverableGraphQLError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, readDecisionModel, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
8796
9098
|
|
|
8797
9099
|
//# sourceMappingURL=index.js.map
|