@powerhousedao/reactor 6.2.2-dev.36 → 6.2.2-dev.38
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-B9gIvuvf.js → build-worker-executor-CAEZD_yJ.js} +2 -2
- package/dist/{build-worker-executor-B9gIvuvf.js.map → build-worker-executor-CAEZD_yJ.js.map} +1 -1
- package/dist/{document-indexer-BY-mPXJF.js → document-indexer-C0GB0b8Q.js} +11 -5
- package/dist/document-indexer-C0GB0b8Q.js.map +1 -0
- package/dist/{drive-container-types-ZSLCC3lC.js → drive-container-types-BJCKXJwH.js} +607 -178
- package/dist/drive-container-types-BJCKXJwH.js.map +1 -0
- package/dist/entry.js +2 -2
- package/dist/index.d.ts +215 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +225 -83
- package/dist/index.js.map +1 -1
- package/dist/projection-entry.js +4 -4
- package/dist/projection-entry.js.map +1 -1
- package/dist/{worker-BMn-2vsH.js → worker-jEJW6_j7.js} +2 -2
- package/dist/{worker-BMn-2vsH.js.map → worker-jEJW6_j7.js.map} +1 -1
- package/package.json +5 -4
- package/dist/document-indexer-BY-mPXJF.js.map +0 -1
- package/dist/drive-container-types-ZSLCC3lC.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as OptimisticLockError, B as ExcessiveReshuffleError, C as DocumentMetaCache, D as APPEND_CONDITION_FAILED_PREFIX, E as CollectionMembershipCache, F as ModuleNotFoundError, H as matchesScope, I as AuthTimestampNotMonotonicError, L as AuthorizationDeniedError, M as DuplicateManifestError, N as DuplicateModuleError, O as AppendConditionFailedError, P as InvalidModuleError, R as DocumentDeletedError, S as KyselyOperationIndex, T as createEmptyConsistencyToken, U as parsePagingOptions, V as InvalidOperationTimestampError, W as throwIfAborted, _ as KyselyExecutionScope, a as createForwardingPoolInstrumentation, b as EventBus, c as KyselyKeyframeStore, d as DriveCollectionId, f as decideAtHead, g as authDecisionModel, h as buildDecisionModel, i as runMigrations, j as RevisionMismatchError, k as DuplicateOperationError, l as DocumentModelRegistry, m as documentDecisionModel, n as REACTOR_SCHEMA, o as instrumentPgPool, p as selectDecisionModel, r as getMigrationStatus, s as KyselyOperationStore, t as DEFAULT_DRIVE_CONTAINER_TYPES, u as SimpleJobExecutor, v as FLAG_PREREQUISITES, w as createConsistencyToken, x as KyselyWriteCache, y as validateFeatureFlags, z as DocumentNotFoundError } from "./drive-container-types-BJCKXJwH.js";
|
|
2
2
|
import { n as ReactorEventTypes, t as EventBusAggregateError } from "./types-DMKLa0Ok.js";
|
|
3
3
|
import { i as WorkerInitFailedError, r as WorkerExitedError, t as WorkerAbortTimeoutError } from "./errors-D3S6Eysd.js";
|
|
4
|
-
import { a as ReadModelCoordinator, i as KyselyDocumentView, n as ConsistencyTracker, o as BaseReadModel, r as makeConsistencyKey, t as KyselyDocumentIndexer } from "./document-indexer-
|
|
4
|
+
import { a as ReadModelCoordinator, i as KyselyDocumentView, n as ConsistencyTracker, o as BaseReadModel, r as makeConsistencyKey, t as KyselyDocumentIndexer } from "./document-indexer-C0GB0b8Q.js";
|
|
5
5
|
import { n as errorToInfo, r as sanitizeArg, t as createForwardingLogger } from "./forwarding-logger-BBkMSxuJ.js";
|
|
6
|
-
import { t as workerEntryPath } from "./worker-
|
|
7
|
-
import { actions, actions as documentActions, createPresignedHeader, decide, generateId, hashDocumentStateForScope, replayDocument } from "@powerhousedao/shared/document-model";
|
|
6
|
+
import { t as workerEntryPath } from "./worker-jEJW6_j7.js";
|
|
7
|
+
import { actions, actions as documentActions, createPresignedHeader, decide, garbageCollect, generateId, hashDocumentStateForScope, replayDocument, sortOperations } from "@powerhousedao/shared/document-model";
|
|
8
8
|
import { addFile, addFolder, copyNode, deleteNode, driveCreateDocument, generateNodesCopy, getDescendants, handleTargetNameCollisions, isFileNode, isFolderNode, moveNode, updateNode } from "@powerhousedao/shared/document-drive";
|
|
9
9
|
import { v4 } from "uuid";
|
|
10
10
|
import { ConsoleLogger, childLogger } from "document-model";
|
|
@@ -190,10 +190,12 @@ function topologicalSort(jobs) {
|
|
|
190
190
|
*/
|
|
191
191
|
function toErrorInfo$1(error) {
|
|
192
192
|
if (error instanceof Error) return {
|
|
193
|
+
name: error.name,
|
|
193
194
|
message: error.message,
|
|
194
195
|
stack: error.stack || (/* @__PURE__ */ new Error()).stack || ""
|
|
195
196
|
};
|
|
196
197
|
return {
|
|
198
|
+
name: "Error",
|
|
197
199
|
message: error,
|
|
198
200
|
stack: (/* @__PURE__ */ new Error()).stack || ""
|
|
199
201
|
};
|
|
@@ -705,13 +707,19 @@ function filterReadableScopes(document, subject) {
|
|
|
705
707
|
const state = document.state;
|
|
706
708
|
if (!state) return document;
|
|
707
709
|
const auth = document.state.auth;
|
|
708
|
-
const
|
|
709
|
-
for (const scope of Object.keys(state)) if (canReadScope(auth, subject, scope)) filtered[scope] = state[scope];
|
|
710
|
+
const readable = (scope) => canReadScope(auth, subject, scope);
|
|
710
711
|
return {
|
|
711
712
|
...document,
|
|
712
|
-
state:
|
|
713
|
+
state: keepReadableScopes(state, readable),
|
|
714
|
+
initialState: keepReadableScopes(document.initialState, readable)
|
|
713
715
|
};
|
|
714
716
|
}
|
|
717
|
+
function keepReadableScopes(scopes, readable) {
|
|
718
|
+
if (!scopes) return scopes;
|
|
719
|
+
const kept = {};
|
|
720
|
+
for (const scope of Object.keys(scopes)) if (readable(scope)) kept[scope] = scopes[scope];
|
|
721
|
+
return kept;
|
|
722
|
+
}
|
|
715
723
|
//#endregion
|
|
716
724
|
//#region src/client/reactor-client.ts
|
|
717
725
|
/**
|
|
@@ -777,8 +785,8 @@ var ReactorClient = class {
|
|
|
777
785
|
* same lookup as the data path. Resolves against the "main" branch. Throws if
|
|
778
786
|
* the identifier cannot be resolved or is ambiguous.
|
|
779
787
|
*/
|
|
780
|
-
async resolveIdOrSlug(identifier, signal) {
|
|
781
|
-
return this.documentView.resolveIdOrSlug(identifier,
|
|
788
|
+
async resolveIdOrSlug(identifier, view, signal) {
|
|
789
|
+
return this.documentView.resolveIdOrSlug(identifier, view, void 0, signal);
|
|
782
790
|
}
|
|
783
791
|
/**
|
|
784
792
|
* Retrieves operations for a document
|
|
@@ -1127,13 +1135,15 @@ var ReactorClient = class {
|
|
|
1127
1135
|
*/
|
|
1128
1136
|
subscribe(search, callback, view) {
|
|
1129
1137
|
this.logger.verbose("subscribe(@search, @view)", search, view);
|
|
1138
|
+
const subject = this.readSubject(view?.subject);
|
|
1139
|
+
const readable = (document) => filterReadableScopes(document, subject);
|
|
1130
1140
|
const unsubscribeCreated = this.subscriptionManager.onDocumentCreated((result) => {
|
|
1131
1141
|
(async () => {
|
|
1132
1142
|
try {
|
|
1133
|
-
const documents = await Promise.all(result.results.map((id) => this.reactor.get(id, view, void 0, void 0)));
|
|
1143
|
+
const documents = await Promise.all(result.results.map((id) => this.reactor.get(id, withAuthScope(view), void 0, void 0)));
|
|
1134
1144
|
callback({
|
|
1135
1145
|
type: DocumentChangeType.Created,
|
|
1136
|
-
documents
|
|
1146
|
+
documents: documents.map(readable)
|
|
1137
1147
|
});
|
|
1138
1148
|
} catch {}
|
|
1139
1149
|
})();
|
|
@@ -1148,7 +1158,7 @@ var ReactorClient = class {
|
|
|
1148
1158
|
const unsubscribeUpdated = this.subscriptionManager.onDocumentStateUpdated((result) => {
|
|
1149
1159
|
callback({
|
|
1150
1160
|
type: DocumentChangeType.Updated,
|
|
1151
|
-
documents: result.results
|
|
1161
|
+
documents: result.results.map(readable)
|
|
1152
1162
|
});
|
|
1153
1163
|
}, search, view);
|
|
1154
1164
|
const unsubscribeRelationship = this.subscriptionManager.onRelationshipChanged((parentId, childId, changeType) => {
|
|
@@ -1214,10 +1224,12 @@ const QueueEventTypes = { JOB_AVAILABLE: 1e4 };
|
|
|
1214
1224
|
const MAX_EXEMPT_CONFLICT_RETRIES = 20;
|
|
1215
1225
|
function toErrorInfo(error) {
|
|
1216
1226
|
if (error instanceof Error) return {
|
|
1227
|
+
name: error.name,
|
|
1217
1228
|
message: error.message,
|
|
1218
1229
|
stack: error.stack || (/* @__PURE__ */ new Error()).stack || ""
|
|
1219
1230
|
};
|
|
1220
1231
|
return {
|
|
1232
|
+
name: "Error",
|
|
1221
1233
|
message: error,
|
|
1222
1234
|
stack: (/* @__PURE__ */ new Error()).stack || ""
|
|
1223
1235
|
};
|
|
@@ -1262,7 +1274,7 @@ var JobResultHandler = class {
|
|
|
1262
1274
|
callbacks.deferJob(handle.job.documentId, handle.job);
|
|
1263
1275
|
return;
|
|
1264
1276
|
}
|
|
1265
|
-
if (result.error && (DocumentDeletedError.isError(result.error) || AuthorizationDeniedError.isError(result.error))) {
|
|
1277
|
+
if (result.error && (DocumentDeletedError.isError(result.error) || AuthorizationDeniedError.isError(result.error) || AuthTimestampNotMonotonicError.isError(result.error) || InvalidOperationTimestampError.isError(result.error) || ExcessiveReshuffleError.isError(result.error))) {
|
|
1266
1278
|
const errorInfo = toErrorInfo(result.error);
|
|
1267
1279
|
this.jobTracker.markFailed(handle.job.id, errorInfo, handle.job);
|
|
1268
1280
|
this.eventBus.emit(ReactorEventTypes.JOB_FAILED, {
|
|
@@ -1321,6 +1333,7 @@ var JobResultHandler = class {
|
|
|
1321
1333
|
stackLines.push(`[Attempt ${index + 1}] Stack trace:\n${error.stack}`);
|
|
1322
1334
|
});
|
|
1323
1335
|
return {
|
|
1336
|
+
name: currentError.name,
|
|
1324
1337
|
message: messageLines.join("\n"),
|
|
1325
1338
|
stack: stackLines.join("\n\n")
|
|
1326
1339
|
};
|
|
@@ -1685,29 +1698,6 @@ function extractMembershipTarget(op) {
|
|
|
1685
1698
|
if (actionType === "DELETE_DOCUMENT") return input?.documentId ?? op.context.documentId;
|
|
1686
1699
|
}
|
|
1687
1700
|
//#endregion
|
|
1688
|
-
//#region src/core/feature-flags.ts
|
|
1689
|
-
/**
|
|
1690
|
-
* Every flag this reactor knows, with the flags it requires. A stage adds its
|
|
1691
|
-
* flag here when it ships, so asking an older reactor for a later stage's flag
|
|
1692
|
-
* is an unrecognized name rather than a flag that quietly does nothing.
|
|
1693
|
-
*/
|
|
1694
|
-
const FLAG_PREREQUISITES = { documentDecisions: [] };
|
|
1695
|
-
/**
|
|
1696
|
-
* Throws when the flags ask for enforcement the reactor cannot deliver. Either
|
|
1697
|
-
* failure would otherwise read as enforcement being on while the reactor
|
|
1698
|
-
* applies less than the caller asked for.
|
|
1699
|
-
*/
|
|
1700
|
-
function validateFeatureFlags(flags, prerequisites) {
|
|
1701
|
-
const known = Object.keys(prerequisites);
|
|
1702
|
-
const unrecognized = Object.keys(flags).filter((name) => !known.includes(name));
|
|
1703
|
-
if (unrecognized.length > 0) throw new Error(`Unrecognized reactor feature flag: ${unrecognized.join(", ")}. This reactor knows: ${known.join(", ")}.`);
|
|
1704
|
-
for (const name of known) {
|
|
1705
|
-
if (flags[name] !== true) continue;
|
|
1706
|
-
const missing = prerequisites[name].filter((required) => flags[required] !== true);
|
|
1707
|
-
if (missing.length > 0) throw new Error(`Reactor feature flag ${name} requires ${missing.join(", ")}.`);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
//#endregion
|
|
1711
1701
|
//#region src/executor/simple-job-executor-manager.ts
|
|
1712
1702
|
/**
|
|
1713
1703
|
* Manages multiple job executors and coordinates job distribution.
|
|
@@ -1949,6 +1939,7 @@ var InMemoryJobTracker = class {
|
|
|
1949
1939
|
}
|
|
1950
1940
|
handleJobFailed(event) {
|
|
1951
1941
|
this.markFailed(event.jobId, {
|
|
1942
|
+
name: event.error.name,
|
|
1952
1943
|
message: event.error.message,
|
|
1953
1944
|
stack: event.error.stack || ""
|
|
1954
1945
|
}, event.job);
|
|
@@ -2410,10 +2401,12 @@ var InMemoryQueue = class {
|
|
|
2410
2401
|
}
|
|
2411
2402
|
toErrorInfo(error) {
|
|
2412
2403
|
if (error instanceof Error) return {
|
|
2404
|
+
name: error.name,
|
|
2413
2405
|
message: error.message,
|
|
2414
2406
|
stack: error.stack || (/* @__PURE__ */ new Error()).stack || ""
|
|
2415
2407
|
};
|
|
2416
2408
|
return {
|
|
2409
|
+
name: "Error",
|
|
2417
2410
|
message: error,
|
|
2418
2411
|
stack: (/* @__PURE__ */ new Error()).stack || ""
|
|
2419
2412
|
};
|
|
@@ -2501,6 +2494,7 @@ var InMemoryQueue = class {
|
|
|
2501
2494
|
await this.resolver.ensureModelLoaded(documentType);
|
|
2502
2495
|
} catch {
|
|
2503
2496
|
await this.failJob(job.id, {
|
|
2497
|
+
name: "Error",
|
|
2504
2498
|
message: `Failed to load document model for type: ${documentType}`,
|
|
2505
2499
|
stack: (/* @__PURE__ */ new Error()).stack || ""
|
|
2506
2500
|
});
|
|
@@ -3537,11 +3531,18 @@ var PollingChannelError = class extends Error {
|
|
|
3537
3531
|
var ChannelError = class extends Error {
|
|
3538
3532
|
source;
|
|
3539
3533
|
error;
|
|
3540
|
-
|
|
3534
|
+
/**
|
|
3535
|
+
* The classification when something other than the error carries it. Absent
|
|
3536
|
+
* means derive it from `error.name`; a dead letter mirrored from a peer sets it,
|
|
3537
|
+
* because only the message crosses the wire.
|
|
3538
|
+
*/
|
|
3539
|
+
errorType;
|
|
3540
|
+
constructor(source, error, errorType) {
|
|
3541
3541
|
super(`ChannelError[${source}]: ${error.message}`);
|
|
3542
3542
|
this.name = "ChannelError";
|
|
3543
3543
|
this.source = source;
|
|
3544
3544
|
this.error = error;
|
|
3545
|
+
this.errorType = errorType;
|
|
3545
3546
|
}
|
|
3546
3547
|
};
|
|
3547
3548
|
//#endregion
|
|
@@ -3912,6 +3913,33 @@ function splitComponent(items, maxSize) {
|
|
|
3912
3913
|
for (let i = 0; i < sorted.length; i += maxSize) chunks.push(sorted.slice(i, i + maxSize));
|
|
3913
3914
|
return chunks;
|
|
3914
3915
|
}
|
|
3916
|
+
/**
|
|
3917
|
+
* Classifies a failure by error name rather than `instanceof`, because a failure
|
|
3918
|
+
* that crossed the pooled-worker boundary arrives as plain data.
|
|
3919
|
+
*/
|
|
3920
|
+
function classifyJobFailure(errorName) {
|
|
3921
|
+
switch (errorName) {
|
|
3922
|
+
case "AuthTimestampNotMonotonicError": return "AUTH_TIMESTAMP_NOT_MONOTONIC";
|
|
3923
|
+
case "InvalidOperationTimestampError": return "INVALID_TIMESTAMP";
|
|
3924
|
+
case "ExcessiveReshuffleError": return "EXCESSIVE_SHUFFLE";
|
|
3925
|
+
case "InvalidSignatureError": return "SIGNATURE_INVALID";
|
|
3926
|
+
case "HashMismatchError": return "HASH_MISMATCH";
|
|
3927
|
+
default: return "UNCLASSIFIED";
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
/** The explicit type when something else carried it, else derived by name. */
|
|
3931
|
+
function syncOperationErrorType(error) {
|
|
3932
|
+
return error?.errorType ?? classifyJobFailure(error?.error?.name ?? "Error");
|
|
3933
|
+
}
|
|
3934
|
+
/** Dead-letter types that must not stop the document syncing. */
|
|
3935
|
+
const NON_QUARANTINING_ERROR_TYPES = new Set(["AUTH_TIMESTAMP_NOT_MONOTONIC"]);
|
|
3936
|
+
/**
|
|
3937
|
+
* A held auth operation must not quarantine: reconciling the two policies needs
|
|
3938
|
+
* the traffic a quarantine would stop.
|
|
3939
|
+
*/
|
|
3940
|
+
function quarantinesDocument(errorType) {
|
|
3941
|
+
return !NON_QUARANTINING_ERROR_TYPES.has(errorType);
|
|
3942
|
+
}
|
|
3915
3943
|
//#endregion
|
|
3916
3944
|
//#region src/sync/channels/interval-poll-timer.ts
|
|
3917
3945
|
const DEFAULT_CONFIG = {
|
|
@@ -4074,7 +4102,7 @@ function serializeEnvelope(envelope) {
|
|
|
4074
4102
|
hash: opWithContext.operation.hash,
|
|
4075
4103
|
skip: opWithContext.operation.skip,
|
|
4076
4104
|
error: opWithContext.operation.error,
|
|
4077
|
-
deniedReason: opWithContext.operation.deniedReason,
|
|
4105
|
+
...opWithContext.operation.deniedReason !== void 0 ? { deniedReason: opWithContext.operation.deniedReason } : {},
|
|
4078
4106
|
id: opWithContext.operation.id,
|
|
4079
4107
|
action: serializeAction(opWithContext.operation.action)
|
|
4080
4108
|
},
|
|
@@ -4102,21 +4130,33 @@ function deserializeSignature(sig) {
|
|
|
4102
4130
|
return sig.split(", ");
|
|
4103
4131
|
}
|
|
4104
4132
|
/**
|
|
4105
|
-
*
|
|
4106
|
-
*
|
|
4107
|
-
*
|
|
4108
|
-
* strings. This function restores them to the Signature tuple format required for verification.
|
|
4133
|
+
* `isDenied` tests strictly against undefined, so a null left in place would mark
|
|
4134
|
+
* every synced operation denied. The key is removed rather than set to undefined,
|
|
4135
|
+
* so an operation that arrived without it stays identical to the one sent.
|
|
4109
4136
|
*/
|
|
4110
|
-
function
|
|
4111
|
-
const
|
|
4112
|
-
if (
|
|
4137
|
+
function normalizeAbsentFields(operation) {
|
|
4138
|
+
const wire = operation;
|
|
4139
|
+
if (wire.error !== null && wire.deniedReason !== null) return operation;
|
|
4140
|
+
const normalized = { ...operation };
|
|
4141
|
+
if (wire.error === null) delete normalized.error;
|
|
4142
|
+
if (wire.deniedReason === null) delete normalized.deniedReason;
|
|
4143
|
+
return normalized;
|
|
4144
|
+
}
|
|
4145
|
+
/** Restores signature tuples and null-valued optional fields to undefined. */
|
|
4146
|
+
function deserializeOperation(opWithContext) {
|
|
4147
|
+
const operation = normalizeAbsentFields(opWithContext.operation);
|
|
4148
|
+
const signer = operation.action.context?.signer;
|
|
4149
|
+
if (!signer?.signatures || signer.signatures.length === 0) return {
|
|
4150
|
+
...opWithContext,
|
|
4151
|
+
operation
|
|
4152
|
+
};
|
|
4113
4153
|
const deserializedSignatures = signer.signatures.map(deserializeSignature);
|
|
4114
4154
|
const deserializedOperation = {
|
|
4115
|
-
...
|
|
4155
|
+
...operation,
|
|
4116
4156
|
action: {
|
|
4117
|
-
...
|
|
4157
|
+
...operation.action,
|
|
4118
4158
|
context: {
|
|
4119
|
-
...
|
|
4159
|
+
...operation.action.context,
|
|
4120
4160
|
signer: {
|
|
4121
4161
|
...signer,
|
|
4122
4162
|
signatures: deserializedSignatures
|
|
@@ -4143,7 +4183,7 @@ function deserializeOperationSignatures(opWithContext) {
|
|
|
4143
4183
|
*/
|
|
4144
4184
|
function envelopesToSyncOperations(envelope, remoteName) {
|
|
4145
4185
|
if (!envelope.operations || envelope.operations.length === 0) return [];
|
|
4146
|
-
return batchOperationsByDocument(envelope.operations.map(
|
|
4186
|
+
return batchOperationsByDocument(envelope.operations.map(deserializeOperation)).map((batch) => {
|
|
4147
4187
|
return new SyncOperation(`syncop-${envelope.channelMeta.id}-${Date.now()}-${syncOpCounter++}`, envelope.key ?? "", (envelope.dependsOn ?? []).filter(Boolean), remoteName, batch.documentId, [batch.scope], batch.branch, batch.operations);
|
|
4148
4188
|
});
|
|
4149
4189
|
}
|
|
@@ -4155,6 +4195,12 @@ const getLatestAppliedOrdinal = (syncOps) => {
|
|
|
4155
4195
|
//#endregion
|
|
4156
4196
|
//#region src/sync/channels/gql-req-channel.ts
|
|
4157
4197
|
/**
|
|
4198
|
+
* Fields the auth projection added to the sync schema. A remote that predates
|
|
4199
|
+
* them rejects the whole query for naming one, so they are selected only while
|
|
4200
|
+
* the remote is known to serve them.
|
|
4201
|
+
*/
|
|
4202
|
+
const DECISION_FIELDS = ["deniedReason", "errorType"];
|
|
4203
|
+
/**
|
|
4158
4204
|
* GraphQL-based synchronization channel for network communication between reactors.
|
|
4159
4205
|
*/
|
|
4160
4206
|
var GqlRequestChannel = class {
|
|
@@ -4181,6 +4227,8 @@ var GqlRequestChannel = class {
|
|
|
4181
4227
|
isPushing = false;
|
|
4182
4228
|
pendingDrain = false;
|
|
4183
4229
|
receivingPages = false;
|
|
4230
|
+
/** Cleared for good the first time the remote rejects {@link DECISION_FIELDS}. */
|
|
4231
|
+
peerServesDecisionFields = true;
|
|
4184
4232
|
isRecovering = false;
|
|
4185
4233
|
connectionState = "connecting";
|
|
4186
4234
|
/** Latest unrecoverable error was an auth rejection; cleared on connect. */
|
|
@@ -4359,7 +4407,7 @@ var GqlRequestChannel = class {
|
|
|
4359
4407
|
const syncOps = [];
|
|
4360
4408
|
for (const dl of deadLetters) {
|
|
4361
4409
|
const syncOp = new SyncOperation(crypto.randomUUID(), dl.jobId, [], this.remoteName, dl.documentId, dl.scopes, dl.branch, []);
|
|
4362
|
-
syncOp.failed(new ChannelError(ChannelErrorSource.Outbox, new Error(dl.error)));
|
|
4410
|
+
syncOp.failed(new ChannelError(ChannelErrorSource.Outbox, new Error(dl.error), dl.errorType ?? void 0));
|
|
4363
4411
|
syncOps.push(syncOp);
|
|
4364
4412
|
}
|
|
4365
4413
|
this.deadLetter.add(...syncOps);
|
|
@@ -4451,7 +4499,44 @@ var GqlRequestChannel = class {
|
|
|
4451
4499
|
* Queries the remote GraphQL endpoint for sync envelopes.
|
|
4452
4500
|
*/
|
|
4453
4501
|
async pollSyncEnvelopes(ackOrdinal, latestOrdinal) {
|
|
4454
|
-
const
|
|
4502
|
+
const variables = {
|
|
4503
|
+
channelId: this.channelId,
|
|
4504
|
+
outboxAck: ackOrdinal,
|
|
4505
|
+
outboxLatest: latestOrdinal
|
|
4506
|
+
};
|
|
4507
|
+
let response;
|
|
4508
|
+
try {
|
|
4509
|
+
response = await this.executeGraphQL(this.pollQuery(this.peerServesDecisionFields), variables);
|
|
4510
|
+
} catch (error) {
|
|
4511
|
+
if (!this.rejectsDecisionFields(error)) throw error;
|
|
4512
|
+
this.logger.warn("Remote @channelId does not serve deniedReason/errorType; polling without them. The remote is on an older schema, so it has neither to report.", this.channelId);
|
|
4513
|
+
this.peerServesDecisionFields = false;
|
|
4514
|
+
response = await this.executeGraphQL(this.pollQuery(false), variables);
|
|
4515
|
+
}
|
|
4516
|
+
return {
|
|
4517
|
+
envelopes: response.pollSyncEnvelopes.envelopes,
|
|
4518
|
+
ackOrdinal: response.pollSyncEnvelopes.ackOrdinal,
|
|
4519
|
+
deadLetters: response.pollSyncEnvelopes.deadLetters ?? [],
|
|
4520
|
+
hasMore: response.pollSyncEnvelopes.hasMore
|
|
4521
|
+
};
|
|
4522
|
+
}
|
|
4523
|
+
/**
|
|
4524
|
+
* True when the remote rejected the query for naming a field it does not
|
|
4525
|
+
* have. Selecting an unknown field fails validation for the whole query, so
|
|
4526
|
+
* an unhandled one takes the channel's polling down until the process
|
|
4527
|
+
* restarts rather than degrading.
|
|
4528
|
+
*/
|
|
4529
|
+
rejectsDecisionFields(error) {
|
|
4530
|
+
if (!this.peerServesDecisionFields) return false;
|
|
4531
|
+
if (!(error instanceof GraphQLRequestError) || error.category !== "graphql") return false;
|
|
4532
|
+
return DECISION_FIELDS.some((field) => error.message.includes(field));
|
|
4533
|
+
}
|
|
4534
|
+
/**
|
|
4535
|
+
* The poll query. `withDecisionFields` selects the two fields added with the
|
|
4536
|
+
* auth projection; a remote on the previous schema is polled without them.
|
|
4537
|
+
*/
|
|
4538
|
+
pollQuery(withDecisionFields) {
|
|
4539
|
+
return `
|
|
4455
4540
|
query PollSyncEnvelopes($channelId: String!, $outboxAck: Int!, $outboxLatest: Int!) {
|
|
4456
4541
|
pollSyncEnvelopes(channelId: $channelId, outboxAck: $outboxAck, outboxLatest: $outboxLatest) {
|
|
4457
4542
|
envelopes {
|
|
@@ -4466,6 +4551,7 @@ var GqlRequestChannel = class {
|
|
|
4466
4551
|
hash
|
|
4467
4552
|
skip
|
|
4468
4553
|
error
|
|
4554
|
+
${withDecisionFields ? "deniedReason" : ""}
|
|
4469
4555
|
id
|
|
4470
4556
|
action {
|
|
4471
4557
|
id
|
|
@@ -4509,6 +4595,7 @@ var GqlRequestChannel = class {
|
|
|
4509
4595
|
deadLetters {
|
|
4510
4596
|
documentId
|
|
4511
4597
|
error
|
|
4598
|
+
${withDecisionFields ? "errorType" : ""}
|
|
4512
4599
|
jobId
|
|
4513
4600
|
branch
|
|
4514
4601
|
scopes
|
|
@@ -4518,18 +4605,6 @@ var GqlRequestChannel = class {
|
|
|
4518
4605
|
}
|
|
4519
4606
|
}
|
|
4520
4607
|
`;
|
|
4521
|
-
const variables = {
|
|
4522
|
-
channelId: this.channelId,
|
|
4523
|
-
outboxAck: ackOrdinal,
|
|
4524
|
-
outboxLatest: latestOrdinal
|
|
4525
|
-
};
|
|
4526
|
-
const response = await this.executeGraphQL(query, variables);
|
|
4527
|
-
return {
|
|
4528
|
-
envelopes: response.pollSyncEnvelopes.envelopes,
|
|
4529
|
-
ackOrdinal: response.pollSyncEnvelopes.ackOrdinal,
|
|
4530
|
-
deadLetters: response.pollSyncEnvelopes.deadLetters ?? [],
|
|
4531
|
-
hasMore: response.pollSyncEnvelopes.hasMore
|
|
4532
|
-
};
|
|
4533
4608
|
}
|
|
4534
4609
|
/**
|
|
4535
4610
|
* Registers or updates this channel on the remote server via GraphQL mutation.
|
|
@@ -5011,7 +5086,8 @@ function rowToDeadLetterRecord(row) {
|
|
|
5011
5086
|
branch: row.branch,
|
|
5012
5087
|
operations: row.operations,
|
|
5013
5088
|
errorSource: row.error_source,
|
|
5014
|
-
errorMessage: row.error_message
|
|
5089
|
+
errorMessage: row.error_message,
|
|
5090
|
+
errorType: row.error_type ?? "UNCLASSIFIED"
|
|
5015
5091
|
};
|
|
5016
5092
|
}
|
|
5017
5093
|
function deadLetterRecordToRow(record) {
|
|
@@ -5025,7 +5101,8 @@ function deadLetterRecordToRow(record) {
|
|
|
5025
5101
|
branch: record.branch,
|
|
5026
5102
|
operations: JSON.stringify(record.operations),
|
|
5027
5103
|
error_source: record.errorSource,
|
|
5028
|
-
error_message: record.errorMessage
|
|
5104
|
+
error_message: record.errorMessage,
|
|
5105
|
+
error_type: record.errorType
|
|
5029
5106
|
};
|
|
5030
5107
|
}
|
|
5031
5108
|
/**
|
|
@@ -5082,9 +5159,11 @@ var KyselySyncDeadLetterStorage = class {
|
|
|
5082
5159
|
}
|
|
5083
5160
|
async listQuarantinedDocumentIds(signal) {
|
|
5084
5161
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
5085
|
-
const rows = await this.db.selectFrom("sync_dead_letters").select("document_id").distinct().execute();
|
|
5162
|
+
const rows = await this.db.selectFrom("sync_dead_letters").select(["document_id", "error_type"]).distinct().execute();
|
|
5086
5163
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
5087
|
-
|
|
5164
|
+
const quarantined = /* @__PURE__ */ new Set();
|
|
5165
|
+
for (const row of rows) if (quarantinesDocument(row.error_type ?? "UNCLASSIFIED")) quarantined.add(row.document_id);
|
|
5166
|
+
return [...quarantined];
|
|
5088
5167
|
}
|
|
5089
5168
|
};
|
|
5090
5169
|
//#endregion
|
|
@@ -5757,7 +5836,8 @@ var SyncManager = class {
|
|
|
5757
5836
|
remote.channel.deadLetter.onAdded((syncOps) => {
|
|
5758
5837
|
for (const syncOp of syncOps) {
|
|
5759
5838
|
this.logger.error("Dead letter (@remote, @documentId, @jobId, @error, @dependencies)", remote.meta.name, syncOp.documentId, syncOp.jobId, syncOp.error?.message ?? "unknown", syncOp.jobDependencies);
|
|
5760
|
-
|
|
5839
|
+
const errorType = syncOperationErrorType(syncOp.error);
|
|
5840
|
+
if (quarantinesDocument(errorType)) this.quarantinedDocumentIds.add(syncOp.documentId);
|
|
5761
5841
|
const record = {
|
|
5762
5842
|
id: syncOp.id,
|
|
5763
5843
|
jobId: syncOp.jobId,
|
|
@@ -5768,7 +5848,8 @@ var SyncManager = class {
|
|
|
5768
5848
|
branch: syncOp.branch,
|
|
5769
5849
|
operations: syncOp.operations,
|
|
5770
5850
|
errorSource: syncOp.error?.source ?? ChannelErrorSource.None,
|
|
5771
|
-
errorMessage: syncOp.error?.error.message ?? "unknown"
|
|
5851
|
+
errorMessage: syncOp.error?.error.message ?? "unknown",
|
|
5852
|
+
errorType
|
|
5772
5853
|
};
|
|
5773
5854
|
this.deadLetterStorage.add(record).catch((err) => {
|
|
5774
5855
|
this.logger.error("Failed to persist dead letter (@id, @error)", record.id, err instanceof Error ? err.message : String(err));
|
|
@@ -5778,7 +5859,8 @@ var SyncManager = class {
|
|
|
5778
5859
|
jobId: record.jobId,
|
|
5779
5860
|
remoteName: record.remoteName,
|
|
5780
5861
|
documentId: record.documentId,
|
|
5781
|
-
errorSource: record.errorSource
|
|
5862
|
+
errorSource: record.errorSource,
|
|
5863
|
+
errorType: record.errorType
|
|
5782
5864
|
}).catch(() => {});
|
|
5783
5865
|
}
|
|
5784
5866
|
const items = remote.channel.deadLetter.items;
|
|
@@ -5805,7 +5887,7 @@ var SyncManager = class {
|
|
|
5805
5887
|
const syncOps = [];
|
|
5806
5888
|
for (const record of records) {
|
|
5807
5889
|
const syncOp = new SyncOperation(record.id, record.jobId, record.jobDependencies, record.remoteName, record.documentId, record.scopes, record.branch, record.operations);
|
|
5808
|
-
syncOp.failed(new ChannelError(record.errorSource, new Error(record.errorMessage)));
|
|
5890
|
+
syncOp.failed(new ChannelError(record.errorSource, new Error(record.errorMessage), record.errorType));
|
|
5809
5891
|
syncOps.push(syncOp);
|
|
5810
5892
|
}
|
|
5811
5893
|
remote.channel.deadLetter.add(...syncOps);
|
|
@@ -5886,8 +5968,7 @@ var SyncManager = class {
|
|
|
5886
5968
|
if (completedJobInfo.status === JobStatus.FAILED) {
|
|
5887
5969
|
const errorMessage = completedJobInfo.error?.message || "Unknown error";
|
|
5888
5970
|
this.logger.error("Failed to apply operations from inbox (@remote, @documentId, @jobId, @error)", remote.meta.name, syncOp.documentId, completedJobInfo.id, errorMessage);
|
|
5889
|
-
|
|
5890
|
-
syncOp.failed(error);
|
|
5971
|
+
syncOp.failed(this.inboxFailure(completedJobInfo.error));
|
|
5891
5972
|
remote.channel.deadLetter.add(syncOp);
|
|
5892
5973
|
} else syncOp.executed();
|
|
5893
5974
|
remote.channel.inbox.remove(syncOp);
|
|
@@ -5964,14 +6045,26 @@ var SyncManager = class {
|
|
|
5964
6045
|
}
|
|
5965
6046
|
if (this.isShutdown) return;
|
|
5966
6047
|
if (completedJobInfo.status === JobStatus.FAILED) {
|
|
5967
|
-
|
|
5968
|
-
const channelError = new ChannelError(ChannelErrorSource.Inbox, /* @__PURE__ */ new Error(`Failed to apply operations: ${errorMessage}`));
|
|
5969
|
-
syncOp.failed(channelError);
|
|
6048
|
+
syncOp.failed(this.inboxFailure(completedJobInfo.error));
|
|
5970
6049
|
remote.channel.deadLetter.add(syncOp);
|
|
5971
6050
|
} else syncOp.executed();
|
|
5972
6051
|
remote.channel.inbox.remove(syncOp);
|
|
5973
6052
|
}
|
|
5974
6053
|
}
|
|
6054
|
+
/**
|
|
6055
|
+
* The dead letter for a load job the executor failed.
|
|
6056
|
+
*
|
|
6057
|
+
* The classification is passed explicitly because it cannot be recovered
|
|
6058
|
+
* downstream: the wrapper carries the failure's message, not the failure, so
|
|
6059
|
+
* deriving it from the wrapper's own name would classify every one of these
|
|
6060
|
+
* as unclassified and quarantine the document. A held auth operation must
|
|
6061
|
+
* keep syncing, because reconciling the two policies needs the traffic a
|
|
6062
|
+
* quarantine would stop.
|
|
6063
|
+
*/
|
|
6064
|
+
inboxFailure(error) {
|
|
6065
|
+
const message = error?.message || "Unknown error";
|
|
6066
|
+
return new ChannelError(ChannelErrorSource.Inbox, /* @__PURE__ */ new Error(`Failed to apply operations: ${message}`), classifyJobFailure(error?.name ?? "Error"));
|
|
6067
|
+
}
|
|
5975
6068
|
async updateOutbox(remote, ackOrdinal, mode = OutboxMode.Backfill, signal) {
|
|
5976
6069
|
const composedSignal = signal ? AbortSignal.any([signal, this.abortController.signal]) : this.abortController.signal;
|
|
5977
6070
|
let maxOrdinal = ackOrdinal;
|
|
@@ -6930,7 +7023,7 @@ var ReactorBuilder = class {
|
|
|
6930
7023
|
await executorManager.start(executorStartCount);
|
|
6931
7024
|
const readModelInstances = Array.from(new Set([...this.readModels]));
|
|
6932
7025
|
const documentViewConsistencyTracker = new ConsistencyTracker();
|
|
6933
|
-
const documentView = new KyselyDocumentView(database, operationStore, operationIndex, writeCache, documentViewConsistencyTracker);
|
|
7026
|
+
const documentView = new KyselyDocumentView(database, operationStore, operationIndex, writeCache, documentViewConsistencyTracker, this.executorConfig.featureFlags?.documentDecisions ?? false);
|
|
6934
7027
|
try {
|
|
6935
7028
|
await documentView.init();
|
|
6936
7029
|
} catch (error) {
|
|
@@ -7069,7 +7162,7 @@ var ReactorBuilder = class {
|
|
|
7069
7162
|
const [{ WorkerHandle }, { createThreadTransport }, { workerEntryPath }] = await Promise.all([
|
|
7070
7163
|
import("./worker-handle-CrERzl8s.js"),
|
|
7071
7164
|
import("./transport-ByGviWdZ.js"),
|
|
7072
|
-
import("./worker-
|
|
7165
|
+
import("./worker-jEJW6_j7.js").then((n) => n.n)
|
|
7073
7166
|
]);
|
|
7074
7167
|
const poolConfig = {
|
|
7075
7168
|
enabled: true,
|
|
@@ -7331,6 +7424,38 @@ function driveIdFromUrl(url) {
|
|
|
7331
7424
|
return url.split("/").pop() ?? "";
|
|
7332
7425
|
}
|
|
7333
7426
|
//#endregion
|
|
7427
|
+
//#region src/decision/stream-order.ts
|
|
7428
|
+
/**
|
|
7429
|
+
* The first pair of effective operations whose stored order contradicts their
|
|
7430
|
+
* timestamps, or undefined when the stream is in position order.
|
|
7431
|
+
*
|
|
7432
|
+
* Such a stream cannot be walked, and the auth stream is never reshuffled once
|
|
7433
|
+
* the monotonic rule is on, so run this before enabling enforcement on a fleet.
|
|
7434
|
+
*
|
|
7435
|
+
* `requireStrict` additionally rejects a tie, which is what the auth stream's
|
|
7436
|
+
* monotonic rule requires and what the walk alone does not care about.
|
|
7437
|
+
*/
|
|
7438
|
+
function firstOutOfOrderPair(operations, options) {
|
|
7439
|
+
const requireStrict = options?.requireStrict ?? false;
|
|
7440
|
+
const effective = garbageCollect(sortOperations([...operations]));
|
|
7441
|
+
for (let i = 1; i < effective.length; i++) {
|
|
7442
|
+
const previous = effective[i - 1];
|
|
7443
|
+
const current = effective[i];
|
|
7444
|
+
const previousAt = Date.parse(previous.timestampUtcMs);
|
|
7445
|
+
const currentAt = Date.parse(current.timestampUtcMs);
|
|
7446
|
+
if (currentAt < previousAt) return {
|
|
7447
|
+
previous,
|
|
7448
|
+
current,
|
|
7449
|
+
kind: "descending"
|
|
7450
|
+
};
|
|
7451
|
+
if (requireStrict && currentAt === previousAt) return {
|
|
7452
|
+
previous,
|
|
7453
|
+
current,
|
|
7454
|
+
kind: "tied"
|
|
7455
|
+
};
|
|
7456
|
+
}
|
|
7457
|
+
}
|
|
7458
|
+
//#endregion
|
|
7334
7459
|
//#region src/read-models/interfaces.ts
|
|
7335
7460
|
function supportsLiveReadModelRegistration(coordinator) {
|
|
7336
7461
|
return "addReadModel" in coordinator && typeof coordinator.addReadModel === "function";
|
|
@@ -7361,6 +7486,7 @@ var DocumentIntegrityService = class {
|
|
|
7361
7486
|
async validateDocument(documentId, branch = "main", signal) {
|
|
7362
7487
|
const keyframeIssues = [];
|
|
7363
7488
|
const snapshotIssues = [];
|
|
7489
|
+
const streamOrderIssues = await this.findStreamOrderIssues(documentId, branch, signal);
|
|
7364
7490
|
const replayCache = new KyselyWriteCache(passthroughKeyframeStore, this.operationStore, this.documentModelRegistry, {
|
|
7365
7491
|
maxDocuments: 1,
|
|
7366
7492
|
ringBufferSize: 1,
|
|
@@ -7387,9 +7513,10 @@ var DocumentIntegrityService = class {
|
|
|
7387
7513
|
} catch {
|
|
7388
7514
|
return {
|
|
7389
7515
|
documentId,
|
|
7390
|
-
isConsistent: keyframeIssues.length === 0,
|
|
7516
|
+
isConsistent: keyframeIssues.length === 0 && streamOrderIssues.length === 0,
|
|
7391
7517
|
keyframeIssues,
|
|
7392
|
-
snapshotIssues
|
|
7518
|
+
snapshotIssues,
|
|
7519
|
+
streamOrderIssues
|
|
7393
7520
|
};
|
|
7394
7521
|
}
|
|
7395
7522
|
const revisions = await this.operationStore.getRevisions(documentId, branch, signal);
|
|
@@ -7415,9 +7542,10 @@ var DocumentIntegrityService = class {
|
|
|
7415
7542
|
}
|
|
7416
7543
|
return {
|
|
7417
7544
|
documentId,
|
|
7418
|
-
isConsistent: keyframeIssues.length === 0 && snapshotIssues.length === 0,
|
|
7545
|
+
isConsistent: keyframeIssues.length === 0 && snapshotIssues.length === 0 && streamOrderIssues.length === 0,
|
|
7419
7546
|
keyframeIssues,
|
|
7420
|
-
snapshotIssues
|
|
7547
|
+
snapshotIssues,
|
|
7548
|
+
streamOrderIssues
|
|
7421
7549
|
};
|
|
7422
7550
|
}
|
|
7423
7551
|
async rebuildKeyframes(documentId, branch = "main", signal) {
|
|
@@ -7439,12 +7567,26 @@ var DocumentIntegrityService = class {
|
|
|
7439
7567
|
scopesInvalidated: scopes.length
|
|
7440
7568
|
};
|
|
7441
7569
|
}
|
|
7570
|
+
async findStreamOrderIssues(documentId, branch, signal) {
|
|
7571
|
+
const scopes = await this.discoverScopes(documentId, branch, signal);
|
|
7572
|
+
const issues = [];
|
|
7573
|
+
for (const scope of scopes) {
|
|
7574
|
+
throwIfAborted(signal);
|
|
7575
|
+
const pair = firstOutOfOrderPair((await this.operationStore.getSince(documentId, scope, branch, -1, void 0, void 0, signal)).results, { requireStrict: scope === "auth" });
|
|
7576
|
+
if (pair !== void 0) issues.push({
|
|
7577
|
+
scope,
|
|
7578
|
+
branch,
|
|
7579
|
+
...pair
|
|
7580
|
+
});
|
|
7581
|
+
}
|
|
7582
|
+
return issues;
|
|
7583
|
+
}
|
|
7442
7584
|
async discoverScopes(documentId, branch, signal) {
|
|
7443
7585
|
const revisions = await this.operationStore.getRevisions(documentId, branch, signal);
|
|
7444
7586
|
return Object.keys(revisions.revision);
|
|
7445
7587
|
}
|
|
7446
7588
|
};
|
|
7447
7589
|
//#endregion
|
|
7448
|
-
export { APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RetryAccounting, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, batchOperationsByDocument, buildDecisionModel, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, removeRelationshipAction, runMigrations, sanitizeArg, supportsLiveReadModelRegistration, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
7590
|
+
export { APPEND_CONDITION_FAILED_PREFIX, AppendConditionFailedError, BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DRIVE_AUTH_ERROR_MESSAGES, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DriveCollectionId, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RetryAccounting, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, authDecisionModel, batchOperationsByDocument, buildDecisionModel, classifyJobFailure, consolidateSyncOperations, createDocumentAction, createForwardingLogger, createMutableShutdownStatus, createRelationalDb, decideAtHead, deleteDocumentAction, documentActions, documentDecisionModel, driveIdFromUrl, envelopesToSyncOperations, errorToInfo, firstOutOfOrderPair, getMigrationStatus, instrumentPgPool, isDriveAuthError, makeConsistencyKey, parseDriveUrl, parsePagingOptions, quarantinesDocument, removeRelationshipAction, runMigrations, sanitizeArg, selectDecisionModel, supportsLiveReadModelRegistration, syncOperationErrorType, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction, workerEntryPath };
|
|
7449
7591
|
|
|
7450
7592
|
//# sourceMappingURL=index.js.map
|