@powerhousedao/reactor 6.2.3-dev.23 → 6.2.3-dev.25
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-DUjyF4NM.js → build-worker-executor-DPGjh9Uc.js} +24 -8
- package/dist/build-worker-executor-DPGjh9Uc.js.map +1 -0
- package/dist/{document-indexer-CQzTEE1o.js → document-indexer-zbdzqZ3K.js} +18 -9
- package/dist/{document-indexer-CQzTEE1o.js.map → document-indexer-zbdzqZ3K.js.map} +1 -1
- package/dist/entry.d.ts +2 -1
- package/dist/entry.js +10 -6
- package/dist/entry.js.map +1 -1
- package/dist/{errors-D3S6Eysd.js → errors-BM_ULVWd.js} +9 -1
- package/dist/{errors-D3S6Eysd.js.map → errors-BM_ULVWd.js.map} +1 -1
- package/dist/{drive-container-types-CS5IxDiA.js → forwarding-logger-CSsCJ38f.js} +1081 -174
- package/dist/forwarding-logger-CSsCJ38f.js.map +1 -0
- package/dist/index.d.ts +2248 -1978
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +438 -258
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.d.ts +2 -1
- package/dist/projection-entry.js +7 -13
- package/dist/projection-entry.js.map +1 -1
- package/dist/{projection-shard-manager-CUo4bF4O.js → projection-shard-manager-B-j8VYzA.js} +2 -3
- package/dist/{projection-shard-manager-CUo4bF4O.js.map → projection-shard-manager-B-j8VYzA.js.map} +1 -1
- package/dist/{projection-worker-wI4PwcV2.js → projection-worker-D8uNFdwX.js} +1 -1
- package/dist/{projection-worker-wI4PwcV2.js.map → projection-worker-D8uNFdwX.js.map} +1 -1
- package/dist/{transport-CuogVKN_.js → transport-B3G50KVd.js} +1 -1
- package/dist/{transport-CuogVKN_.js.map → transport-B3G50KVd.js.map} +1 -1
- package/dist/{transport-ByGviWdZ.js → transport-CZDHzfvy.js} +1 -1
- package/dist/{transport-ByGviWdZ.js.map → transport-CZDHzfvy.js.map} +1 -1
- package/dist/{worker-handle-CrERzl8s.js → worker-handle-CwWNTpUg.js} +22 -16
- package/dist/worker-handle-CwWNTpUg.js.map +1 -0
- package/package.json +7 -8
- package/dist/build-worker-executor-DUjyF4NM.js.map +0 -1
- package/dist/drive-container-types-CS5IxDiA.js.map +0 -1
- package/dist/error-info-Cpu4OY3o.js +0 -62
- package/dist/error-info-Cpu4OY3o.js.map +0 -1
- package/dist/forwarding-logger-BBkMSxuJ.js +0 -85
- package/dist/forwarding-logger-BBkMSxuJ.js.map +0 -1
- package/dist/types-DMKLa0Ok.js +0 -33
- package/dist/types-DMKLa0Ok.js.map +0 -1
- package/dist/worker-g03lNM42.js +0 -22
- package/dist/worker-g03lNM42.js.map +0 -1
- package/dist/worker-handle-CrERzl8s.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import {
|
|
3
|
-
import { i as
|
|
4
|
-
import {
|
|
5
|
-
import { n as errorToInfo, r as sanitizeArg, t as createForwardingLogger } from "./forwarding-logger-BBkMSxuJ.js";
|
|
6
|
-
import { t as workerEntryPath } from "./worker-g03lNM42.js";
|
|
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";
|
|
1
|
+
import { $ as DocumentNotFoundError, A as ModuleNotFoundError, B as authDecisionModel, C as DocumentMetaCache, D as DuplicateManifestError, E as JobExecutorEventTypes, F as summarizeSubmittedActions, G as DocumentExistence, H as APPEND_CONDITION_FAILED_PREFIX, I as targetDocumentId, J as RevisionMismatchError, K as DuplicateOperationError, L as decideAtHead, M as createConsistencyToken, N as createEmptyConsistencyToken, O as DuplicateModuleError, P as submittedActionIds, Q as DocumentDeletedError, R as selectDecisionModel, S as KyselyOperationIndex, T as DEFAULT_DEFERRED_JOB_TTL_MS, U as AppendConditionFailedError, V as buildDecisionModel, W as DocumentAlreadyExistsError, X as AuthTimestampNotMonotonicError, Y as AuthEnforcementDisabledError, Z as AuthorizationDeniedError, _ as DriveCollectionId, a as DEFAULT_DRIVE_CONTAINER_TYPES, at as EventBusAggregateError, b as EventBus, c as runMigrations, ct as parsePagingOptions, d as KyselyOperationStore, dt as __exportAll, et as ExcessiveReshuffleError, f as KyselyKeyframeStore, g as PassthroughSigner, h as verifyActionSignature, it as UpgradePreconditionFailedError, j as GATED_DOCUMENT_ACTIONS, k as InvalidModuleError, l as createForwardingPoolInstrumentation, lt as throwIfAborted, m as SimpleJobExecutor, n as errorToInfo, nt as InvalidSignatureError, o as REACTOR_SCHEMA, ot as ReactorEventTypes, p as DocumentModelRegistry, q as OptimisticLockError, r as sanitizeArg, rt as RelationshipNotFoundError, s as getMigrationStatus, st as matchesScope, t as createForwardingLogger, tt as InvalidOperationTimestampError, u as instrumentPgPool, v as KyselyExecutionScope, w as CollectionMembershipCache, x as KyselyWriteCache, y as resolveFeatureFlags, z as documentDecisionModel } from "./forwarding-logger-CSsCJ38f.js";
|
|
2
|
+
import { i as WorkerInitFailedError, r as WorkerExitedError, t as WorkerAbortTimeoutError } from "./errors-BM_ULVWd.js";
|
|
3
|
+
import { a as KyselyDocumentView, c as ReadModelCoordinator, d as DEFAULT_READ_MODEL_YIELD_DEADLINE_MS, f as defaultReadModelIndexingConfig, i as DeletedDocumentRead, l as BaseReadModel, n as ConsistencyTracker, o as DOCUMENT_INDEXER_READ_MODEL, p as unchunkedReadModelIndexingConfig, r as makeConsistencyKey, s as DOCUMENT_VIEW_READ_MODEL, t as KyselyDocumentIndexer, u as DEFAULT_COMMIT_CHUNK_SIZE } from "./document-indexer-zbdzqZ3K.js";
|
|
4
|
+
import { DEFAULT_SIGNATURE_POLICY, DowngradeNotSupportedError, MAX_AUTH_GRANTS, UnsupportedDocumentModelVersionError, actionSignerIdentity, actionSigningTarget, actions, actions as documentActions, createCopyHeader, decide, deserializeSignature, garbageCollect, generateId, groupDocumentType, groupMembershipActionTypes, hashDocumentStateForScope, normalizeDocumentModelVersion, requestedSignaturePolicy, sortOperations, toTransportAction, withSignaturePolicy } from "@powerhousedao/shared/document-model";
|
|
8
5
|
import { addFile, addFolder, copyNode, deleteNode, driveCreateDocument, generateNodesCopy, getDescendants, handleTargetNameCollisions, isFileNode, isFolderNode, moveNode, updateNode } from "@powerhousedao/shared/document-drive";
|
|
9
6
|
import { v4 } from "uuid";
|
|
10
7
|
import { ConsoleLogger, childLogger } from "document-model";
|
|
@@ -237,37 +234,31 @@ function getSharedActionScope(actions) {
|
|
|
237
234
|
return baseScope;
|
|
238
235
|
}
|
|
239
236
|
/**
|
|
240
|
-
* Signs an action
|
|
241
|
-
*
|
|
237
|
+
* Signs an action for `target`, the log it is written to. An action already
|
|
238
|
+
* signed under a key is returned unchanged; one whose signer or last tuple has
|
|
239
|
+
* no key is unsigned, and is signed like any other.
|
|
242
240
|
*/
|
|
243
|
-
const signAction = async (action, signer, signal) => {
|
|
244
|
-
const
|
|
245
|
-
if (
|
|
246
|
-
const signature = await signer.signAction(action, signal);
|
|
241
|
+
const signAction = async (action, signer, target, signal) => {
|
|
242
|
+
const existing = action.context?.signer;
|
|
243
|
+
if (existing?.app?.key && existing.signatures.at(-1)?.[1]) return action;
|
|
244
|
+
const signature = await signer.signAction(action, target, signal);
|
|
247
245
|
return {
|
|
248
246
|
...action,
|
|
249
247
|
context: {
|
|
250
248
|
...action.context,
|
|
251
249
|
signer: {
|
|
252
|
-
|
|
253
|
-
address: signer.user?.address || "",
|
|
254
|
-
networkId: signer.user?.networkId || "",
|
|
255
|
-
chainId: signer.user?.chainId || 0
|
|
256
|
-
},
|
|
257
|
-
app: {
|
|
258
|
-
name: signer.app?.name || "",
|
|
259
|
-
key: signer.app?.key || ""
|
|
260
|
-
},
|
|
250
|
+
...actionSignerIdentity(signer),
|
|
261
251
|
signatures: [signature]
|
|
262
252
|
}
|
|
263
253
|
}
|
|
264
254
|
};
|
|
265
255
|
};
|
|
266
256
|
/**
|
|
267
|
-
* Signs
|
|
257
|
+
* Signs the actions of a job on `job.documentId`, each for the log it is
|
|
258
|
+
* written to: a relationship action lands in its source document.
|
|
268
259
|
*/
|
|
269
|
-
const signActions = async (actions, signer, signal) => {
|
|
270
|
-
return Promise.all(actions.map((action) => signAction(action, signer, signal)));
|
|
260
|
+
const signActions = async (actions, signer, job, signal) => {
|
|
261
|
+
return Promise.all(actions.map((action) => signAction(action, signer, actionSigningTarget(action, job.documentId, job.branch), signal)));
|
|
271
262
|
};
|
|
272
263
|
function buildSingleJobMeta(jobId, callerMeta) {
|
|
273
264
|
return {
|
|
@@ -321,6 +312,10 @@ let JobStatus = /* @__PURE__ */ function(JobStatus) {
|
|
|
321
312
|
* during construction, so the partial-`this` hazard does not apply.
|
|
322
313
|
*/
|
|
323
314
|
var DriveClient = class {
|
|
315
|
+
client;
|
|
316
|
+
logger;
|
|
317
|
+
reactor;
|
|
318
|
+
signer;
|
|
324
319
|
constructor(client, logger, reactor, signer) {
|
|
325
320
|
this.client = client;
|
|
326
321
|
this.logger = logger;
|
|
@@ -329,11 +324,11 @@ var DriveClient = class {
|
|
|
329
324
|
}
|
|
330
325
|
async create(input, signal) {
|
|
331
326
|
this.logger.verbose("drives.create(@input)", input);
|
|
332
|
-
const driveDoc = driveCreateDocument({ global: {
|
|
327
|
+
const driveDoc = withSignaturePolicy(driveCreateDocument({ global: {
|
|
333
328
|
name: input.global.name || "",
|
|
334
329
|
icon: input.global.icon ?? null,
|
|
335
330
|
nodes: []
|
|
336
|
-
} });
|
|
331
|
+
} }), requestedSignaturePolicy(input, await this.client.getCreateSignaturePolicy()), { protocolVersions: input.protocolVersions });
|
|
337
332
|
if (input.preferredEditor) driveDoc.header.meta = {
|
|
338
333
|
...driveDoc.header.meta,
|
|
339
334
|
preferredEditor: input.preferredEditor
|
|
@@ -343,24 +338,25 @@ var DriveClient = class {
|
|
|
343
338
|
async addFile(driveIdentifier, document, parentFolder, signal) {
|
|
344
339
|
this.logger.verbose("drives.addFile(@driveIdentifier, @document, @parentFolder)", driveIdentifier, document.header.id, parentFolder);
|
|
345
340
|
const documentId = document.header.id;
|
|
341
|
+
const createInput = {
|
|
342
|
+
model: document.header.documentType,
|
|
343
|
+
version: 0,
|
|
344
|
+
documentId: document.header.id,
|
|
345
|
+
signing: {
|
|
346
|
+
signature: document.header.id,
|
|
347
|
+
publicKey: document.header.sig.publicKey,
|
|
348
|
+
nonce: document.header.sig.nonce,
|
|
349
|
+
createdAtUtcIso: document.header.createdAtUtcIso,
|
|
350
|
+
documentType: document.header.documentType
|
|
351
|
+
},
|
|
352
|
+
slug: document.header.slug,
|
|
353
|
+
name: document.header.name,
|
|
354
|
+
branch: document.header.branch,
|
|
355
|
+
meta: document.header.meta,
|
|
356
|
+
protocolVersions: document.header.protocolVersions ?? { "base-reducer": 2 }
|
|
357
|
+
};
|
|
346
358
|
const documentActions = await signActions([
|
|
347
|
-
createDocumentAction(
|
|
348
|
-
model: document.header.documentType,
|
|
349
|
-
version: 0,
|
|
350
|
-
documentId: document.header.id,
|
|
351
|
-
signing: {
|
|
352
|
-
signature: document.header.id,
|
|
353
|
-
publicKey: document.header.sig.publicKey,
|
|
354
|
-
nonce: document.header.sig.nonce,
|
|
355
|
-
createdAtUtcIso: document.header.createdAtUtcIso,
|
|
356
|
-
documentType: document.header.documentType
|
|
357
|
-
},
|
|
358
|
-
slug: document.header.slug,
|
|
359
|
-
name: document.header.name,
|
|
360
|
-
branch: document.header.branch,
|
|
361
|
-
meta: document.header.meta,
|
|
362
|
-
protocolVersions: document.header.protocolVersions ?? { "base-reducer": 2 }
|
|
363
|
-
}),
|
|
359
|
+
createDocumentAction(createInput),
|
|
364
360
|
upgradeDocumentAction({
|
|
365
361
|
documentId: document.header.id,
|
|
366
362
|
model: document.header.documentType,
|
|
@@ -369,13 +365,19 @@ var DriveClient = class {
|
|
|
369
365
|
initialState: document.state
|
|
370
366
|
}),
|
|
371
367
|
addRelationshipAction(driveIdentifier, documentId, "child")
|
|
372
|
-
], this.signer,
|
|
368
|
+
], this.signer, {
|
|
369
|
+
documentId,
|
|
370
|
+
branch: "main"
|
|
371
|
+
}, signal);
|
|
373
372
|
const driveActions = await signActions([addFile({
|
|
374
373
|
id: documentId,
|
|
375
374
|
name: document.header.name || documentId,
|
|
376
375
|
documentType: document.header.documentType,
|
|
377
376
|
parentFolder
|
|
378
|
-
})], this.signer,
|
|
377
|
+
})], this.signer, {
|
|
378
|
+
documentId: driveIdentifier,
|
|
379
|
+
branch: "main"
|
|
380
|
+
}, signal);
|
|
379
381
|
await this.runJobs([{
|
|
380
382
|
key: "document",
|
|
381
383
|
documentId,
|
|
@@ -465,18 +467,20 @@ var DriveClient = class {
|
|
|
465
467
|
});
|
|
466
468
|
resolvedNamesByTargetId.set(entry.targetId, resolved);
|
|
467
469
|
}
|
|
470
|
+
const policy = await this.client.getCreateSignaturePolicy();
|
|
468
471
|
for (const entry of copyPlan) {
|
|
469
472
|
const node = drive.state.global.nodes.find((n) => n.id === entry.srcId);
|
|
470
473
|
if (!node || !isFileNode(node)) continue;
|
|
471
474
|
const srcDoc = await this.client.get(entry.srcId, void 0, signal);
|
|
472
475
|
const duplicated = {
|
|
473
476
|
...srcDoc,
|
|
474
|
-
header:
|
|
477
|
+
header: createCopyHeader(srcDoc.header, entry.targetId, policy),
|
|
475
478
|
initialState: srcDoc.state,
|
|
476
479
|
operations: {}
|
|
477
480
|
};
|
|
478
481
|
const resolvedName = resolvedNamesByTargetId.get(entry.targetId);
|
|
479
482
|
if (resolvedName) duplicated.header.name = resolvedName;
|
|
483
|
+
entry.targetId = duplicated.header.id;
|
|
480
484
|
await this.addFile(driveIdentifier, duplicated, entry.targetParentFolder ?? void 0, signal);
|
|
481
485
|
}
|
|
482
486
|
return this.client.execute(driveIdentifier, "main", copyPlan.map((entry) => copyNode(entry)), signal);
|
|
@@ -512,7 +516,7 @@ var DriveClient = class {
|
|
|
512
516
|
async runJobs(jobs, signal) {
|
|
513
517
|
const batchResult = await this.reactor.executeBatch({ jobs }, signal);
|
|
514
518
|
const completedJobs = await Promise.all(Object.values(batchResult.jobs).map((job) => this.client.waitForJob(job, signal)));
|
|
515
|
-
for (const job of completedJobs) if (job.status ===
|
|
519
|
+
for (const job of completedJobs) if (job.status === "FAILED") throw this.toError(job);
|
|
516
520
|
return completedJobs;
|
|
517
521
|
}
|
|
518
522
|
toError(job) {
|
|
@@ -529,8 +533,14 @@ var DriveClient = class {
|
|
|
529
533
|
}
|
|
530
534
|
}
|
|
531
535
|
async removeFileNode(driveId, fileId, signal) {
|
|
532
|
-
const relationshipActions = await signActions([removeRelationshipAction(driveId, fileId, "child")], this.signer,
|
|
533
|
-
|
|
536
|
+
const relationshipActions = await signActions([removeRelationshipAction(driveId, fileId, "child")], this.signer, {
|
|
537
|
+
documentId: driveId,
|
|
538
|
+
branch: "main"
|
|
539
|
+
}, signal);
|
|
540
|
+
const driveActions = await signActions([deleteNode({ id: fileId })], this.signer, {
|
|
541
|
+
documentId: driveId,
|
|
542
|
+
branch: "main"
|
|
543
|
+
}, signal);
|
|
534
544
|
const batchResult = await this.reactor.executeBatch({ jobs: [{
|
|
535
545
|
key: "relationship",
|
|
536
546
|
documentId: driveId,
|
|
@@ -547,10 +557,10 @@ var DriveClient = class {
|
|
|
547
557
|
dependsOn: ["relationship"]
|
|
548
558
|
}] }, signal);
|
|
549
559
|
const completedJobs = await Promise.all(Object.values(batchResult.jobs).map((job) => this.client.waitForJob(job, signal)));
|
|
550
|
-
for (const job of completedJobs) if (job.status ===
|
|
560
|
+
for (const job of completedJobs) if (job.status === "FAILED") throw new Error(job.error?.message);
|
|
551
561
|
const deleteJob = await this.reactor.deleteDocument(fileId, this.signer, signal);
|
|
552
562
|
const deleteCompleted = await this.client.waitForJob(deleteJob, signal);
|
|
553
|
-
if (deleteCompleted.status ===
|
|
563
|
+
if (deleteCompleted.status === "FAILED") throw new Error(deleteCompleted.error?.message);
|
|
554
564
|
}
|
|
555
565
|
};
|
|
556
566
|
//#endregion
|
|
@@ -561,13 +571,15 @@ var DriveClient = class {
|
|
|
561
571
|
* Only READ_READY and FAILED are truly terminal.
|
|
562
572
|
*/
|
|
563
573
|
function isTerminalStatus(status) {
|
|
564
|
-
return status ===
|
|
574
|
+
return status === "READ_READY" || status === "FAILED";
|
|
565
575
|
}
|
|
566
576
|
/**
|
|
567
577
|
* Event-driven implementation of IJobAwaiter.
|
|
568
578
|
* Subscribes to operation events to detect job completion without polling.
|
|
569
579
|
*/
|
|
570
580
|
var JobAwaiter = class {
|
|
581
|
+
eventBus;
|
|
582
|
+
getJobStatus;
|
|
571
583
|
pendingJobs = /* @__PURE__ */ new Map();
|
|
572
584
|
unsubscribers = [];
|
|
573
585
|
constructor(eventBus, getJobStatus) {
|
|
@@ -709,7 +721,7 @@ let DocumentChangeType = /* @__PURE__ */ function(DocumentChangeType) {
|
|
|
709
721
|
* would diverge permanently. The document scope carries the metadata the same
|
|
710
722
|
* argument covers. Grants gate domain-scope reads only.
|
|
711
723
|
*/
|
|
712
|
-
const ALWAYS_READABLE_SCOPES = new Set(["auth", "document"]);
|
|
724
|
+
const ALWAYS_READABLE_SCOPES = /* @__PURE__ */ new Set(["auth", "document"]);
|
|
713
725
|
/** What a gate does with an uninitialized policy when told nothing. */
|
|
714
726
|
const OPEN_BY_DEFAULT = { withholdUninitialized: false };
|
|
715
727
|
/**
|
|
@@ -783,6 +795,9 @@ var BareReadGate = class {
|
|
|
783
795
|
* list names is fetched.
|
|
784
796
|
*/
|
|
785
797
|
var SeededStateReader = class {
|
|
798
|
+
documentView;
|
|
799
|
+
seed;
|
|
800
|
+
branch;
|
|
786
801
|
constructor(documentView, seed, branch) {
|
|
787
802
|
this.documentView = documentView;
|
|
788
803
|
this.seed = seed;
|
|
@@ -812,7 +827,7 @@ var SeededStateReader = class {
|
|
|
812
827
|
if (DocumentNotFoundError.isError(error)) return;
|
|
813
828
|
let exists;
|
|
814
829
|
try {
|
|
815
|
-
exists = await this.documentView.exists([documentId],
|
|
830
|
+
exists = await this.documentView.exists([documentId], "LiveOnly", void 0, signal);
|
|
816
831
|
} catch {
|
|
817
832
|
throw error;
|
|
818
833
|
}
|
|
@@ -833,6 +848,12 @@ var SeededStateReader = class {
|
|
|
833
848
|
* from state no commit ever invalidates.
|
|
834
849
|
*/
|
|
835
850
|
var ModelReadGate = class {
|
|
851
|
+
model;
|
|
852
|
+
documentView;
|
|
853
|
+
servesGroups;
|
|
854
|
+
operationIndex;
|
|
855
|
+
logger;
|
|
856
|
+
options;
|
|
836
857
|
constructor(model, documentView, servesGroups, operationIndex, logger, options = OPEN_BY_DEFAULT) {
|
|
837
858
|
this.model = model;
|
|
838
859
|
this.documentView = documentView;
|
|
@@ -972,7 +993,7 @@ function authSubjectFromSigner(signer) {
|
|
|
972
993
|
function withAuthScope(view) {
|
|
973
994
|
if (view?.scopes && view.scopes.length > 0) return {
|
|
974
995
|
...view,
|
|
975
|
-
scopes: [
|
|
996
|
+
scopes: [.../* @__PURE__ */ new Set([...view.scopes, "auth"])]
|
|
976
997
|
};
|
|
977
998
|
return view;
|
|
978
999
|
}
|
|
@@ -1049,8 +1070,9 @@ var ReactorClient = class {
|
|
|
1049
1070
|
documentView;
|
|
1050
1071
|
readGate;
|
|
1051
1072
|
actionEvaluation;
|
|
1073
|
+
createSignaturePolicy;
|
|
1052
1074
|
drives;
|
|
1053
|
-
constructor(logger, reactor, signer, subscriptionManager, jobAwaiter, documentIndexer, documentView, readGate = new BareReadGate(), actionEvaluation) {
|
|
1075
|
+
constructor(logger, reactor, signer, subscriptionManager, jobAwaiter, documentIndexer, documentView, readGate = new BareReadGate(), actionEvaluation, createSignaturePolicy = DEFAULT_SIGNATURE_POLICY) {
|
|
1054
1076
|
this.logger = logger;
|
|
1055
1077
|
this.reactor = reactor;
|
|
1056
1078
|
this.signer = signer;
|
|
@@ -1060,6 +1082,7 @@ var ReactorClient = class {
|
|
|
1060
1082
|
this.documentView = documentView;
|
|
1061
1083
|
this.readGate = readGate;
|
|
1062
1084
|
this.actionEvaluation = actionEvaluation;
|
|
1085
|
+
this.createSignaturePolicy = createSignaturePolicy;
|
|
1063
1086
|
this.drives = new DriveClient(this, logger, reactor, signer);
|
|
1064
1087
|
this.logger.verbose("ReactorClient initialized");
|
|
1065
1088
|
}
|
|
@@ -1150,7 +1173,7 @@ var ReactorClient = class {
|
|
|
1150
1173
|
/** True when the id is taken; a soft-deleted document's id is still taken. */
|
|
1151
1174
|
async isDocumentIdTaken(documentId, signal) {
|
|
1152
1175
|
this.logger.verbose("isDocumentIdTaken(@documentId)", documentId);
|
|
1153
|
-
return (await this.documentView.exists([documentId],
|
|
1176
|
+
return (await this.documentView.exists([documentId], "IncludingDeleted", void 0, signal))[0];
|
|
1154
1177
|
}
|
|
1155
1178
|
/**
|
|
1156
1179
|
* Retrieves operations for a document
|
|
@@ -1403,13 +1426,17 @@ var ReactorClient = class {
|
|
|
1403
1426
|
scopeStates: document.state ?? {}
|
|
1404
1427
|
};
|
|
1405
1428
|
}
|
|
1429
|
+
getCreateSignaturePolicy() {
|
|
1430
|
+
return Promise.resolve(this.createSignaturePolicy);
|
|
1431
|
+
}
|
|
1406
1432
|
/**
|
|
1407
1433
|
* Creates a document and waits for completion
|
|
1408
1434
|
*/
|
|
1409
1435
|
async create(document, parentIdentifier, signal) {
|
|
1410
1436
|
this.logger.verbose("create(@id, @parentIdentifier)", document.header.id, parentIdentifier);
|
|
1411
1437
|
const documentId = document.header.id;
|
|
1412
|
-
const
|
|
1438
|
+
const branch = document.header.branch || "main";
|
|
1439
|
+
const createInput = {
|
|
1413
1440
|
model: document.header.documentType,
|
|
1414
1441
|
version: 0,
|
|
1415
1442
|
documentId,
|
|
@@ -1425,23 +1452,30 @@ var ReactorClient = class {
|
|
|
1425
1452
|
branch: document.header.branch,
|
|
1426
1453
|
meta: document.header.meta,
|
|
1427
1454
|
protocolVersions: document.header.protocolVersions ?? { "base-reducer": 2 }
|
|
1428
|
-
}
|
|
1455
|
+
};
|
|
1456
|
+
const createActions = await signActions([createDocumentAction(createInput), upgradeDocumentAction({
|
|
1429
1457
|
documentId,
|
|
1430
1458
|
model: document.header.documentType,
|
|
1431
1459
|
fromVersion: 0,
|
|
1432
1460
|
toVersion: normalizeDocumentModelVersion(document.state.document?.version),
|
|
1433
1461
|
initialState: document.state
|
|
1434
|
-
})], this.signer,
|
|
1462
|
+
})], this.signer, {
|
|
1463
|
+
documentId,
|
|
1464
|
+
branch
|
|
1465
|
+
}, signal);
|
|
1435
1466
|
const jobs = [{
|
|
1436
1467
|
key: "create",
|
|
1437
1468
|
documentId,
|
|
1438
1469
|
scope: getSharedActionScope(createActions),
|
|
1439
|
-
branch
|
|
1470
|
+
branch,
|
|
1440
1471
|
actions: createActions,
|
|
1441
1472
|
dependsOn: []
|
|
1442
1473
|
}];
|
|
1443
1474
|
if (parentIdentifier) {
|
|
1444
|
-
const parentActions = await signActions([addRelationshipAction(parentIdentifier, documentId, "child")], this.signer,
|
|
1475
|
+
const parentActions = await signActions([addRelationshipAction(parentIdentifier, documentId, "child")], this.signer, {
|
|
1476
|
+
documentId: parentIdentifier,
|
|
1477
|
+
branch: "main"
|
|
1478
|
+
}, signal);
|
|
1445
1479
|
jobs.push({
|
|
1446
1480
|
key: "parent",
|
|
1447
1481
|
documentId: parentIdentifier,
|
|
@@ -1453,7 +1487,7 @@ var ReactorClient = class {
|
|
|
1453
1487
|
}
|
|
1454
1488
|
const batchResult = await this.reactor.executeBatch({ jobs }, signal);
|
|
1455
1489
|
const completedJobs = await Promise.all(Object.values(batchResult.jobs).map((job) => this.waitForJob(job, signal)));
|
|
1456
|
-
for (const job of completedJobs) if (job.status ===
|
|
1490
|
+
for (const job of completedJobs) if (job.status === "FAILED") throw new Error(job.error?.message);
|
|
1457
1491
|
const created = await this.reactor.get(documentId);
|
|
1458
1492
|
return this.gateDocument(created, void 0, signal);
|
|
1459
1493
|
}
|
|
@@ -1475,7 +1509,7 @@ var ReactorClient = class {
|
|
|
1475
1509
|
}, void 0);
|
|
1476
1510
|
if (!module) throw new Error(`Document model not found for type: ${documentModelType}`);
|
|
1477
1511
|
}
|
|
1478
|
-
const document = module.utils.createDocument();
|
|
1512
|
+
const document = withSignaturePolicy(module.utils.createDocument(), requestedSignaturePolicy(options, this.createSignaturePolicy), { protocolVersions: options?.protocolVersions });
|
|
1479
1513
|
document.state.document.version = normalizeDocumentModelVersion(module.version);
|
|
1480
1514
|
return this.create(document, options?.parentIdentifier, signal);
|
|
1481
1515
|
}
|
|
@@ -1501,19 +1535,26 @@ var ReactorClient = class {
|
|
|
1501
1535
|
const branch = document.header.branch || "main";
|
|
1502
1536
|
const fromVersion = normalizeDocumentModelVersion(document.state.document?.version);
|
|
1503
1537
|
let targetVersion = toVersion;
|
|
1504
|
-
if (targetVersion === void 0)
|
|
1538
|
+
if (targetVersion === void 0) {
|
|
1539
|
+
const module = await this.getDocumentModelModule(documentType);
|
|
1540
|
+
targetVersion = normalizeDocumentModelVersion(module.version);
|
|
1541
|
+
}
|
|
1505
1542
|
if (targetVersion === fromVersion) return this.gateDocument(document, { branch }, signal);
|
|
1506
1543
|
if (targetVersion < fromVersion) throw new DowngradeNotSupportedError(documentType, fromVersion, targetVersion);
|
|
1507
|
-
const
|
|
1544
|
+
const action = upgradeDocumentAction({
|
|
1508
1545
|
documentId,
|
|
1509
1546
|
model: documentType,
|
|
1510
1547
|
fromVersion,
|
|
1511
1548
|
toVersion: targetVersion,
|
|
1512
1549
|
revision: { ...document.header.revision }
|
|
1513
|
-
})
|
|
1550
|
+
});
|
|
1551
|
+
const signedActions = await signActions([action], this.signer, {
|
|
1552
|
+
documentId,
|
|
1553
|
+
branch
|
|
1554
|
+
}, signal);
|
|
1514
1555
|
const jobInfo = await this.reactor.execute(documentId, branch, signedActions, signal);
|
|
1515
1556
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1516
|
-
if (completedJob.status !==
|
|
1557
|
+
if (completedJob.status !== "FAILED") {
|
|
1517
1558
|
const upgraded = await this.reactor.getByIdOrSlug(documentId, { branch }, completedJob.consistencyToken, signal);
|
|
1518
1559
|
return this.gateDocument(upgraded, { branch }, signal);
|
|
1519
1560
|
}
|
|
@@ -1540,10 +1581,14 @@ var ReactorClient = class {
|
|
|
1540
1581
|
*/
|
|
1541
1582
|
async execute(documentIdentifier, branch, actions, signal, subject) {
|
|
1542
1583
|
this.logger.verbose("execute(@documentIdentifier, @branch, @count actions)", documentIdentifier, branch, actions.length);
|
|
1543
|
-
const
|
|
1544
|
-
const
|
|
1584
|
+
const documentId = await this.resolveWriteTarget(documentIdentifier, branch, actions, signal);
|
|
1585
|
+
const signedActions = await signActions(actions, this.signer, {
|
|
1586
|
+
documentId,
|
|
1587
|
+
branch
|
|
1588
|
+
}, signal);
|
|
1589
|
+
const jobInfo = await this.reactor.execute(documentId, branch, signedActions, signal);
|
|
1545
1590
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1546
|
-
if (completedJob.status ===
|
|
1591
|
+
if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1547
1592
|
const view = {
|
|
1548
1593
|
branch,
|
|
1549
1594
|
subject
|
|
@@ -1556,18 +1601,41 @@ var ReactorClient = class {
|
|
|
1556
1601
|
*/
|
|
1557
1602
|
async executeAsync(documentIdentifier, branch, actions, signal) {
|
|
1558
1603
|
this.logger.verbose("executeAsync(@documentIdentifier, @branch, @count actions)", documentIdentifier, branch, actions.length);
|
|
1559
|
-
const
|
|
1560
|
-
|
|
1604
|
+
const documentId = await this.resolveWriteTarget(documentIdentifier, branch, actions, signal);
|
|
1605
|
+
const signedActions = await signActions(actions, this.signer, {
|
|
1606
|
+
documentId,
|
|
1607
|
+
branch
|
|
1608
|
+
}, signal);
|
|
1609
|
+
return this.reactor.execute(documentId, branch, signedActions, signal);
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* The id a write on `identifier` is stored under, which its signatures bind.
|
|
1613
|
+
* A create names its own id, and an id no slug maps to is taken as given, so
|
|
1614
|
+
* a document still in flight resolves to itself.
|
|
1615
|
+
*/
|
|
1616
|
+
async resolveWriteTarget(identifier, branch, actions, signal) {
|
|
1617
|
+
if (actions.some((action) => action.type === "CREATE_DOCUMENT")) return identifier;
|
|
1618
|
+
const view = { branch };
|
|
1619
|
+
const bySlug = await this.documentView.resolveSlug(identifier, view, void 0, signal);
|
|
1620
|
+
if (bySlug === void 0 || bySlug === identifier) return identifier;
|
|
1621
|
+
return this.documentView.resolveIdOrSlug(identifier, view, void 0, signal);
|
|
1561
1622
|
}
|
|
1562
1623
|
async executeBatch(request, signal) {
|
|
1563
1624
|
this.logger.verbose("executeBatch(@count jobs)", request.jobs.length);
|
|
1564
|
-
const signedJobs = await Promise.all(request.jobs.map(async (job) =>
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1625
|
+
const signedJobs = await Promise.all(request.jobs.map(async (job) => {
|
|
1626
|
+
const documentId = await this.resolveWriteTarget(job.documentId, job.branch, job.actions, signal);
|
|
1627
|
+
return {
|
|
1628
|
+
...job,
|
|
1629
|
+
documentId,
|
|
1630
|
+
actions: await signActions(job.actions, this.signer, {
|
|
1631
|
+
documentId,
|
|
1632
|
+
branch: job.branch
|
|
1633
|
+
}, signal)
|
|
1634
|
+
};
|
|
1635
|
+
}));
|
|
1568
1636
|
const batchResult = await this.reactor.executeBatch({ jobs: signedJobs }, signal);
|
|
1569
1637
|
const completedJobs = await Promise.all(Object.values(batchResult.jobs).map((job) => this.waitForJob(job, signal)));
|
|
1570
|
-
for (const job of completedJobs) if (job.status ===
|
|
1638
|
+
for (const job of completedJobs) if (job.status === "FAILED") throw new Error(job.error?.message);
|
|
1571
1639
|
return batchResult;
|
|
1572
1640
|
}
|
|
1573
1641
|
/**
|
|
@@ -1592,7 +1660,7 @@ var ReactorClient = class {
|
|
|
1592
1660
|
this.logger.verbose("addRelationship(@sourceIdentifier, @targetIdentifier, @relationshipType, @metadata, @branch)", sourceIdentifier, targetIdentifier, relationshipType, metadata, branch);
|
|
1593
1661
|
const jobInfo = await this.reactor.addRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1594
1662
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1595
|
-
if (completedJob.status ===
|
|
1663
|
+
if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1596
1664
|
const result = await this.reactor.getByIdOrSlug(sourceIdentifier, { branch }, completedJob.consistencyToken, signal);
|
|
1597
1665
|
return this.gateDocument(result, { branch }, signal);
|
|
1598
1666
|
}
|
|
@@ -1604,7 +1672,7 @@ var ReactorClient = class {
|
|
|
1604
1672
|
if (!await this.readRelationshipEdge(sourceIdentifier, targetIdentifier, relationshipType, { branch }, signal)) throw new RelationshipNotFoundError(sourceIdentifier, targetIdentifier, relationshipType);
|
|
1605
1673
|
const jobInfo = await this.reactor.updateRelationship(sourceIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1606
1674
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1607
|
-
if (completedJob.status ===
|
|
1675
|
+
if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1608
1676
|
const result = await this.reactor.getByIdOrSlug(sourceIdentifier, { branch }, completedJob.consistencyToken, signal);
|
|
1609
1677
|
return this.gateDocument(result, { branch }, signal);
|
|
1610
1678
|
}
|
|
@@ -1615,7 +1683,7 @@ var ReactorClient = class {
|
|
|
1615
1683
|
this.logger.verbose("removeRelationship(@sourceIdentifier, @targetIdentifier, @relationshipType, @branch)", sourceIdentifier, targetIdentifier, relationshipType, branch);
|
|
1616
1684
|
const jobInfo = await this.reactor.removeRelationship(sourceIdentifier, targetIdentifier, relationshipType, branch, this.signer, signal);
|
|
1617
1685
|
const completedJob = await this.waitForJob(jobInfo, signal);
|
|
1618
|
-
if (completedJob.status ===
|
|
1686
|
+
if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1619
1687
|
const result = await this.reactor.getByIdOrSlug(sourceIdentifier, { branch }, completedJob.consistencyToken, signal);
|
|
1620
1688
|
return this.gateDocument(result, { branch }, signal);
|
|
1621
1689
|
}
|
|
@@ -1627,10 +1695,10 @@ var ReactorClient = class {
|
|
|
1627
1695
|
const metadata = (await this.readRelationshipEdge(sourceParentIdentifier, targetIdentifier, relationshipType, { branch }, signal))?.metadata;
|
|
1628
1696
|
const removeJobInfo = await this.reactor.removeRelationship(sourceParentIdentifier, targetIdentifier, relationshipType, branch, this.signer, signal);
|
|
1629
1697
|
const removeCompletedJob = await this.waitForJob(removeJobInfo, signal);
|
|
1630
|
-
if (removeCompletedJob.status ===
|
|
1698
|
+
if (removeCompletedJob.status === "FAILED") throw new Error(removeCompletedJob.error?.message);
|
|
1631
1699
|
const addJobInfo = await this.reactor.addRelationship(targetParentIdentifier, targetIdentifier, relationshipType, metadata, branch, this.signer, signal);
|
|
1632
1700
|
const addCompletedJob = await this.waitForJob(addJobInfo, signal);
|
|
1633
|
-
if (addCompletedJob.status ===
|
|
1701
|
+
if (addCompletedJob.status === "FAILED") throw new Error(addCompletedJob.error?.message);
|
|
1634
1702
|
const sourceResult = await this.reactor.getByIdOrSlug(sourceParentIdentifier, { branch }, removeCompletedJob.consistencyToken, signal);
|
|
1635
1703
|
const targetResult = await this.reactor.getByIdOrSlug(targetParentIdentifier, { branch }, addCompletedJob.consistencyToken, signal);
|
|
1636
1704
|
return {
|
|
@@ -1644,7 +1712,7 @@ var ReactorClient = class {
|
|
|
1644
1712
|
const completedJobs = await Promise.all(Object.entries(result.jobs).map(async ([key, jobInfo]) => {
|
|
1645
1713
|
return [key, await this.waitForJob(jobInfo, signal)];
|
|
1646
1714
|
}));
|
|
1647
|
-
for (const [, completedJob] of completedJobs) if (completedJob.status ===
|
|
1715
|
+
for (const [, completedJob] of completedJobs) if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1648
1716
|
return { jobs: Object.fromEntries(completedJobs) };
|
|
1649
1717
|
}
|
|
1650
1718
|
/**
|
|
@@ -1653,8 +1721,8 @@ var ReactorClient = class {
|
|
|
1653
1721
|
async deleteDocument(identifier, propagate, signal) {
|
|
1654
1722
|
this.logger.verbose("deleteDocument(@identifier, @propagate)", identifier, propagate);
|
|
1655
1723
|
const jobs = [];
|
|
1656
|
-
if (propagate ===
|
|
1657
|
-
const toDelete = new Set([identifier]);
|
|
1724
|
+
if (propagate === "cascade") {
|
|
1725
|
+
const toDelete = /* @__PURE__ */ new Set([identifier]);
|
|
1658
1726
|
let changed = true;
|
|
1659
1727
|
while (changed) {
|
|
1660
1728
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
@@ -1678,7 +1746,7 @@ var ReactorClient = class {
|
|
|
1678
1746
|
const jobInfo = await this.reactor.deleteDocument(identifier, this.signer, signal);
|
|
1679
1747
|
jobs.push(jobInfo);
|
|
1680
1748
|
const completedJobs = await Promise.all(jobs.map((job) => this.waitForJob(job, signal)));
|
|
1681
|
-
for (const completedJob of completedJobs) if (completedJob.status ===
|
|
1749
|
+
for (const completedJob of completedJobs) if (completedJob.status === "FAILED") throw new Error(completedJob.error?.message);
|
|
1682
1750
|
}
|
|
1683
1751
|
/**
|
|
1684
1752
|
* Deletes documents and waits for completion
|
|
@@ -1738,27 +1806,27 @@ var ReactorClient = class {
|
|
|
1738
1806
|
deliver((async () => {
|
|
1739
1807
|
const documents = await Promise.all(result.results.map((id) => this.reactor.get(id, withAuthScope(view), void 0, void 0)));
|
|
1740
1808
|
return {
|
|
1741
|
-
type:
|
|
1809
|
+
type: "created",
|
|
1742
1810
|
documents: await Promise.all(documents.map(readable))
|
|
1743
1811
|
};
|
|
1744
1812
|
})());
|
|
1745
1813
|
}, search);
|
|
1746
1814
|
const unsubscribeDeleted = this.subscriptionManager.onDocumentDeleted((documentIds) => {
|
|
1747
1815
|
deliver({
|
|
1748
|
-
type:
|
|
1816
|
+
type: "deleted",
|
|
1749
1817
|
documents: [],
|
|
1750
1818
|
context: { childId: documentIds[0] }
|
|
1751
1819
|
});
|
|
1752
1820
|
}, search);
|
|
1753
1821
|
const unsubscribeUpdated = this.subscriptionManager.onDocumentStateUpdated((result) => {
|
|
1754
1822
|
deliver((async () => ({
|
|
1755
|
-
type:
|
|
1823
|
+
type: "updated",
|
|
1756
1824
|
documents: await Promise.all(result.results.map(readable))
|
|
1757
1825
|
}))());
|
|
1758
1826
|
}, search, view);
|
|
1759
1827
|
const unsubscribeRelationship = this.subscriptionManager.onRelationshipChanged((parentId, childId, changeType) => {
|
|
1760
1828
|
deliver({
|
|
1761
|
-
type: changeType ===
|
|
1829
|
+
type: changeType === "added" ? "child_added" : "child_removed",
|
|
1762
1830
|
documents: [],
|
|
1763
1831
|
context: {
|
|
1764
1832
|
parentId,
|
|
@@ -1787,18 +1855,6 @@ var ReactorClient = class {
|
|
|
1787
1855
|
//#endregion
|
|
1788
1856
|
//#region src/queue/types.ts
|
|
1789
1857
|
/**
|
|
1790
|
-
* State of a job in the queue
|
|
1791
|
-
*/
|
|
1792
|
-
let JobQueueState = /* @__PURE__ */ function(JobQueueState) {
|
|
1793
|
-
JobQueueState[JobQueueState["UNKNOWN"] = -1] = "UNKNOWN";
|
|
1794
|
-
JobQueueState[JobQueueState["PREPROCESSING"] = 0] = "PREPROCESSING";
|
|
1795
|
-
JobQueueState[JobQueueState["PENDING"] = 1] = "PENDING";
|
|
1796
|
-
JobQueueState[JobQueueState["READY"] = 2] = "READY";
|
|
1797
|
-
JobQueueState[JobQueueState["RUNNING"] = 3] = "RUNNING";
|
|
1798
|
-
JobQueueState[JobQueueState["RESOLVED"] = 4] = "RESOLVED";
|
|
1799
|
-
return JobQueueState;
|
|
1800
|
-
}({});
|
|
1801
|
-
/**
|
|
1802
1858
|
* How a retry is accounted against the job's retry limit.
|
|
1803
1859
|
* - `CountAgainstLimit` (default): a fault; the job eventually exhausts its
|
|
1804
1860
|
* retries and fails terminally.
|
|
@@ -1831,6 +1887,11 @@ function toErrorInfo(error) {
|
|
|
1831
1887
|
};
|
|
1832
1888
|
}
|
|
1833
1889
|
var JobResultHandler = class {
|
|
1890
|
+
queue;
|
|
1891
|
+
jobTracker;
|
|
1892
|
+
eventBus;
|
|
1893
|
+
resolver;
|
|
1894
|
+
logger;
|
|
1834
1895
|
constructor(queue, jobTracker, eventBus, resolver, logger) {
|
|
1835
1896
|
this.queue = queue;
|
|
1836
1897
|
this.jobTracker = jobTracker;
|
|
@@ -1861,7 +1922,7 @@ var JobResultHandler = class {
|
|
|
1861
1922
|
if (result.error && AppendConditionFailedError.isError(result.error) && this.countConflicts(handle.job) < MAX_EXEMPT_CONFLICT_RETRIES) {
|
|
1862
1923
|
const errorInfo = toErrorInfo(result.error);
|
|
1863
1924
|
try {
|
|
1864
|
-
await this.queue.retryJob(handle.job.id, errorInfo,
|
|
1925
|
+
await this.queue.retryJob(handle.job.id, errorInfo, "exempt-from-limit");
|
|
1865
1926
|
return;
|
|
1866
1927
|
} catch {}
|
|
1867
1928
|
}
|
|
@@ -1870,7 +1931,7 @@ var JobResultHandler = class {
|
|
|
1870
1931
|
callbacks.deferJob(result.error.documentId, handle.job);
|
|
1871
1932
|
return;
|
|
1872
1933
|
}
|
|
1873
|
-
if (result.error && (DocumentDeletedError.isError(result.error) || DocumentAlreadyExistsError.isError(result.error) || DocumentNotFoundError.isError(result.error) || AuthorizationDeniedError.isError(result.error) || AuthTimestampNotMonotonicError.isError(result.error) || InvalidOperationTimestampError.isError(result.error) || ExcessiveReshuffleError.isError(result.error) || UpgradePreconditionFailedError.isError(result.error))) {
|
|
1934
|
+
if (result.error && (DocumentDeletedError.isError(result.error) || DocumentAlreadyExistsError.isError(result.error) || DocumentNotFoundError.isError(result.error) || AuthorizationDeniedError.isError(result.error) || AuthTimestampNotMonotonicError.isError(result.error) || InvalidOperationTimestampError.isError(result.error) || ExcessiveReshuffleError.isError(result.error) || InvalidSignatureError.isError(result.error) || UpgradePreconditionFailedError.isError(result.error))) {
|
|
1874
1935
|
const errorInfo = toErrorInfo(result.error);
|
|
1875
1936
|
this.jobTracker.markFailed(handle.job.id, errorInfo, handle.job);
|
|
1876
1937
|
this.eventBus.emit(ReactorEventTypes.JOB_FAILED, {
|
|
@@ -1959,6 +2020,12 @@ var JobResultHandler = class {
|
|
|
1959
2020
|
* is stranded at PENDING for as long as the deferral lasts.
|
|
1960
2021
|
*/
|
|
1961
2022
|
var DeferredJobs = class {
|
|
2023
|
+
queue;
|
|
2024
|
+
jobTracker;
|
|
2025
|
+
eventBus;
|
|
2026
|
+
logger;
|
|
2027
|
+
ttlMs;
|
|
2028
|
+
onReleased;
|
|
1962
2029
|
#byDocumentId = /* @__PURE__ */ new Map();
|
|
1963
2030
|
#timers = /* @__PURE__ */ new Map();
|
|
1964
2031
|
constructor(queue, jobTracker, eventBus, logger, ttlMs = DEFAULT_DEFERRED_JOB_TTL_MS, onReleased = () => Promise.resolve()) {
|
|
@@ -2120,6 +2187,13 @@ function bucketFor(documentId, numWorkers) {
|
|
|
2120
2187
|
* (Powerhouse board wiki id: d400d711-f07e-4389-a226-4e9fdd4fa8ba)
|
|
2121
2188
|
*/
|
|
2122
2189
|
var WorkerPoolJobExecutorManager = class {
|
|
2190
|
+
workerFactory;
|
|
2191
|
+
eventBus;
|
|
2192
|
+
queue;
|
|
2193
|
+
jobTracker;
|
|
2194
|
+
logger;
|
|
2195
|
+
resolver;
|
|
2196
|
+
operationIndex;
|
|
2123
2197
|
workers = [];
|
|
2124
2198
|
isRunning = false;
|
|
2125
2199
|
activeJobs = 0;
|
|
@@ -2258,6 +2332,7 @@ var WorkerPoolJobExecutorManager = class {
|
|
|
2258
2332
|
await this.tryDispatchFor(worker);
|
|
2259
2333
|
return;
|
|
2260
2334
|
}
|
|
2335
|
+
for (const refusal of outcome.signatureRefusals ?? []) this.eventBus.emit(ReactorEventTypes.SIGNATURE_REFUSED, refusal).catch(() => {});
|
|
2261
2336
|
if (outcome.result.success) {
|
|
2262
2337
|
this.totalJobsProcessed++;
|
|
2263
2338
|
const completedEvent = {
|
|
@@ -2383,6 +2458,12 @@ function fillMissingMemberships(documentIds, found) {
|
|
|
2383
2458
|
* Listens for job available events and dispatches jobs to executors.
|
|
2384
2459
|
*/
|
|
2385
2460
|
var SimpleJobExecutorManager = class {
|
|
2461
|
+
executorFactory;
|
|
2462
|
+
eventBus;
|
|
2463
|
+
queue;
|
|
2464
|
+
jobTracker;
|
|
2465
|
+
logger;
|
|
2466
|
+
resolver;
|
|
2386
2467
|
executors = [];
|
|
2387
2468
|
isRunning = false;
|
|
2388
2469
|
activeJobs = 0;
|
|
@@ -2557,6 +2638,7 @@ var SimpleJobExecutorManager = class {
|
|
|
2557
2638
|
* Subscribes to operation events to update job states.
|
|
2558
2639
|
*/
|
|
2559
2640
|
var InMemoryJobTracker = class {
|
|
2641
|
+
eventBus;
|
|
2560
2642
|
jobs = /* @__PURE__ */ new Map();
|
|
2561
2643
|
unsubscribers = [];
|
|
2562
2644
|
constructor(eventBus) {
|
|
@@ -2577,11 +2659,11 @@ var InMemoryJobTracker = class {
|
|
|
2577
2659
|
handleWriteReady(event) {
|
|
2578
2660
|
const jobId = event.jobId;
|
|
2579
2661
|
const job = this.jobs.get(jobId);
|
|
2580
|
-
if (job && job.status ===
|
|
2662
|
+
if (job && job.status === "RUNNING") {
|
|
2581
2663
|
const consistencyToken = createConsistencyToken(event.operations);
|
|
2582
2664
|
this.jobs.set(jobId, {
|
|
2583
2665
|
...job,
|
|
2584
|
-
status:
|
|
2666
|
+
status: "WRITE_READY",
|
|
2585
2667
|
consistencyToken,
|
|
2586
2668
|
result: summarizeSubmittedActions(event.operations, event.submittedActionIds)
|
|
2587
2669
|
});
|
|
@@ -2590,9 +2672,9 @@ var InMemoryJobTracker = class {
|
|
|
2590
2672
|
handleReadReady(event) {
|
|
2591
2673
|
const jobId = event.jobId;
|
|
2592
2674
|
const job = this.jobs.get(jobId);
|
|
2593
|
-
if (job && job.status ===
|
|
2675
|
+
if (job && job.status === "WRITE_READY") this.jobs.set(jobId, {
|
|
2594
2676
|
...job,
|
|
2595
|
-
status:
|
|
2677
|
+
status: "READ_READY"
|
|
2596
2678
|
});
|
|
2597
2679
|
}
|
|
2598
2680
|
handleJobFailed(event) {
|
|
@@ -2615,7 +2697,7 @@ var InMemoryJobTracker = class {
|
|
|
2615
2697
|
this.jobs.set(jobId, {
|
|
2616
2698
|
id: jobId,
|
|
2617
2699
|
documentId: "",
|
|
2618
|
-
status:
|
|
2700
|
+
status: "RUNNING",
|
|
2619
2701
|
createdAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2620
2702
|
consistencyToken: createEmptyConsistencyToken(),
|
|
2621
2703
|
meta: {
|
|
@@ -2627,7 +2709,7 @@ var InMemoryJobTracker = class {
|
|
|
2627
2709
|
}
|
|
2628
2710
|
this.jobs.set(jobId, {
|
|
2629
2711
|
...job,
|
|
2630
|
-
status:
|
|
2712
|
+
status: "RUNNING"
|
|
2631
2713
|
});
|
|
2632
2714
|
}
|
|
2633
2715
|
markFailed(jobId, error, job) {
|
|
@@ -2636,7 +2718,7 @@ var InMemoryJobTracker = class {
|
|
|
2636
2718
|
this.jobs.set(jobId, {
|
|
2637
2719
|
id: jobId,
|
|
2638
2720
|
documentId: job?.documentId ?? "",
|
|
2639
|
-
status:
|
|
2721
|
+
status: "FAILED",
|
|
2640
2722
|
createdAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2641
2723
|
completedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2642
2724
|
error,
|
|
@@ -2651,7 +2733,7 @@ var InMemoryJobTracker = class {
|
|
|
2651
2733
|
}
|
|
2652
2734
|
this.jobs.set(jobId, {
|
|
2653
2735
|
...existing,
|
|
2654
|
-
status:
|
|
2736
|
+
status: "FAILED",
|
|
2655
2737
|
completedAtUtcIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2656
2738
|
error,
|
|
2657
2739
|
job,
|
|
@@ -2745,6 +2827,7 @@ function highestOf(ops) {
|
|
|
2745
2827
|
return highest;
|
|
2746
2828
|
}
|
|
2747
2829
|
var ProcessorQueue = class {
|
|
2830
|
+
options;
|
|
2748
2831
|
tasks = [];
|
|
2749
2832
|
running = false;
|
|
2750
2833
|
closed = false;
|
|
@@ -3327,11 +3410,11 @@ var JobExecutionHandle = class {
|
|
|
3327
3410
|
onDefer;
|
|
3328
3411
|
getStateName(state) {
|
|
3329
3412
|
switch (state) {
|
|
3330
|
-
case
|
|
3331
|
-
case
|
|
3332
|
-
case
|
|
3333
|
-
case
|
|
3334
|
-
case
|
|
3413
|
+
case 0: return "PREPROCESSING";
|
|
3414
|
+
case 1: return "PENDING";
|
|
3415
|
+
case 2: return "READY";
|
|
3416
|
+
case 3: return "RUNNING";
|
|
3417
|
+
case 4: return "RESOLVED";
|
|
3335
3418
|
default: return `UNKNOWN`;
|
|
3336
3419
|
}
|
|
3337
3420
|
}
|
|
@@ -3350,23 +3433,23 @@ var JobExecutionHandle = class {
|
|
|
3350
3433
|
return this._state;
|
|
3351
3434
|
}
|
|
3352
3435
|
start() {
|
|
3353
|
-
if (this._state !==
|
|
3354
|
-
this._state =
|
|
3436
|
+
if (this._state !== 2) throw new Error(`Cannot start job in state ${this.getStateName(this._state)}`);
|
|
3437
|
+
this._state = 3;
|
|
3355
3438
|
this.onStart?.();
|
|
3356
3439
|
}
|
|
3357
3440
|
complete() {
|
|
3358
|
-
if (this._state !==
|
|
3359
|
-
this._state =
|
|
3441
|
+
if (this._state !== 3) throw new Error(`Cannot complete job in state ${this.getStateName(this._state)}`);
|
|
3442
|
+
this._state = 4;
|
|
3360
3443
|
this.onComplete?.();
|
|
3361
3444
|
}
|
|
3362
3445
|
fail(error) {
|
|
3363
|
-
if (this._state !==
|
|
3364
|
-
this._state =
|
|
3446
|
+
if (this._state !== 3) throw new Error(`Cannot fail job in state ${this.getStateName(this._state)}`);
|
|
3447
|
+
this._state = 4;
|
|
3365
3448
|
this.onFail?.(error);
|
|
3366
3449
|
}
|
|
3367
3450
|
defer() {
|
|
3368
|
-
if (this._state !==
|
|
3369
|
-
this._state =
|
|
3451
|
+
if (this._state !== 3) throw new Error(`Cannot defer job in state ${this.getStateName(this._state)}`);
|
|
3452
|
+
this._state = 4;
|
|
3370
3453
|
this.onDefer?.();
|
|
3371
3454
|
}
|
|
3372
3455
|
};
|
|
@@ -3379,6 +3462,8 @@ var JobExecutionHandle = class {
|
|
|
3379
3462
|
* Implements dependency management through queue hints.
|
|
3380
3463
|
*/
|
|
3381
3464
|
var InMemoryQueue = class {
|
|
3465
|
+
eventBus;
|
|
3466
|
+
resolver;
|
|
3382
3467
|
queues = /* @__PURE__ */ new Map();
|
|
3383
3468
|
jobIdToQueueKey = /* @__PURE__ */ new Map();
|
|
3384
3469
|
docIdToJobId = /* @__PURE__ */ new Map();
|
|
@@ -3513,7 +3598,7 @@ var InMemoryQueue = class {
|
|
|
3513
3598
|
this.jobIdToQueueKey.delete(job.id);
|
|
3514
3599
|
this.markJobExecuting(job);
|
|
3515
3600
|
if (queue.length === 0) this.queues.delete(queueKey);
|
|
3516
|
-
const handle = new JobExecutionHandle(job,
|
|
3601
|
+
const handle = new JobExecutionHandle(job, 2, {
|
|
3517
3602
|
onStart: () => {},
|
|
3518
3603
|
onComplete: () => {
|
|
3519
3604
|
this.completeJob(job.id);
|
|
@@ -3539,7 +3624,7 @@ var InMemoryQueue = class {
|
|
|
3539
3624
|
this.jobIdToQueueKey.delete(job.id);
|
|
3540
3625
|
this.markJobExecuting(job);
|
|
3541
3626
|
if (queue.length === 0) this.queues.delete(queueKey);
|
|
3542
|
-
const handle = new JobExecutionHandle(job,
|
|
3627
|
+
const handle = new JobExecutionHandle(job, 2, {
|
|
3543
3628
|
onStart: () => {},
|
|
3544
3629
|
onComplete: () => {
|
|
3545
3630
|
this.completeJob(job.id);
|
|
@@ -3573,7 +3658,7 @@ var InMemoryQueue = class {
|
|
|
3573
3658
|
this.jobIdToQueueKey.delete(job.id);
|
|
3574
3659
|
this.markJobExecuting(job);
|
|
3575
3660
|
if (queue.length === 0) this.queues.delete(queueKey);
|
|
3576
|
-
const handle = new JobExecutionHandle(job,
|
|
3661
|
+
const handle = new JobExecutionHandle(job, 2, {
|
|
3577
3662
|
onStart: () => {},
|
|
3578
3663
|
onComplete: () => {
|
|
3579
3664
|
this.completeJob(job.id);
|
|
@@ -3675,7 +3760,7 @@ var InMemoryQueue = class {
|
|
|
3675
3760
|
if (documentId) this.markJobComplete(jobId, documentId);
|
|
3676
3761
|
this.jobIndex.delete(jobId);
|
|
3677
3762
|
}
|
|
3678
|
-
async retryJob(jobId, error, accounting =
|
|
3763
|
+
async retryJob(jobId, error, accounting = "count-against-limit") {
|
|
3679
3764
|
const job = this.jobIndex.get(jobId);
|
|
3680
3765
|
if (!job) return;
|
|
3681
3766
|
job.lastError = error;
|
|
@@ -3687,7 +3772,7 @@ var InMemoryQueue = class {
|
|
|
3687
3772
|
const retryCount = job.retryCount || 0;
|
|
3688
3773
|
const updatedJob = {
|
|
3689
3774
|
...job,
|
|
3690
|
-
retryCount: accounting ===
|
|
3775
|
+
retryCount: accounting === "count-against-limit" ? retryCount + 1 : retryCount,
|
|
3691
3776
|
lastError: error
|
|
3692
3777
|
};
|
|
3693
3778
|
await this.enqueue(updatedJob);
|
|
@@ -3888,6 +3973,8 @@ function describeSource(source) {
|
|
|
3888
3973
|
* and failure-caching state.
|
|
3889
3974
|
*/
|
|
3890
3975
|
var DocumentModelResolver = class {
|
|
3976
|
+
registry;
|
|
3977
|
+
loader;
|
|
3891
3978
|
loadingModels = /* @__PURE__ */ new Map();
|
|
3892
3979
|
failedModelTypes = /* @__PURE__ */ new Set();
|
|
3893
3980
|
broadcastHook = null;
|
|
@@ -3958,6 +4045,7 @@ var DocumentModelResolver = class {
|
|
|
3958
4045
|
* Since there is no loader, missing models cannot be recovered.
|
|
3959
4046
|
*/
|
|
3960
4047
|
var NullDocumentModelResolver = class {
|
|
4048
|
+
registry;
|
|
3961
4049
|
constructor(registry) {
|
|
3962
4050
|
this.registry = registry;
|
|
3963
4051
|
}
|
|
@@ -4181,6 +4269,8 @@ var ReactorSubscriptionManager = class {
|
|
|
4181
4269
|
* is emitted, so that reactor.get() returns fresh data when callbacks fire.
|
|
4182
4270
|
*/
|
|
4183
4271
|
var SubscriptionNotificationReadModel = class {
|
|
4272
|
+
subscriptionManager;
|
|
4273
|
+
documentView;
|
|
4184
4274
|
name = "subscription-notification";
|
|
4185
4275
|
constructor(subscriptionManager, documentView) {
|
|
4186
4276
|
this.subscriptionManager = subscriptionManager;
|
|
@@ -4203,10 +4293,10 @@ var SubscriptionNotificationReadModel = class {
|
|
|
4203
4293
|
deleted.push(deletedId);
|
|
4204
4294
|
} else if (actionType === "ADD_RELATIONSHIP") {
|
|
4205
4295
|
const input = operation.action.input;
|
|
4206
|
-
this.subscriptionManager.notifyRelationshipChanged(input.sourceId, input.targetId,
|
|
4296
|
+
this.subscriptionManager.notifyRelationshipChanged(input.sourceId, input.targetId, "added", input.childType);
|
|
4207
4297
|
} else if (actionType === "REMOVE_RELATIONSHIP") {
|
|
4208
4298
|
const input = operation.action.input;
|
|
4209
|
-
this.subscriptionManager.notifyRelationshipChanged(input.sourceId, input.targetId,
|
|
4299
|
+
this.subscriptionManager.notifyRelationshipChanged(input.sourceId, input.targetId, "removed", input.childType);
|
|
4210
4300
|
} else if (!created.includes(context.documentId)) updatedIds.add(context.documentId);
|
|
4211
4301
|
}
|
|
4212
4302
|
if (created.length > 0) this.subscriptionManager.notifyDocumentsCreated(created, documentTypes, parentIds);
|
|
@@ -4231,6 +4321,10 @@ var SubscriptionNotificationReadModel = class {
|
|
|
4231
4321
|
* keeps the common case (a membership write later than all history) free.
|
|
4232
4322
|
*/
|
|
4233
4323
|
var GroupReevaluationTrigger = class {
|
|
4324
|
+
logger;
|
|
4325
|
+
eventBus;
|
|
4326
|
+
queue;
|
|
4327
|
+
operationIndex;
|
|
4234
4328
|
unsubscribe;
|
|
4235
4329
|
constructor(logger, eventBus, queue, operationIndex) {
|
|
4236
4330
|
this.logger = logger;
|
|
@@ -4382,7 +4476,7 @@ var Mailbox = class {
|
|
|
4382
4476
|
this.itemsMap.set(item.id, item);
|
|
4383
4477
|
for (const op of item.operations) this._latestOrdinal = Math.max(this._latestOrdinal, op.context.ordinal);
|
|
4384
4478
|
item.on((syncOp, _, next) => {
|
|
4385
|
-
if (next ===
|
|
4479
|
+
if (next === 2) for (const op of syncOp.operations) this._ack = Math.max(this._ack, op.context.ordinal);
|
|
4386
4480
|
});
|
|
4387
4481
|
}
|
|
4388
4482
|
if (this.paused) {
|
|
@@ -4496,7 +4590,7 @@ var BufferedMailbox = class {
|
|
|
4496
4590
|
this.itemsMap.set(item.id, item);
|
|
4497
4591
|
for (const op of item.operations) this._latestOrdinal = Math.max(this._latestOrdinal, op.context.ordinal);
|
|
4498
4592
|
item.on((syncOp, _, next) => {
|
|
4499
|
-
if (next ===
|
|
4593
|
+
if (next === 2) for (const op of syncOp.operations) this._ack = Math.max(this._ack, op.context.ordinal);
|
|
4500
4594
|
});
|
|
4501
4595
|
}
|
|
4502
4596
|
this.addedBuffer.push(...items);
|
|
@@ -4610,7 +4704,14 @@ var GraphQLRequestError = class extends Error {
|
|
|
4610
4704
|
* difference between a channel that recovers and one that is dead for the
|
|
4611
4705
|
* process lifetime.
|
|
4612
4706
|
*/
|
|
4613
|
-
const RECOVERABLE_GRAPHQL_ERROR_CODES = {
|
|
4707
|
+
const RECOVERABLE_GRAPHQL_ERROR_CODES = {
|
|
4708
|
+
/**
|
|
4709
|
+
* A stored operation cannot be represented in the schema - an action with no
|
|
4710
|
+
* id, say. The document holding it needs repairing, but the channel serves
|
|
4711
|
+
* every other document, and a peer that stopped polling would stop receiving
|
|
4712
|
+
* those too.
|
|
4713
|
+
*/
|
|
4714
|
+
malformedStoredOperation: "MALFORMED_STORED_OPERATION" };
|
|
4614
4715
|
const RECOVERABLE_CODES = new Set(Object.values(RECOVERABLE_GRAPHQL_ERROR_CODES));
|
|
4615
4716
|
/**
|
|
4616
4717
|
* True when every error the response carried named a recoverable code.
|
|
@@ -4719,23 +4820,23 @@ var SyncOperation = class {
|
|
|
4719
4820
|
this.scopes = scopes;
|
|
4720
4821
|
this.branch = branch;
|
|
4721
4822
|
this.operations = operations;
|
|
4722
|
-
this.status =
|
|
4823
|
+
this.status = -1;
|
|
4723
4824
|
}
|
|
4724
4825
|
on(callback) {
|
|
4725
4826
|
this.callbacks.push(callback);
|
|
4726
4827
|
}
|
|
4727
4828
|
started() {
|
|
4728
|
-
this.transition(
|
|
4829
|
+
this.transition(0);
|
|
4729
4830
|
}
|
|
4730
4831
|
transported() {
|
|
4731
|
-
this.transition(
|
|
4832
|
+
this.transition(1);
|
|
4732
4833
|
}
|
|
4733
4834
|
executed() {
|
|
4734
|
-
this.transition(
|
|
4835
|
+
this.transition(2);
|
|
4735
4836
|
}
|
|
4736
4837
|
failed(error) {
|
|
4737
4838
|
this.error = error;
|
|
4738
|
-
this.transition(
|
|
4839
|
+
this.transition(3);
|
|
4739
4840
|
}
|
|
4740
4841
|
transition(next) {
|
|
4741
4842
|
const prev = this.status;
|
|
@@ -4945,9 +5046,11 @@ function consolidateSyncOperations(syncOps) {
|
|
|
4945
5046
|
}
|
|
4946
5047
|
const first = group.ops[0];
|
|
4947
5048
|
const merged = new SyncOperation(first.id, first.jobId, remappedDeps, first.remoteName, first.documentId, first.scopes, first.branch, allOperations);
|
|
4948
|
-
if (first.status >
|
|
4949
|
-
|
|
4950
|
-
|
|
5049
|
+
if (first.status > 0) {
|
|
5050
|
+
if (first.status >= 3) merged.executed();
|
|
5051
|
+
else if (first.status >= 2) merged.transported();
|
|
5052
|
+
else merged.started();
|
|
5053
|
+
}
|
|
4951
5054
|
result.push(merged);
|
|
4952
5055
|
}
|
|
4953
5056
|
return result;
|
|
@@ -5078,7 +5181,7 @@ function syncOperationErrorType(error) {
|
|
|
5078
5181
|
return error?.errorType ?? classifyJobFailure(error?.error?.name ?? "Error");
|
|
5079
5182
|
}
|
|
5080
5183
|
/** Dead-letter types that must not stop the document syncing. */
|
|
5081
|
-
const NON_QUARANTINING_ERROR_TYPES = new Set(["AUTH_TIMESTAMP_NOT_MONOTONIC"]);
|
|
5184
|
+
const NON_QUARANTINING_ERROR_TYPES = /* @__PURE__ */ new Set(["AUTH_TIMESTAMP_NOT_MONOTONIC"]);
|
|
5082
5185
|
/**
|
|
5083
5186
|
* A held auth operation must not quarantine: reconciling the two policies needs
|
|
5084
5187
|
* the traffic a quarantine would stop.
|
|
@@ -5304,7 +5407,7 @@ function envelopesToSyncOperations(envelope, remoteName) {
|
|
|
5304
5407
|
}
|
|
5305
5408
|
const getLatestAppliedOrdinal = (syncOps) => {
|
|
5306
5409
|
let maxOrdinal = 0;
|
|
5307
|
-
for (const syncOp of syncOps) if (syncOp.status ===
|
|
5410
|
+
for (const syncOp of syncOps) if (syncOp.status === 2) for (const op of syncOp.operations) maxOrdinal = Math.max(maxOrdinal, op.context.ordinal);
|
|
5308
5411
|
return maxOrdinal;
|
|
5309
5412
|
};
|
|
5310
5413
|
//#endregion
|
|
@@ -5319,6 +5422,7 @@ const DECISION_FIELDS = ["deniedReason", "errorType"];
|
|
|
5319
5422
|
* GraphQL-based synchronization channel for network communication between reactors.
|
|
5320
5423
|
*/
|
|
5321
5424
|
var GqlRequestChannel = class {
|
|
5425
|
+
logger;
|
|
5322
5426
|
inbox;
|
|
5323
5427
|
outbox;
|
|
5324
5428
|
deadLetter;
|
|
@@ -5526,7 +5630,7 @@ var GqlRequestChannel = class {
|
|
|
5526
5630
|
const syncOps = [];
|
|
5527
5631
|
for (const dl of deadLetters) {
|
|
5528
5632
|
const syncOp = new SyncOperation(crypto.randomUUID(), dl.jobId, [], this.remoteName, dl.documentId, dl.scopes, dl.branch, []);
|
|
5529
|
-
syncOp.failed(new ChannelError(
|
|
5633
|
+
syncOp.failed(new ChannelError("outbox", new Error(dl.error), dl.errorType ?? void 0));
|
|
5530
5634
|
syncOps.push(syncOp);
|
|
5531
5635
|
}
|
|
5532
5636
|
this.deadLetter.add(...syncOps);
|
|
@@ -5546,7 +5650,7 @@ var GqlRequestChannel = class {
|
|
|
5546
5650
|
const classification = this.classifyError(err);
|
|
5547
5651
|
this.failureCount++;
|
|
5548
5652
|
this.lastFailureUtcMs = Date.now();
|
|
5549
|
-
const channelError = new ChannelError(
|
|
5653
|
+
const channelError = new ChannelError("inbox", err);
|
|
5550
5654
|
this.logger.error("GqlChannel poll error (@FailureCount, @Classification): @Error", this.failureCount, classification, channelError);
|
|
5551
5655
|
if (classification === "unrecoverable") {
|
|
5552
5656
|
this.pollTimer.stop();
|
|
@@ -5790,7 +5894,7 @@ var GqlRequestChannel = class {
|
|
|
5790
5894
|
this.transitionConnectionState("reconnecting");
|
|
5791
5895
|
this.schedulePushRetry();
|
|
5792
5896
|
} else {
|
|
5793
|
-
const channelError = new ChannelError(
|
|
5897
|
+
const channelError = new ChannelError("outbox", err);
|
|
5794
5898
|
for (const syncOp of syncOps) syncOp.failed(channelError);
|
|
5795
5899
|
this.deadLetter.add(...syncOps);
|
|
5796
5900
|
this.outbox.remove(...syncOps);
|
|
@@ -6012,7 +6116,7 @@ var GqlRequestChannelFactory = class {
|
|
|
6012
6116
|
...retryMaxDelayMs !== void 0 && { retryMaxDelayMs },
|
|
6013
6117
|
...maxQueueDepth !== void 0 && { maxQueueDepth },
|
|
6014
6118
|
...backpressureCheckIntervalMs !== void 0 && { backpressureCheckIntervalMs },
|
|
6015
|
-
startPaused: options?.pollBehavior ===
|
|
6119
|
+
startPaused: options?.pollBehavior === "manual"
|
|
6016
6120
|
});
|
|
6017
6121
|
return new GqlRequestChannel(this.logger, remoteId, remoteName, cursorStorage, gqlConfig, operationIndex, pollTimer);
|
|
6018
6122
|
}
|
|
@@ -6029,6 +6133,7 @@ function firstOrdinalOf$1(syncOp) {
|
|
|
6029
6133
|
* In general, the resolvers are responsible for updating mailboxes.
|
|
6030
6134
|
*/
|
|
6031
6135
|
var GqlResponseChannel = class {
|
|
6136
|
+
logger;
|
|
6032
6137
|
inbox;
|
|
6033
6138
|
outbox;
|
|
6034
6139
|
deadLetter;
|
|
@@ -6139,7 +6244,7 @@ var GqlResponseChannel = class {
|
|
|
6139
6244
|
*/
|
|
6140
6245
|
rememberUnserved(syncOps) {
|
|
6141
6246
|
for (const syncOp of syncOps) {
|
|
6142
|
-
if (syncOp.status ===
|
|
6247
|
+
if (syncOp.status === 2) continue;
|
|
6143
6248
|
const first = firstOrdinalOf$1(syncOp);
|
|
6144
6249
|
if (first > 0 && first < this.evictedOutboxFloor) this.evictedOutboxFloor = first;
|
|
6145
6250
|
}
|
|
@@ -6184,7 +6289,7 @@ var GqlResponseChannel = class {
|
|
|
6184
6289
|
unservedFloor() {
|
|
6185
6290
|
let floor = this.evictedOutboxFloor;
|
|
6186
6291
|
for (const syncOp of this.outbox.items) {
|
|
6187
|
-
if (syncOp.status ===
|
|
6292
|
+
if (syncOp.status === 2) continue;
|
|
6188
6293
|
const first = firstOrdinalOf$1(syncOp);
|
|
6189
6294
|
if (first > 0 && first < floor) floor = first;
|
|
6190
6295
|
}
|
|
@@ -6224,6 +6329,7 @@ function remoteCursorToRow(cursor) {
|
|
|
6224
6329
|
};
|
|
6225
6330
|
}
|
|
6226
6331
|
var KyselySyncCursorStorage = class {
|
|
6332
|
+
db;
|
|
6227
6333
|
constructor(db) {
|
|
6228
6334
|
this.db = db;
|
|
6229
6335
|
}
|
|
@@ -6299,6 +6405,7 @@ function deadLetterRecordToRow(record) {
|
|
|
6299
6405
|
* PGlite/Kysely-backed implementation of {@link ISyncDeadLetterStorage}.
|
|
6300
6406
|
*/
|
|
6301
6407
|
var KyselySyncDeadLetterStorage = class {
|
|
6408
|
+
db;
|
|
6302
6409
|
constructor(db) {
|
|
6303
6410
|
this.db = db;
|
|
6304
6411
|
}
|
|
@@ -6420,6 +6527,7 @@ function remoteRecordToRow(remote) {
|
|
|
6420
6527
|
};
|
|
6421
6528
|
}
|
|
6422
6529
|
var KyselySyncRemoteStorage = class {
|
|
6530
|
+
db;
|
|
6423
6531
|
constructor(db) {
|
|
6424
6532
|
this.db = db;
|
|
6425
6533
|
}
|
|
@@ -6570,6 +6678,7 @@ var BatchAggregator = class {
|
|
|
6570
6678
|
* to provide a fast path for jobs that have already synced.
|
|
6571
6679
|
*/
|
|
6572
6680
|
var SyncAwaiter = class {
|
|
6681
|
+
eventBus;
|
|
6573
6682
|
completedResults = /* @__PURE__ */ new Map();
|
|
6574
6683
|
pendingWaiters = /* @__PURE__ */ new Map();
|
|
6575
6684
|
unsubscribers = [];
|
|
@@ -6769,24 +6878,19 @@ var SyncStatusTracker = class {
|
|
|
6769
6878
|
}
|
|
6770
6879
|
};
|
|
6771
6880
|
function deriveStatus(inboxCount, outboxCount, errorCount) {
|
|
6772
|
-
if (errorCount > 0) return
|
|
6773
|
-
if (inboxCount > 0 && outboxCount > 0) return
|
|
6774
|
-
if (inboxCount > 0) return
|
|
6775
|
-
if (outboxCount > 0) return
|
|
6776
|
-
return
|
|
6881
|
+
if (errorCount > 0) return "ERROR";
|
|
6882
|
+
if (inboxCount > 0 && outboxCount > 0) return "OUTGOING_AND_INCOMING";
|
|
6883
|
+
if (inboxCount > 0) return "INCOMING";
|
|
6884
|
+
if (outboxCount > 0) return "OUTGOING";
|
|
6885
|
+
return "SYNCED";
|
|
6777
6886
|
}
|
|
6778
6887
|
//#endregion
|
|
6779
6888
|
//#region src/sync/sync-manager.ts
|
|
6780
|
-
var OutboxMode = /* @__PURE__ */ function(OutboxMode) {
|
|
6781
|
-
OutboxMode["Backfill"] = "backfill";
|
|
6782
|
-
OutboxMode["BatchTriggered"] = "batch-triggered";
|
|
6783
|
-
return OutboxMode;
|
|
6784
|
-
}(OutboxMode || {});
|
|
6785
6889
|
const defaultSyncManagerConfig = {
|
|
6786
6890
|
maxDeadLettersPerRemote: 100,
|
|
6787
6891
|
maxInboxBatchSize: 32,
|
|
6788
6892
|
maxHeldOperationsPerRemote: 1e4,
|
|
6789
|
-
staleRemotePollWindowMs:
|
|
6893
|
+
staleRemotePollWindowMs: 3e5
|
|
6790
6894
|
};
|
|
6791
6895
|
const PLAN_KEY_TO_JOB_UUID_CAP = 1e4;
|
|
6792
6896
|
/**
|
|
@@ -6889,7 +6993,7 @@ var SyncManager = class {
|
|
|
6889
6993
|
if (outboxAckOrdinal > 0) {
|
|
6890
6994
|
const backfillController = new AbortController();
|
|
6891
6995
|
this.backfillAbortControllers.set(record.name, backfillController);
|
|
6892
|
-
this.updateOutbox(remote, outboxAckOrdinal,
|
|
6996
|
+
this.updateOutbox(remote, outboxAckOrdinal, "backfill", backfillController.signal).catch((error) => {
|
|
6893
6997
|
if (backfillController.signal.aborted) return;
|
|
6894
6998
|
this.logger.error("Backfill failed for remote @RemoteName: @Error", remote.meta.name, error instanceof Error ? error : new Error(String(error)));
|
|
6895
6999
|
}).finally(() => {
|
|
@@ -7008,7 +7112,7 @@ var SyncManager = class {
|
|
|
7008
7112
|
}
|
|
7009
7113
|
const backfillController = new AbortController();
|
|
7010
7114
|
this.backfillAbortControllers.set(name, backfillController);
|
|
7011
|
-
this.updateOutbox(remote, 0,
|
|
7115
|
+
this.updateOutbox(remote, 0, "backfill", backfillController.signal).catch((error) => {
|
|
7012
7116
|
if (backfillController.signal.aborted) return;
|
|
7013
7117
|
this.logger.error("Backfill failed for remote @RemoteName: @Error", remote.meta.name, error instanceof Error ? error : new Error(String(error)));
|
|
7014
7118
|
}).finally(() => {
|
|
@@ -7128,7 +7232,7 @@ var SyncManager = class {
|
|
|
7128
7232
|
scopes: syncOp.scopes,
|
|
7129
7233
|
branch: syncOp.branch,
|
|
7130
7234
|
operations: syncOp.operations,
|
|
7131
|
-
errorSource: syncOp.error?.source ??
|
|
7235
|
+
errorSource: syncOp.error?.source ?? "none",
|
|
7132
7236
|
errorMessage: syncOp.error?.error.message ?? "unknown",
|
|
7133
7237
|
errorType
|
|
7134
7238
|
};
|
|
@@ -7188,7 +7292,7 @@ var SyncManager = class {
|
|
|
7188
7292
|
for (const remote of affectedRemotes) trimMailboxFromBatch(remote.channel.inbox, batch);
|
|
7189
7293
|
for (const remote of affectedRemotes) {
|
|
7190
7294
|
if (!this.remotes.has(remote.meta.name) || this.removing.has(remote.meta.name)) continue;
|
|
7191
|
-
await this.updateOutbox(remote, remote.channel.outbox.latestOrdinal,
|
|
7295
|
+
await this.updateOutbox(remote, remote.channel.outbox.latestOrdinal, "batch-triggered");
|
|
7192
7296
|
}
|
|
7193
7297
|
await this.drainPrunes();
|
|
7194
7298
|
}
|
|
@@ -7230,7 +7334,7 @@ var SyncManager = class {
|
|
|
7230
7334
|
if (this.isShutdown) return;
|
|
7231
7335
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7232
7336
|
this.logger.error("Failed to load operations from inbox (@remote, @documentId, @error)", remote.meta.name, syncOp.documentId, err.message);
|
|
7233
|
-
const channelError = new ChannelError(
|
|
7337
|
+
const channelError = new ChannelError("inbox", err);
|
|
7234
7338
|
syncOp.failed(channelError);
|
|
7235
7339
|
remote.channel.deadLetter.add(syncOp);
|
|
7236
7340
|
remote.channel.inbox.remove(syncOp);
|
|
@@ -7243,14 +7347,14 @@ var SyncManager = class {
|
|
|
7243
7347
|
if (this.isShutdown) return;
|
|
7244
7348
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7245
7349
|
this.logger.error("Failed to wait for job completion (@remote, @documentId, @jobId, @error)", remote.meta.name, syncOp.documentId, jobInfo.id, err.message);
|
|
7246
|
-
const channelError = new ChannelError(
|
|
7350
|
+
const channelError = new ChannelError("inbox", err);
|
|
7247
7351
|
syncOp.failed(channelError);
|
|
7248
7352
|
remote.channel.deadLetter.add(syncOp);
|
|
7249
7353
|
remote.channel.inbox.remove(syncOp);
|
|
7250
7354
|
return;
|
|
7251
7355
|
}
|
|
7252
7356
|
if (this.isShutdown) return;
|
|
7253
|
-
if (completedJobInfo.status ===
|
|
7357
|
+
if (completedJobInfo.status === "FAILED") {
|
|
7254
7358
|
const errorMessage = completedJobInfo.error?.message || "Unknown error";
|
|
7255
7359
|
this.logger.error("Failed to apply operations from inbox (@remote, @documentId, @jobId, @error)", remote.meta.name, syncOp.documentId, completedJobInfo.id, errorMessage);
|
|
7256
7360
|
syncOp.failed(this.inboxFailure(completedJobInfo.error));
|
|
@@ -7293,7 +7397,7 @@ var SyncManager = class {
|
|
|
7293
7397
|
if (this.isShutdown) return;
|
|
7294
7398
|
for (const { remote, syncOp } of items) {
|
|
7295
7399
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7296
|
-
syncOp.failed(new ChannelError(
|
|
7400
|
+
syncOp.failed(new ChannelError("inbox", err));
|
|
7297
7401
|
remote.channel.deadLetter.add(syncOp);
|
|
7298
7402
|
remote.channel.inbox.remove(syncOp);
|
|
7299
7403
|
}
|
|
@@ -7310,7 +7414,7 @@ var SyncManager = class {
|
|
|
7310
7414
|
for (const { remote, syncOp } of items) {
|
|
7311
7415
|
if (!(syncOp.jobId in result.jobs)) {
|
|
7312
7416
|
this.logger.error("Job key missing from batch load result (@remote, @documentId, @jobId)", remote.meta.name, syncOp.documentId, syncOp.jobId);
|
|
7313
|
-
const error = new ChannelError(
|
|
7417
|
+
const error = new ChannelError("inbox", /* @__PURE__ */ new Error(`Job key '${syncOp.jobId}' missing from batch load result`));
|
|
7314
7418
|
syncOp.failed(error);
|
|
7315
7419
|
remote.channel.deadLetter.add(syncOp);
|
|
7316
7420
|
remote.channel.inbox.remove(syncOp);
|
|
@@ -7323,13 +7427,13 @@ var SyncManager = class {
|
|
|
7323
7427
|
} catch (error) {
|
|
7324
7428
|
if (this.isShutdown) continue;
|
|
7325
7429
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7326
|
-
syncOp.failed(new ChannelError(
|
|
7430
|
+
syncOp.failed(new ChannelError("inbox", err));
|
|
7327
7431
|
remote.channel.deadLetter.add(syncOp);
|
|
7328
7432
|
remote.channel.inbox.remove(syncOp);
|
|
7329
7433
|
continue;
|
|
7330
7434
|
}
|
|
7331
7435
|
if (this.isShutdown) return;
|
|
7332
|
-
if (completedJobInfo.status ===
|
|
7436
|
+
if (completedJobInfo.status === "FAILED") {
|
|
7333
7437
|
syncOp.failed(this.inboxFailure(completedJobInfo.error));
|
|
7334
7438
|
remote.channel.deadLetter.add(syncOp);
|
|
7335
7439
|
} else syncOp.executed();
|
|
@@ -7348,7 +7452,7 @@ var SyncManager = class {
|
|
|
7348
7452
|
*/
|
|
7349
7453
|
inboxFailure(error) {
|
|
7350
7454
|
const message = error?.message || "Unknown error";
|
|
7351
|
-
return new ChannelError(
|
|
7455
|
+
return new ChannelError("inbox", /* @__PURE__ */ new Error(`Failed to apply operations: ${message}`), classifyJobFailure(error?.name ?? "Error"));
|
|
7352
7456
|
}
|
|
7353
7457
|
/**
|
|
7354
7458
|
* Where the next outbox derivation starts: at the evicted floor when there is
|
|
@@ -7375,7 +7479,7 @@ var SyncManager = class {
|
|
|
7375
7479
|
*/
|
|
7376
7480
|
evictPastOutboxBound(remote) {
|
|
7377
7481
|
const cap = this.config.maxHeldOperationsPerRemote;
|
|
7378
|
-
const queued = remote.channel.outbox.items.filter((syncOp) => syncOp.status ===
|
|
7482
|
+
const queued = remote.channel.outbox.items.filter((syncOp) => syncOp.status === -1).sort((a, b) => firstOrdinalOf(a) - firstOrdinalOf(b));
|
|
7379
7483
|
let kept = 0;
|
|
7380
7484
|
let cut = queued.length;
|
|
7381
7485
|
for (let i = 0; i < queued.length; i++) {
|
|
@@ -7467,7 +7571,7 @@ var SyncManager = class {
|
|
|
7467
7571
|
* it marked; the count is what keeps that drain from removing the remote this
|
|
7468
7572
|
* call is still adding to.
|
|
7469
7573
|
*/
|
|
7470
|
-
async updateOutbox(remote, ackOrdinal, mode =
|
|
7574
|
+
async updateOutbox(remote, ackOrdinal, mode = "backfill", signal) {
|
|
7471
7575
|
this.derivingOutboxes++;
|
|
7472
7576
|
try {
|
|
7473
7577
|
await this.deriveOutbox(remote, ackOrdinal, mode, signal);
|
|
@@ -7495,11 +7599,11 @@ var SyncManager = class {
|
|
|
7495
7599
|
const prevJobId = lastJobByDoc.get(batch.documentId);
|
|
7496
7600
|
const deps = [];
|
|
7497
7601
|
if (prevJobId) deps.push(prevJobId);
|
|
7498
|
-
if (mode ===
|
|
7602
|
+
if (mode === "batch-triggered" && prevChainJobId && prevChainJobId !== prevJobId) deps.push(prevChainJobId);
|
|
7499
7603
|
const syncOp = new SyncOperation(crypto.randomUUID(), jobId, deps, remote.meta.name, batch.documentId, [batch.scope], batch.branch, batch.operations);
|
|
7500
7604
|
syncOps.push(syncOp);
|
|
7501
7605
|
lastJobByDoc.set(batch.documentId, jobId);
|
|
7502
|
-
if (mode ===
|
|
7606
|
+
if (mode === "batch-triggered") prevChainJobId = jobId;
|
|
7503
7607
|
}
|
|
7504
7608
|
remote.channel.outbox.add(...syncOps);
|
|
7505
7609
|
this.evictPastOutboxBound(remote);
|
|
@@ -7807,7 +7911,7 @@ var Reactor = class {
|
|
|
7807
7911
|
this.logger.verbose("create(@id, @type, @slug)", document.header.id, document.header.documentType, document.header.slug);
|
|
7808
7912
|
const createdAtUtcIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
7809
7913
|
throwIfAborted(signal, () => new AbortError());
|
|
7810
|
-
|
|
7914
|
+
const createAction = createDocumentAction({
|
|
7811
7915
|
model: document.header.documentType,
|
|
7812
7916
|
version: 0,
|
|
7813
7917
|
documentId: document.header.id,
|
|
@@ -7823,14 +7927,20 @@ var Reactor = class {
|
|
|
7823
7927
|
branch: document.header.branch,
|
|
7824
7928
|
meta: document.header.meta,
|
|
7825
7929
|
protocolVersions: document.header.protocolVersions ?? { "base-reducer": 2 }
|
|
7826
|
-
})
|
|
7930
|
+
});
|
|
7931
|
+
const upgradeAction = upgradeDocumentAction({
|
|
7827
7932
|
documentId: document.header.id,
|
|
7828
7933
|
model: document.header.documentType,
|
|
7829
7934
|
fromVersion: 0,
|
|
7830
7935
|
toVersion: normalizeDocumentModelVersion(document.state.document?.version),
|
|
7831
7936
|
initialState: document.state
|
|
7832
|
-
})
|
|
7833
|
-
|
|
7937
|
+
});
|
|
7938
|
+
const branch = document.header.branch || "main";
|
|
7939
|
+
let actions = [createAction, upgradeAction];
|
|
7940
|
+
if (signer) actions = await signActions(actions, signer, {
|
|
7941
|
+
documentId: document.header.id,
|
|
7942
|
+
branch
|
|
7943
|
+
}, signal);
|
|
7834
7944
|
const jobId = v4();
|
|
7835
7945
|
const jobMeta = buildSingleJobMeta(jobId, meta);
|
|
7836
7946
|
const job = {
|
|
@@ -7838,7 +7948,7 @@ var Reactor = class {
|
|
|
7838
7948
|
kind: "mutation",
|
|
7839
7949
|
documentId: document.header.id,
|
|
7840
7950
|
scope: "document",
|
|
7841
|
-
branch
|
|
7951
|
+
branch,
|
|
7842
7952
|
actions,
|
|
7843
7953
|
operations: [],
|
|
7844
7954
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -7850,7 +7960,7 @@ var Reactor = class {
|
|
|
7850
7960
|
const jobInfo = {
|
|
7851
7961
|
id: jobId,
|
|
7852
7962
|
documentId: job.documentId,
|
|
7853
|
-
status:
|
|
7963
|
+
status: "PENDING",
|
|
7854
7964
|
createdAtUtcIso,
|
|
7855
7965
|
consistencyToken: {
|
|
7856
7966
|
version: 1,
|
|
@@ -7869,7 +7979,10 @@ var Reactor = class {
|
|
|
7869
7979
|
const createdAtUtcIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
7870
7980
|
throwIfAborted(signal, () => new AbortError());
|
|
7871
7981
|
let action = deleteDocumentAction(id);
|
|
7872
|
-
if (signer) action = await signAction(action, signer,
|
|
7982
|
+
if (signer) action = await signAction(action, signer, {
|
|
7983
|
+
documentId: id,
|
|
7984
|
+
branch: "main"
|
|
7985
|
+
}, signal);
|
|
7873
7986
|
const jobId = v4();
|
|
7874
7987
|
const jobMeta = buildSingleJobMeta(jobId, meta);
|
|
7875
7988
|
const job = {
|
|
@@ -7889,7 +8002,7 @@ var Reactor = class {
|
|
|
7889
8002
|
const jobInfo = {
|
|
7890
8003
|
id: jobId,
|
|
7891
8004
|
documentId: job.documentId,
|
|
7892
|
-
status:
|
|
8005
|
+
status: "PENDING",
|
|
7893
8006
|
createdAtUtcIso,
|
|
7894
8007
|
consistencyToken: {
|
|
7895
8008
|
version: 1,
|
|
@@ -7927,7 +8040,7 @@ var Reactor = class {
|
|
|
7927
8040
|
const jobInfo = {
|
|
7928
8041
|
id: jobId,
|
|
7929
8042
|
documentId: job.documentId,
|
|
7930
|
-
status:
|
|
8043
|
+
status: "PENDING",
|
|
7931
8044
|
createdAtUtcIso,
|
|
7932
8045
|
consistencyToken: {
|
|
7933
8046
|
version: 1,
|
|
@@ -7967,7 +8080,7 @@ var Reactor = class {
|
|
|
7967
8080
|
const jobInfo = {
|
|
7968
8081
|
id: jobId,
|
|
7969
8082
|
documentId: job.documentId,
|
|
7970
|
-
status:
|
|
8083
|
+
status: "PENDING",
|
|
7971
8084
|
createdAtUtcIso,
|
|
7972
8085
|
consistencyToken: {
|
|
7973
8086
|
version: 1,
|
|
@@ -8002,7 +8115,7 @@ var Reactor = class {
|
|
|
8002
8115
|
const jobInfo = {
|
|
8003
8116
|
id: planKeyToJobId.get(jobPlan.key),
|
|
8004
8117
|
documentId: jobPlan.documentId,
|
|
8005
|
-
status:
|
|
8118
|
+
status: "PENDING",
|
|
8006
8119
|
createdAtUtcIso,
|
|
8007
8120
|
consistencyToken: {
|
|
8008
8121
|
version: 1,
|
|
@@ -8072,7 +8185,7 @@ var Reactor = class {
|
|
|
8072
8185
|
const jobInfo = {
|
|
8073
8186
|
id: planKeyToJobId.get(jobPlan.key),
|
|
8074
8187
|
documentId: jobPlan.documentId,
|
|
8075
|
-
status:
|
|
8188
|
+
status: "PENDING",
|
|
8076
8189
|
createdAtUtcIso,
|
|
8077
8190
|
consistencyToken: {
|
|
8078
8191
|
version: 1,
|
|
@@ -8126,21 +8239,30 @@ var Reactor = class {
|
|
|
8126
8239
|
this.logger.verbose("addRelationship(@sourceId, @targetId, @relationshipType, @metadata, @branch)", sourceId, targetId, relationshipType, metadata, branch);
|
|
8127
8240
|
throwIfAborted(signal, () => new AbortError());
|
|
8128
8241
|
let actions = [addRelationshipAction(sourceId, targetId, relationshipType, metadata)];
|
|
8129
|
-
if (signer) actions = await signActions(actions, signer,
|
|
8242
|
+
if (signer) actions = await signActions(actions, signer, {
|
|
8243
|
+
documentId: sourceId,
|
|
8244
|
+
branch
|
|
8245
|
+
}, signal);
|
|
8130
8246
|
return await this.execute(sourceId, branch, actions, signal);
|
|
8131
8247
|
}
|
|
8132
8248
|
async updateRelationship(sourceId, targetId, relationshipType, metadata, branch = "main", signer, signal) {
|
|
8133
8249
|
this.logger.verbose("updateRelationship(@sourceId, @targetId, @relationshipType, @metadata, @branch)", sourceId, targetId, relationshipType, metadata, branch);
|
|
8134
8250
|
throwIfAborted(signal, () => new AbortError());
|
|
8135
8251
|
let actions = [updateRelationshipAction(sourceId, targetId, relationshipType, metadata)];
|
|
8136
|
-
if (signer) actions = await signActions(actions, signer,
|
|
8252
|
+
if (signer) actions = await signActions(actions, signer, {
|
|
8253
|
+
documentId: sourceId,
|
|
8254
|
+
branch
|
|
8255
|
+
}, signal);
|
|
8137
8256
|
return await this.execute(sourceId, branch, actions, signal);
|
|
8138
8257
|
}
|
|
8139
8258
|
async removeRelationship(sourceId, targetId, relationshipType, branch = "main", signer, signal) {
|
|
8140
8259
|
this.logger.verbose("removeRelationship(@sourceId, @targetId, @relationshipType, @branch)", sourceId, targetId, relationshipType, branch);
|
|
8141
8260
|
throwIfAborted(signal, () => new AbortError());
|
|
8142
8261
|
let actions = [removeRelationshipAction(sourceId, targetId, relationshipType)];
|
|
8143
|
-
if (signer) actions = await signActions(actions, signer,
|
|
8262
|
+
if (signer) actions = await signActions(actions, signer, {
|
|
8263
|
+
documentId: sourceId,
|
|
8264
|
+
branch
|
|
8265
|
+
}, signal);
|
|
8144
8266
|
return await this.execute(sourceId, branch, actions, signal);
|
|
8145
8267
|
}
|
|
8146
8268
|
getJobStatus(jobId, signal) {
|
|
@@ -8152,7 +8274,7 @@ var Reactor = class {
|
|
|
8152
8274
|
return Promise.resolve({
|
|
8153
8275
|
id: jobId,
|
|
8154
8276
|
documentId: "",
|
|
8155
|
-
status:
|
|
8277
|
+
status: "FAILED",
|
|
8156
8278
|
createdAtUtcIso: now,
|
|
8157
8279
|
completedAtUtcIso: now,
|
|
8158
8280
|
error: toErrorInfo$1("Job not found"),
|
|
@@ -8244,8 +8366,11 @@ var ReactorBuilder = class {
|
|
|
8244
8366
|
eventBus;
|
|
8245
8367
|
readModelCoordinator;
|
|
8246
8368
|
readModelCoordinatorFactory;
|
|
8247
|
-
signatureVerifier;
|
|
8248
8369
|
kyselyInstance;
|
|
8370
|
+
signer;
|
|
8371
|
+
workerSigner;
|
|
8372
|
+
trustPolicy;
|
|
8373
|
+
workerTrustPolicy;
|
|
8249
8374
|
signalHandlersEnabled = false;
|
|
8250
8375
|
queueInstance;
|
|
8251
8376
|
channelScheme;
|
|
@@ -8344,10 +8469,34 @@ var ReactorBuilder = class {
|
|
|
8344
8469
|
this.eventBus = eventBus;
|
|
8345
8470
|
return this;
|
|
8346
8471
|
}
|
|
8347
|
-
|
|
8348
|
-
|
|
8472
|
+
/**
|
|
8473
|
+
* Signs the operations the executor synthesizes: the NOOP an UNDO becomes and
|
|
8474
|
+
* the action a REDO rebuilds. Without one they are stored unsigned. Pooled
|
|
8475
|
+
* workers import `workerSigner` to build the same signer.
|
|
8476
|
+
*/
|
|
8477
|
+
withSigner(signer, workerSigner) {
|
|
8478
|
+
this.signer = signer;
|
|
8479
|
+
this.workerSigner = workerSigner;
|
|
8349
8480
|
return this;
|
|
8350
8481
|
}
|
|
8482
|
+
/** Whether {@link withSigner} was called. */
|
|
8483
|
+
hasSigner() {
|
|
8484
|
+
return this.signer !== void 0;
|
|
8485
|
+
}
|
|
8486
|
+
/**
|
|
8487
|
+
* Decides at admission whether a key may sign as the user it claims; see
|
|
8488
|
+
* {@link SignatureTrustPolicy} for the contract and the default. Pooled
|
|
8489
|
+
* workers import `workerTrustPolicy` to build the same policy.
|
|
8490
|
+
*/
|
|
8491
|
+
withTrustPolicy(trustPolicy, workerTrustPolicy) {
|
|
8492
|
+
this.trustPolicy = trustPolicy;
|
|
8493
|
+
this.workerTrustPolicy = workerTrustPolicy;
|
|
8494
|
+
return this;
|
|
8495
|
+
}
|
|
8496
|
+
/** Whether {@link withTrustPolicy} was called. */
|
|
8497
|
+
hasTrustPolicy() {
|
|
8498
|
+
return this.trustPolicy !== void 0;
|
|
8499
|
+
}
|
|
8351
8500
|
withKysely(kysely) {
|
|
8352
8501
|
this.kyselyInstance = kysely;
|
|
8353
8502
|
return this;
|
|
@@ -8401,8 +8550,7 @@ var ReactorBuilder = class {
|
|
|
8401
8550
|
* this enables the pool — there is no `enabled` flag. Provide `db`
|
|
8402
8551
|
* (each worker opens its own Postgres pool; the parent database is built
|
|
8403
8552
|
* from it too unless {@link withKysely} is set) or a custom `factory`
|
|
8404
|
-
* transport.
|
|
8405
|
-
* omitted = no executor-side signature verification.
|
|
8553
|
+
* transport.
|
|
8406
8554
|
*/
|
|
8407
8555
|
withWorkerPool(options) {
|
|
8408
8556
|
this.workerPool = options;
|
|
@@ -8477,11 +8625,12 @@ var ReactorBuilder = class {
|
|
|
8477
8625
|
if (resolver instanceof DocumentModelResolver) resolver.setModelLoadedHook((documentType) => eventBus.emit(ReactorEventTypes.MODEL_LOADED, { documentType }));
|
|
8478
8626
|
const queue = this.queueInstance ?? new InMemoryQueue(eventBus, resolver);
|
|
8479
8627
|
const jobTracker = new InMemoryJobTracker(eventBus);
|
|
8480
|
-
const
|
|
8628
|
+
const cacheConfig = {
|
|
8481
8629
|
maxDocuments: this.writeCacheConfig?.maxDocuments ?? 100,
|
|
8482
8630
|
ringBufferSize: this.writeCacheConfig?.ringBufferSize ?? 10,
|
|
8483
8631
|
keyframeInterval: this.writeCacheConfig?.keyframeInterval ?? 10
|
|
8484
|
-
}
|
|
8632
|
+
};
|
|
8633
|
+
const writeCache = new KyselyWriteCache(keyframeStore, operationStore, documentModelRegistry, cacheConfig);
|
|
8485
8634
|
await writeCache.startup();
|
|
8486
8635
|
const operationIndex = new KyselyOperationIndex(database);
|
|
8487
8636
|
const documentMetaCache = new DocumentMetaCache(operationStore, { maxDocuments: 1e3 });
|
|
@@ -8490,20 +8639,24 @@ var ReactorBuilder = class {
|
|
|
8490
8639
|
const executionScope = new KyselyExecutionScope(database, operationStore, operationIndex, keyframeStore, writeCache, documentMetaCache, collectionMembershipCache);
|
|
8491
8640
|
let executorManager = this.executorManager;
|
|
8492
8641
|
let executorStartCount = this.executorConfig.maxConcurrency ?? 1;
|
|
8493
|
-
if (!executorManager)
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
if (
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8642
|
+
if (!executorManager) {
|
|
8643
|
+
if (this.workerPool) {
|
|
8644
|
+
const pool = this.workerPool;
|
|
8645
|
+
let factory = pool.factory;
|
|
8646
|
+
if (!factory) {
|
|
8647
|
+
if (pool.db === void 0) throw new Error("unreachable: worker pool configured without db or factory");
|
|
8648
|
+
if (this.signer && !this.workerSigner) this.logger.warn("Worker pool has no signer spec; pooled workers store synthesized operations unsigned");
|
|
8649
|
+
if (this.trustPolicy && !this.workerTrustPolicy) this.logger.warn("Worker pool has no trust policy spec; pooled workers apply the default trust policy");
|
|
8650
|
+
factory = await this.createDefaultWorkerFactory(pool.numWorkers, pool.db);
|
|
8651
|
+
}
|
|
8652
|
+
const poolManager = new WorkerPoolJobExecutorManager(factory, eventBus, queue, jobTracker, this.logger, resolver, operationIndex, this.executorConfig.jobTimeoutMs, this.executorConfig.deferredJobTtlMs);
|
|
8653
|
+
executorManager = poolManager;
|
|
8654
|
+
executorStartCount = pool.numWorkers;
|
|
8655
|
+
if (resolver instanceof DocumentModelResolver) resolver.setBroadcastHook((entry) => poolManager.loadModel(entry));
|
|
8656
|
+
} else executorManager = new SimpleJobExecutorManager(() => new SimpleJobExecutor(this.logger, documentModelRegistry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, this.driveContainerTypes, this.executorConfig, executionScope, this.signer, this.trustPolicy), eventBus, queue, jobTracker, this.logger, resolver, this.executorConfig.jobTimeoutMs, this.executorConfig.deferredJobTtlMs);
|
|
8657
|
+
}
|
|
8505
8658
|
await executorManager.start(executorStartCount);
|
|
8506
|
-
const callerReadModels = Array.from(new Set([...this.readModels]));
|
|
8659
|
+
const callerReadModels = Array.from(/* @__PURE__ */ new Set([...this.readModels]));
|
|
8507
8660
|
const degradedComponents = [];
|
|
8508
8661
|
const startDegraded = (component, error) => {
|
|
8509
8662
|
degradedComponents.push({
|
|
@@ -8517,7 +8670,7 @@ var ReactorBuilder = class {
|
|
|
8517
8670
|
yieldDeadlineMs: this.executorConfig.yieldDeadlineMs ?? 50
|
|
8518
8671
|
};
|
|
8519
8672
|
const documentViewConsistencyTracker = new ConsistencyTracker();
|
|
8520
|
-
const documentView = new KyselyDocumentView(database, operationStore, operationIndex, writeCache, documentViewConsistencyTracker, featureFlags.documentDecisions ?
|
|
8673
|
+
const documentView = new KyselyDocumentView(database, operationStore, operationIndex, writeCache, documentViewConsistencyTracker, featureFlags.documentDecisions ? "StateAtDeletion" : "NotFound", readModelIndexing);
|
|
8521
8674
|
try {
|
|
8522
8675
|
await documentView.init();
|
|
8523
8676
|
} catch (error) {
|
|
@@ -8573,7 +8726,7 @@ var ReactorBuilder = class {
|
|
|
8573
8726
|
const reactor = new Reactor(this.logger, documentModelRegistry, queue, jobTracker, readModelCoordinator, this.features, documentView, documentIndexer, operationStore, eventBus, executorManager);
|
|
8574
8727
|
let syncModule = void 0;
|
|
8575
8728
|
if (this.channelScheme) {
|
|
8576
|
-
const factory = this.channelScheme ===
|
|
8729
|
+
const factory = this.channelScheme === "connect" ? new GqlRequestChannelFactory(this.logger, this.jwtHandler, queue) : new GqlResponseChannelFactory(this.logger);
|
|
8577
8730
|
syncModule = new SyncBuilder().withChannelFactory(factory).buildModule(reactor, this.logger, operationIndex, eventBus, database, this.driveContainerTypes);
|
|
8578
8731
|
await syncModule.syncManager.startup();
|
|
8579
8732
|
} else if (this.syncBuilder) {
|
|
@@ -8674,7 +8827,7 @@ var ReactorBuilder = class {
|
|
|
8674
8827
|
poolInstrumentations.push(forwarder);
|
|
8675
8828
|
this.instrumentedPools.push(forwarder);
|
|
8676
8829
|
}
|
|
8677
|
-
const { ProjectionShardManager } = await import("./projection-shard-manager-
|
|
8830
|
+
const { ProjectionShardManager } = await import("./projection-shard-manager-B-j8VYzA.js");
|
|
8678
8831
|
const manager = new ProjectionShardManager({
|
|
8679
8832
|
shardCount: config.shardCount,
|
|
8680
8833
|
db,
|
|
@@ -8708,7 +8861,7 @@ var ReactorBuilder = class {
|
|
|
8708
8861
|
return manager;
|
|
8709
8862
|
}
|
|
8710
8863
|
async createDefaultProjectionWorkerFactory() {
|
|
8711
|
-
const [{ createProjectionThreadTransport }, { projectionWorkerEntryPath }] = await Promise.all([import("./transport-
|
|
8864
|
+
const [{ createProjectionThreadTransport }, { projectionWorkerEntryPath }] = await Promise.all([import("./transport-B3G50KVd.js"), import("./projection-worker-D8uNFdwX.js")]);
|
|
8712
8865
|
return () => createProjectionThreadTransport(projectionWorkerEntryPath);
|
|
8713
8866
|
}
|
|
8714
8867
|
/**
|
|
@@ -8716,11 +8869,11 @@ var ReactorBuilder = class {
|
|
|
8716
8869
|
* custom `factory`. Each worker spawns a real `node:worker_threads`
|
|
8717
8870
|
* Worker pointing at the compiled `worker/entry.js`.
|
|
8718
8871
|
*/
|
|
8719
|
-
async createDefaultWorkerFactory(numWorkers, db
|
|
8872
|
+
async createDefaultWorkerFactory(numWorkers, db) {
|
|
8720
8873
|
const [{ WorkerHandle }, { createThreadTransport }, { workerEntryPath }] = await Promise.all([
|
|
8721
|
-
import("./worker-handle-
|
|
8722
|
-
import("./transport-
|
|
8723
|
-
|
|
8874
|
+
import("./worker-handle-CwWNTpUg.js"),
|
|
8875
|
+
import("./transport-CZDHzfvy.js"),
|
|
8876
|
+
Promise.resolve().then(() => worker_exports)
|
|
8724
8877
|
]);
|
|
8725
8878
|
const poolConfig = {
|
|
8726
8879
|
enabled: true,
|
|
@@ -8740,9 +8893,10 @@ var ReactorBuilder = class {
|
|
|
8740
8893
|
initPayload: {
|
|
8741
8894
|
poolConfig,
|
|
8742
8895
|
db,
|
|
8743
|
-
signatureVerifier,
|
|
8744
8896
|
models,
|
|
8745
|
-
executorConfig: this.executorConfig
|
|
8897
|
+
executorConfig: this.executorConfig,
|
|
8898
|
+
signer: this.workerSigner,
|
|
8899
|
+
trustPolicy: this.workerTrustPolicy
|
|
8746
8900
|
},
|
|
8747
8901
|
logger,
|
|
8748
8902
|
poolInstrumentation
|
|
@@ -8985,30 +9139,6 @@ function createHybridProjectionCoordinatorFactory(options = {}) {
|
|
|
8985
9139
|
};
|
|
8986
9140
|
}
|
|
8987
9141
|
//#endregion
|
|
8988
|
-
//#region src/signer/passthrough-signer.ts
|
|
8989
|
-
/**
|
|
8990
|
-
* A no-op signer that returns empty values for all methods.
|
|
8991
|
-
* Used when signing is not required.
|
|
8992
|
-
*/
|
|
8993
|
-
var PassthroughSigner = class {
|
|
8994
|
-
publicKey = {};
|
|
8995
|
-
sign() {
|
|
8996
|
-
return Promise.resolve(new Uint8Array(0));
|
|
8997
|
-
}
|
|
8998
|
-
verify() {
|
|
8999
|
-
return Promise.resolve();
|
|
9000
|
-
}
|
|
9001
|
-
signAction() {
|
|
9002
|
-
return Promise.resolve([
|
|
9003
|
-
"",
|
|
9004
|
-
"",
|
|
9005
|
-
"",
|
|
9006
|
-
"",
|
|
9007
|
-
""
|
|
9008
|
-
]);
|
|
9009
|
-
}
|
|
9010
|
-
};
|
|
9011
|
-
//#endregion
|
|
9012
9142
|
//#region src/core/reactor-client-builder.ts
|
|
9013
9143
|
/**
|
|
9014
9144
|
* Builder class for constructing ReactorClient instances with proper configuration
|
|
@@ -9021,7 +9151,10 @@ var ReactorClientBuilder = class {
|
|
|
9021
9151
|
documentIndexer;
|
|
9022
9152
|
documentView;
|
|
9023
9153
|
signer;
|
|
9024
|
-
|
|
9154
|
+
workerSigner;
|
|
9155
|
+
trustPolicy;
|
|
9156
|
+
workerTrustPolicy;
|
|
9157
|
+
createSignaturePolicy = DEFAULT_SIGNATURE_POLICY;
|
|
9025
9158
|
subscriptionManager;
|
|
9026
9159
|
jobAwaiter;
|
|
9027
9160
|
documentModelLoader;
|
|
@@ -9055,17 +9188,28 @@ var ReactorClientBuilder = class {
|
|
|
9055
9188
|
return this;
|
|
9056
9189
|
}
|
|
9057
9190
|
/**
|
|
9058
|
-
*
|
|
9059
|
-
*
|
|
9060
|
-
*
|
|
9191
|
+
* Signs submitted actions, and the operations a reactor built from
|
|
9192
|
+
* `withReactorBuilder` synthesizes unless that builder has its own signer.
|
|
9193
|
+
* A `trustPolicy` reaches that builder unless it has its own.
|
|
9061
9194
|
*/
|
|
9062
9195
|
withSigner(config) {
|
|
9063
9196
|
if ("signer" in config) {
|
|
9064
9197
|
this.signer = config.signer;
|
|
9065
|
-
this.
|
|
9198
|
+
this.workerSigner = config.workerSigner;
|
|
9199
|
+
this.trustPolicy = config.trustPolicy;
|
|
9200
|
+
this.workerTrustPolicy = config.workerTrustPolicy;
|
|
9066
9201
|
} else this.signer = config;
|
|
9067
9202
|
return this;
|
|
9068
9203
|
}
|
|
9204
|
+
/**
|
|
9205
|
+
* What the client creates new documents as when a call does not say:
|
|
9206
|
+
* `v2-required` (the default) or `legacy`, for a fleet with peers that
|
|
9207
|
+
* predate v2-required documents. Existing documents keep their policy.
|
|
9208
|
+
*/
|
|
9209
|
+
withCreateSignaturePolicy(policy) {
|
|
9210
|
+
this.createSignaturePolicy = policy;
|
|
9211
|
+
return this;
|
|
9212
|
+
}
|
|
9069
9213
|
withSubscriptionManager(subscriptionManager) {
|
|
9070
9214
|
this.subscriptionManager = subscriptionManager;
|
|
9071
9215
|
return this;
|
|
@@ -9130,8 +9274,9 @@ var ReactorClientBuilder = class {
|
|
|
9130
9274
|
let documentView;
|
|
9131
9275
|
let reactorModule;
|
|
9132
9276
|
if (this.reactorBuilder) {
|
|
9133
|
-
if (this.signatureVerifier) this.reactorBuilder.withSignatureVerifier(this.signatureVerifier);
|
|
9134
9277
|
if (this.documentModelLoader) this.reactorBuilder.withDocumentModelLoader(this.documentModelLoader);
|
|
9278
|
+
if (this.signer && !this.reactorBuilder.hasSigner()) this.reactorBuilder.withSigner(this.signer, this.workerSigner);
|
|
9279
|
+
if (this.trustPolicy && !this.reactorBuilder.hasTrustPolicy()) this.reactorBuilder.withTrustPolicy(this.trustPolicy, this.workerTrustPolicy);
|
|
9135
9280
|
reactorModule = await this.reactorBuilder.buildModule();
|
|
9136
9281
|
reactor = reactorModule.reactor;
|
|
9137
9282
|
eventBus = reactorModule.eventBus;
|
|
@@ -9149,7 +9294,7 @@ var ReactorClientBuilder = class {
|
|
|
9149
9294
|
const jobAwaiter = this.jobAwaiter ?? new JobAwaiter(eventBus, (jobId, signal) => reactor.getJobStatus(jobId, signal));
|
|
9150
9295
|
const decisionModel = reactorModule ? readDecisionModel(reactorModule.featureFlags, reactorModule.documentModelRegistry) : void 0;
|
|
9151
9296
|
return {
|
|
9152
|
-
client: new ReactorClient(this.logger, reactor, signer, subscriptionManager, jobAwaiter, documentIndexer, documentView, this.readGate ?? this.resolveReadGate(reactorModule, documentView, decisionModel), this.resolveActionEvaluation(reactorModule, decisionModel)),
|
|
9297
|
+
client: new ReactorClient(this.logger, reactor, signer, subscriptionManager, jobAwaiter, documentIndexer, documentView, this.readGate ?? this.resolveReadGate(reactorModule, documentView, decisionModel), this.resolveActionEvaluation(reactorModule, decisionModel), this.createSignaturePolicy),
|
|
9153
9298
|
reactor,
|
|
9154
9299
|
eventBus,
|
|
9155
9300
|
documentIndexer,
|
|
@@ -9187,6 +9332,38 @@ function driveIdFromUrl(url) {
|
|
|
9187
9332
|
return url.split("/").pop() ?? "";
|
|
9188
9333
|
}
|
|
9189
9334
|
//#endregion
|
|
9335
|
+
//#region src/signer/types.ts
|
|
9336
|
+
const SIGNATURE_REFUSAL_CODES = [
|
|
9337
|
+
"UNSIGNED_REQUIRED",
|
|
9338
|
+
"UNSIGNED_IDENTITY",
|
|
9339
|
+
"KEY_MISMATCH",
|
|
9340
|
+
"MALFORMED_TUPLE",
|
|
9341
|
+
"TIMESTAMP_MISMATCH",
|
|
9342
|
+
"HASH_MISMATCH",
|
|
9343
|
+
"BAD_SIGNATURE",
|
|
9344
|
+
"SCHEME_BELOW_POLICY",
|
|
9345
|
+
"ID_MISMATCH",
|
|
9346
|
+
"DUPLICATE_ACTION",
|
|
9347
|
+
"SIGNER_UNAUTHORIZED"
|
|
9348
|
+
];
|
|
9349
|
+
//#endregion
|
|
9350
|
+
//#region src/executor/worker/index.ts
|
|
9351
|
+
var worker_exports = /* @__PURE__ */ __exportAll({
|
|
9352
|
+
createForwardingLogger: () => createForwardingLogger,
|
|
9353
|
+
errorToInfo: () => errorToInfo,
|
|
9354
|
+
sanitizeArg: () => sanitizeArg,
|
|
9355
|
+
workerEntryPath: () => workerEntryPath
|
|
9356
|
+
});
|
|
9357
|
+
function resolveWorkerEntryPath() {
|
|
9358
|
+
const url = new URL("./entry.js", import.meta.url);
|
|
9359
|
+
if (url.protocol !== "file:") return url.href;
|
|
9360
|
+
let pathname = decodeURIComponent(url.pathname);
|
|
9361
|
+
if (/^\/[A-Za-z]:[/\\]/.test(pathname)) pathname = pathname.slice(1);
|
|
9362
|
+
return pathname;
|
|
9363
|
+
}
|
|
9364
|
+
/** Absolute path to the worker entry script for use with `new Worker(workerEntryPath)`. */
|
|
9365
|
+
const workerEntryPath = resolveWorkerEntryPath();
|
|
9366
|
+
//#endregion
|
|
9190
9367
|
//#region src/decision/sync-scope-gate.ts
|
|
9191
9368
|
/** What a subject may read of a document that is not there to be read. */
|
|
9192
9369
|
const META_ONLY = (scope) => ALWAYS_READABLE_SCOPES.has(scope);
|
|
@@ -9198,6 +9375,9 @@ const META_ONLY = (scope) => ALWAYS_READABLE_SCOPES.has(scope);
|
|
|
9198
9375
|
* path's own job, and it is the only thing this adds to the gate it wraps.
|
|
9199
9376
|
*/
|
|
9200
9377
|
var SyncScopeGate = class {
|
|
9378
|
+
gate;
|
|
9379
|
+
documentView;
|
|
9380
|
+
logger;
|
|
9201
9381
|
constructor(gate, documentView, logger) {
|
|
9202
9382
|
this.gate = gate;
|
|
9203
9383
|
this.documentView = documentView;
|
|
@@ -9414,6 +9594,6 @@ var DocumentIntegrityService = class {
|
|
|
9414
9594
|
}
|
|
9415
9595
|
};
|
|
9416
9596
|
//#endregion
|
|
9417
|
-
export { ALWAYS_READABLE_SCOPES, APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, AuthEnforcementDisabledError, BareReadGate, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_COMMIT_CHUNK_SIZE, DEFAULT_DRIVE_CONTAINER_TYPES, DEFAULT_READ_MODEL_YIELD_DEADLINE_MS, DOCUMENT_INDEXER_READ_MODEL, DOCUMENT_VIEW_READ_MODEL, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DeletedDocumentRead, 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, defaultReadModelIndexingConfig, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, isRecoverableGraphQLError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, readDecisionModel, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, unchunkedReadModelIndexingConfig, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
9597
|
+
export { ALWAYS_READABLE_SCOPES, APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, AuthEnforcementDisabledError, BareReadGate, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_COMMIT_CHUNK_SIZE, DEFAULT_DRIVE_CONTAINER_TYPES, DEFAULT_READ_MODEL_YIELD_DEADLINE_MS, DOCUMENT_INDEXER_READ_MODEL, DOCUMENT_VIEW_READ_MODEL, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DeletedDocumentRead, 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, InvalidSignatureError, 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, SIGNATURE_REFUSAL_CODES, SeededStateReader, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncScopeGate, SyncStatus, SyncStatusTracker, addRelationshipAction, authDecisionModel, batchOperationsByDocument, buildDecisionModel, classifyJobFailure, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createHybridProjectionCoordinatorFactory, createMutableShutdownStatus, createReactorHostModuleBase, createRelationalDb, decideAtHead, defaultReadModelIndexingConfig, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, isRecoverableGraphQLError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, readDecisionModel, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, unchunkedReadModelIndexingConfig, updateRelationshipAction, upgradeDocumentAction, verifyActionSignature, workerEntryPath };
|
|
9418
9598
|
|
|
9419
9599
|
//# sourceMappingURL=index.js.map
|