@peerbit/document 15.0.14 → 15.0.16
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/README.md +25 -0
- package/dist/src/callback-detachment.d.ts +5 -0
- package/dist/src/callback-detachment.d.ts.map +1 -1
- package/dist/src/callback-detachment.js +377 -6
- package/dist/src/callback-detachment.js.map +1 -1
- package/dist/src/domain.d.ts.map +1 -1
- package/dist/src/domain.js +2 -2
- package/dist/src/domain.js.map +1 -1
- package/dist/src/program.d.ts +7 -0
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +312 -145
- package/dist/src/program.js.map +1 -1
- package/dist/src/search.d.ts +2 -0
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +36 -6
- package/dist/src/search.js.map +1 -1
- package/dist/src/transform.d.ts +2 -0
- package/dist/src/transform.d.ts.map +1 -1
- package/dist/src/transform.js +4 -0
- package/dist/src/transform.js.map +1 -1
- package/package.json +15 -15
- package/src/callback-detachment.ts +546 -6
- package/src/domain.ts +2 -3
- package/src/program.ts +682 -358
- package/src/search.ts +49 -5
- package/src/transform.ts +7 -0
package/dist/src/program.js
CHANGED
|
@@ -35,16 +35,16 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
35
35
|
import { BorshError, deserialize, field, serialize, variant, } from "@dao-xyz/borsh";
|
|
36
36
|
import { AccessError } from "@peerbit/crypto";
|
|
37
37
|
import { Context, NotFoundError, } from "@peerbit/document-interface";
|
|
38
|
-
import { extractDocumentFieldSimple, initializeDocumentRust, planDocumentContext, planDocumentContextBatch, tryPlanDocumentContext, tryPlanDocumentContextBatch, } from "./native-rust.js";
|
|
39
38
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
40
39
|
import { Entry, EntryType, LamportClock, ShallowEntry, ShallowMeta, Timestamp, entryV0PlainPayloadDataFromStorage, } from "@peerbit/log";
|
|
41
40
|
import { logger as loggerFn } from "@peerbit/logger";
|
|
42
41
|
import { Program } from "@peerbit/program";
|
|
43
|
-
import { SharedLog, } from "@peerbit/shared-log";
|
|
44
|
-
import { detachCanPerformCallbackProperties, detachEntryPayloadForCallback, } from "./callback-detachment.js";
|
|
42
|
+
import { PersistedDeliveryError, SharedLog, } from "@peerbit/shared-log";
|
|
43
|
+
import { detachCanPerformCallbackProperties, detachEntryForCallback, detachEntryPayloadForCallback, } from "./callback-detachment.js";
|
|
45
44
|
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
45
|
+
import { extractDocumentFieldSimple, initializeDocumentRust, planDocumentContext, planDocumentContextBatch, tryPlanDocumentContext, tryPlanDocumentContextBatch, } from "./native-rust.js";
|
|
46
46
|
import { BORSH_ENCODING_OPERATION, DeleteOperation, PutOperation, PutWithKeyOperation, coerceDeleteOperation, isDeleteOperation, isPutOperation, } from "./operation.js";
|
|
47
|
-
import {
|
|
47
|
+
import { canPerformPolicyDeleteFieldPaths, canPerformPolicyNeedsDeleteValue, canPerformPolicyNeedsPreviousEntries, canPerformPolicyPutNeedsEntryPublicKeys, canPerformPolicySignedByFieldPaths, createCanPerformDeletePolicyEvaluator, createCanPerformPolicyEvaluator, getCanPerformPolicyDescriptor, } from "./policy.js";
|
|
48
48
|
import { isResultIndexedValue } from "./result-shape.js";
|
|
49
49
|
import { DocumentIndex, INDEX_CONTEXT_SHAPE, coerceWithContext, coerceWithIndexed, coerceWithLazyIndexed, encodeContextSuffix as encodeDocumentContextSuffix, } from "./search.js";
|
|
50
50
|
import { getDocumentTransformDescriptor, } from "./transform.js";
|
|
@@ -111,6 +111,54 @@ const encodePutOperationPayload = (data) => {
|
|
|
111
111
|
return encoded;
|
|
112
112
|
};
|
|
113
113
|
const toContextBigInt = (value) => typeof value === "bigint" ? value : BigInt(value);
|
|
114
|
+
const hasPersistedDelivery = (options) => typeof options?.delivery === "object" &&
|
|
115
|
+
options.delivery.reliability === "persisted";
|
|
116
|
+
const withoutPersistedDelivery = (options) => {
|
|
117
|
+
if (!hasPersistedDelivery(options)) {
|
|
118
|
+
return options;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
...options,
|
|
122
|
+
target: "none",
|
|
123
|
+
delivery: false,
|
|
124
|
+
replicate: false,
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const runAfterDocumentCommit = (options, committedHashes, fn) => {
|
|
128
|
+
if (!hasPersistedDelivery(options))
|
|
129
|
+
return fn();
|
|
130
|
+
const resolvedHashes = typeof committedHashes === "function" ? committedHashes() : committedHashes;
|
|
131
|
+
const hashes = typeof resolvedHashes === "string" ? [resolvedHashes] : resolvedHashes;
|
|
132
|
+
try {
|
|
133
|
+
const result = fn();
|
|
134
|
+
if (isPromiseLike(result)) {
|
|
135
|
+
return result.catch((error) => {
|
|
136
|
+
throw new PersistedDeliveryError(error, hashes);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new PersistedDeliveryError(error, hashes);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const runWithTrustedLocalCommitEvidence = (options, evidence, fn) => {
|
|
146
|
+
if (!evidence || !hasPersistedDelivery(options))
|
|
147
|
+
return fn();
|
|
148
|
+
const classify = (error) => {
|
|
149
|
+
if (evidence.committedHashes.size > 0) {
|
|
150
|
+
throw new PersistedDeliveryError(error, evidence.committedHashes);
|
|
151
|
+
}
|
|
152
|
+
throw error;
|
|
153
|
+
};
|
|
154
|
+
try {
|
|
155
|
+
const result = fn();
|
|
156
|
+
return isPromiseLike(result) ? result.catch(classify) : result;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return classify(error);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
114
162
|
const NATIVE_LOCAL_PUT_OPTIONS = Object.freeze({
|
|
115
163
|
replicate: false,
|
|
116
164
|
target: "none",
|
|
@@ -136,6 +184,7 @@ const cachedNativeLocalPutOptions = (options) => {
|
|
|
136
184
|
}
|
|
137
185
|
return options.unique === true ? NATIVE_LOCAL_UNIQUE_PUT_OPTIONS : undefined;
|
|
138
186
|
};
|
|
187
|
+
const persistedDeliveryAlreadySettled = new WeakSet();
|
|
139
188
|
class CompatDocumentBackend {
|
|
140
189
|
putImpl;
|
|
141
190
|
putManyImpl;
|
|
@@ -186,15 +235,7 @@ class NativeDocumentBackend {
|
|
|
186
235
|
useNativeExistingDocumentContext,
|
|
187
236
|
requiredPreviousSignerPublicKey,
|
|
188
237
|
existing,
|
|
189
|
-
}), (documentAppendCommit) =>
|
|
190
|
-
this.context.keepEntry(documentAppendCommit.append.hash);
|
|
191
|
-
return {
|
|
192
|
-
get entry() {
|
|
193
|
-
return documentAppendCommit.entry;
|
|
194
|
-
},
|
|
195
|
-
removed: documentAppendCommit.removed,
|
|
196
|
-
};
|
|
197
|
-
}));
|
|
238
|
+
}), (documentAppendCommit) => this.context.finishPreparedPlainPutCommit(documentAppendCommit, options));
|
|
198
239
|
};
|
|
199
240
|
const assertPolicyAndCommit = (existingContext, previousSignerPublicKey) => {
|
|
200
241
|
const existingHead = this.context.getIndexedContextHead(existingContext);
|
|
@@ -239,6 +280,9 @@ class NativeDocumentBackend {
|
|
|
239
280
|
}
|
|
240
281
|
const prepared = docs.map((doc) => this.context.preparePlainPut(doc));
|
|
241
282
|
if (this.context.hasDuplicatePreparedPutKeys(prepared)) {
|
|
283
|
+
if (hasPersistedDelivery(options)) {
|
|
284
|
+
throw this.context.nativeModeError("requires distinct document keys for persisted putMany");
|
|
285
|
+
}
|
|
242
286
|
const results = [];
|
|
243
287
|
for (const doc of docs) {
|
|
244
288
|
results.push(await this.put(doc, putOptions));
|
|
@@ -318,17 +362,7 @@ class NativeDocumentBackend {
|
|
|
318
362
|
if (!documentAppendCommit) {
|
|
319
363
|
throw this.context.nativeModeError("requires native batched payload append support");
|
|
320
364
|
}
|
|
321
|
-
return
|
|
322
|
-
for (const commit of documentAppendCommit.commits) {
|
|
323
|
-
this.context.keepEntry(commit.append.hash);
|
|
324
|
-
}
|
|
325
|
-
return {
|
|
326
|
-
get entries() {
|
|
327
|
-
return documentAppendCommit.entries;
|
|
328
|
-
},
|
|
329
|
-
removed: documentAppendCommit.removed,
|
|
330
|
-
};
|
|
331
|
-
});
|
|
365
|
+
return this.context.finishPreparedPlainPutManyCommit(documentAppendCommit, options);
|
|
332
366
|
});
|
|
333
367
|
}
|
|
334
368
|
del(id, options) {
|
|
@@ -337,6 +371,10 @@ class NativeDocumentBackend {
|
|
|
337
371
|
}
|
|
338
372
|
}
|
|
339
373
|
const nativeDocumentContextFactsAsContext = (facts) => facts;
|
|
374
|
+
// Keep the public putMany result shape unchanged while carrying the native
|
|
375
|
+
// commit/coordinate facts to the internal persisted-delivery seam. The result
|
|
376
|
+
// remains the lifetime owner of the lazy full-entry materializer.
|
|
377
|
+
const persistedDocumentAppendDelivery = new WeakMap();
|
|
340
378
|
const asTrustedDocumentSharedLog = (log) => log;
|
|
341
379
|
const documentIndexStoreKey = (id) => {
|
|
342
380
|
const key = indexerTypes.toIdeable(id);
|
|
@@ -430,11 +468,7 @@ let Documents = (() => {
|
|
|
430
468
|
const boundMethods = new Map();
|
|
431
469
|
const detachedFromEntry = (entry) => {
|
|
432
470
|
const fromEntry = Reflect.get(domain, "fromEntry", domain);
|
|
433
|
-
return Reflect.apply(fromEntry, domain, [
|
|
434
|
-
entry instanceof Entry
|
|
435
|
-
? detachEntryPayloadForCallback(entry)
|
|
436
|
-
: entry,
|
|
437
|
-
]);
|
|
471
|
+
return Reflect.apply(fromEntry, domain, [detachEntryForCallback(entry)]);
|
|
438
472
|
};
|
|
439
473
|
const facade = Object.create(Object.getPrototypeOf(domain));
|
|
440
474
|
let callbackDomain;
|
|
@@ -490,6 +524,22 @@ let Documents = (() => {
|
|
|
490
524
|
});
|
|
491
525
|
return callbackDomain;
|
|
492
526
|
}
|
|
527
|
+
detachTrimEntryCallback(option) {
|
|
528
|
+
const filter = option?.filter;
|
|
529
|
+
if (!option || !filter?.canTrim) {
|
|
530
|
+
return option;
|
|
531
|
+
}
|
|
532
|
+
const canTrim = filter.canTrim;
|
|
533
|
+
return {
|
|
534
|
+
...option,
|
|
535
|
+
filter: {
|
|
536
|
+
...filter,
|
|
537
|
+
canTrim: function (entry) {
|
|
538
|
+
return Reflect.apply(canTrim, this, [detachEntryForCallback(entry)]);
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
};
|
|
542
|
+
}
|
|
493
543
|
createNativeDocumentBackendContext() {
|
|
494
544
|
return {
|
|
495
545
|
assertPlainPutSupported: (doc, options) => {
|
|
@@ -519,12 +569,9 @@ let Documents = (() => {
|
|
|
519
569
|
},
|
|
520
570
|
commitNativeDocumentAppend: (input) => this.commitNativeDocumentAppend(input),
|
|
521
571
|
commitNativeDocumentAppendMany: (input) => this.commitNativeDocumentAppendMany(input),
|
|
522
|
-
|
|
523
|
-
|
|
572
|
+
finishPreparedPlainPutCommit: (commit, options) => this.finishPreparedPlainPutCommit(commit, options),
|
|
573
|
+
finishPreparedPlainPutManyCommit: (commit, options) => this.finishPreparedPlainPutManyCommit(commit, options),
|
|
524
574
|
deleteDocument: (id, options) => this.delNativeDocumentBackend(id, options),
|
|
525
|
-
keepEntry: (hash) => {
|
|
526
|
-
this.keepCache?.add(hash);
|
|
527
|
-
},
|
|
528
575
|
nativeModeError: (message) => this.nativeModeError(message),
|
|
529
576
|
};
|
|
530
577
|
}
|
|
@@ -715,10 +762,14 @@ let Documents = (() => {
|
|
|
715
762
|
if (options?.replicate === true) {
|
|
716
763
|
unsupported.push("replicated put");
|
|
717
764
|
}
|
|
718
|
-
if (options?.target &&
|
|
765
|
+
if (options?.target &&
|
|
766
|
+
options.target !== "none" &&
|
|
767
|
+
!(hasPersistedDelivery(options) && options.target === "replicators")) {
|
|
719
768
|
unsupported.push("non-local target");
|
|
720
769
|
}
|
|
721
|
-
if (options?.delivery !== undefined &&
|
|
770
|
+
if (options?.delivery !== undefined &&
|
|
771
|
+
options.delivery !== false &&
|
|
772
|
+
!hasPersistedDelivery(options)) {
|
|
722
773
|
unsupported.push("delivery");
|
|
723
774
|
}
|
|
724
775
|
if (options?.checkRemote) {
|
|
@@ -793,7 +844,8 @@ let Documents = (() => {
|
|
|
793
844
|
return this.nativeFieldValueMatchesPublicKey(value, localPublicKey);
|
|
794
845
|
}
|
|
795
846
|
nativeFieldValueMatchesPublicKey(value, publicKey) {
|
|
796
|
-
const localRawPublicKey = publicKey
|
|
847
|
+
const localRawPublicKey = publicKey
|
|
848
|
+
.publicKey;
|
|
797
849
|
return (value instanceof Uint8Array &&
|
|
798
850
|
(bytesEqual(value, publicKey.bytes) ||
|
|
799
851
|
(localRawPublicKey ? bytesEqual(value, localRawPublicKey) : false)));
|
|
@@ -949,6 +1001,9 @@ let Documents = (() => {
|
|
|
949
1001
|
return;
|
|
950
1002
|
}
|
|
951
1003
|
const unsupported = this.unsupportedNativePutOptions(options);
|
|
1004
|
+
if (options && hasPersistedDelivery(options)) {
|
|
1005
|
+
unsupported.push("delivery");
|
|
1006
|
+
}
|
|
952
1007
|
if (options?.unique !== undefined) {
|
|
953
1008
|
unsupported.push("unique delete");
|
|
954
1009
|
}
|
|
@@ -992,6 +1047,9 @@ let Documents = (() => {
|
|
|
992
1047
|
if (!this.isNativeMode()) {
|
|
993
1048
|
return options;
|
|
994
1049
|
}
|
|
1050
|
+
if (hasPersistedDelivery(options)) {
|
|
1051
|
+
return options;
|
|
1052
|
+
}
|
|
995
1053
|
if (options?.replicate === false && options.target === "none") {
|
|
996
1054
|
return options;
|
|
997
1055
|
}
|
|
@@ -1320,8 +1378,7 @@ let Documents = (() => {
|
|
|
1320
1378
|
this._documentInternalChangeListenerCount = Math.max(0, this._documentChangeListenerCount - changeListenersBeforeIndexOpen);
|
|
1321
1379
|
this._nativeDocumentFieldExtractionPlans ??= new Map();
|
|
1322
1380
|
this._nativeDocumentFieldExtractionPlans.clear();
|
|
1323
|
-
this._nativeDocumentIdExtractionPlan =
|
|
1324
|
-
asTrustedDocumentIndex(this._index).getNativeDocumentFieldExtractionPlan(idProperty);
|
|
1381
|
+
this._nativeDocumentIdExtractionPlan = asTrustedDocumentIndex(this._index).getNativeDocumentFieldExtractionPlan(idProperty);
|
|
1325
1382
|
// B12: the historical document->log compatibility mapping (6 -> log v8,
|
|
1326
1383
|
// 7 -> log v9) is retired; the rejection at the top of open() fires for
|
|
1327
1384
|
// any defined value before this point.
|
|
@@ -1371,11 +1428,7 @@ let Documents = (() => {
|
|
|
1371
1428
|
const keep = options?.keep;
|
|
1372
1429
|
keepFunction = keep
|
|
1373
1430
|
? function (entry) {
|
|
1374
|
-
return Reflect.apply(keep, this, [
|
|
1375
|
-
entry instanceof Entry
|
|
1376
|
-
? detachEntryPayloadForCallback(entry)
|
|
1377
|
-
: entry,
|
|
1378
|
-
]);
|
|
1431
|
+
return Reflect.apply(keep, this, [detachEntryForCallback(entry)]);
|
|
1379
1432
|
}
|
|
1380
1433
|
: undefined;
|
|
1381
1434
|
}
|
|
@@ -1384,7 +1437,7 @@ let Documents = (() => {
|
|
|
1384
1437
|
canReplicate: options?.canReplicate,
|
|
1385
1438
|
canAppend: this.canAppend.bind(this),
|
|
1386
1439
|
onChange: this.handleChanges.bind(this),
|
|
1387
|
-
trim: options?.log?.trim,
|
|
1440
|
+
trim: this.detachTrimEntryCallback(options?.log?.trim),
|
|
1388
1441
|
appendDurability: options?.appendDurability,
|
|
1389
1442
|
nativeBackbone: options?.nativeBackbone,
|
|
1390
1443
|
nativeGraph: options?.nativeGraph,
|
|
@@ -1650,7 +1703,8 @@ let Documents = (() => {
|
|
|
1650
1703
|
: reference.document);
|
|
1651
1704
|
}
|
|
1652
1705
|
else {
|
|
1653
|
-
keyValue =
|
|
1706
|
+
keyValue =
|
|
1707
|
+
await this.getNativeDocumentIdFromPutOperation(putOperation);
|
|
1654
1708
|
if (keyValue == null) {
|
|
1655
1709
|
if (this.isNativeMode()) {
|
|
1656
1710
|
return false;
|
|
@@ -1941,7 +1995,28 @@ let Documents = (() => {
|
|
|
1941
1995
|
};
|
|
1942
1996
|
}
|
|
1943
1997
|
async put(doc, options) {
|
|
1944
|
-
|
|
1998
|
+
if (hasPersistedDelivery(options)) {
|
|
1999
|
+
asTrustedDocumentSharedLog(this.log).assertPersistedDeliveryOptions(options);
|
|
2000
|
+
}
|
|
2001
|
+
const result = await this._documentBackend.put(doc, options);
|
|
2002
|
+
if (!hasPersistedDelivery(options) ||
|
|
2003
|
+
persistedDeliveryAlreadySettled.has(result)) {
|
|
2004
|
+
return result;
|
|
2005
|
+
}
|
|
2006
|
+
const entry = result.entry;
|
|
2007
|
+
await this.deliverPersistedDocumentEntries([entry], options);
|
|
2008
|
+
return {
|
|
2009
|
+
get entry() {
|
|
2010
|
+
return entry;
|
|
2011
|
+
},
|
|
2012
|
+
removed: result.removed,
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
deliverPersistedDocumentEntries(entries, options) {
|
|
2016
|
+
return asTrustedDocumentSharedLog(this.log).deliverPersistedEntries(entries, options);
|
|
2017
|
+
}
|
|
2018
|
+
deliverPersistedDocumentAppendCommits(delivery, options) {
|
|
2019
|
+
return asTrustedDocumentSharedLog(this.log).deliverPersistedAppendCommits(delivery.appendCommits, delivery.materializeEntries, options);
|
|
1945
2020
|
}
|
|
1946
2021
|
async putCompatDocumentBackend(doc, options) {
|
|
1947
2022
|
const putOptions = this.normalizeNativeModePutOptions(options);
|
|
@@ -1971,6 +2046,7 @@ let Documents = (() => {
|
|
|
1971
2046
|
const operation = "operation" in prepared
|
|
1972
2047
|
? prepared.operation
|
|
1973
2048
|
: new PutOperation({ data: prepared.encodedDocument });
|
|
2049
|
+
const persistedDelivery = hasPersistedDelivery(putOptions);
|
|
1974
2050
|
const appended = await this.log.append(operation, {
|
|
1975
2051
|
...putOptions,
|
|
1976
2052
|
meta: {
|
|
@@ -1983,32 +2059,73 @@ let Documents = (() => {
|
|
|
1983
2059
|
operation,
|
|
1984
2060
|
});
|
|
1985
2061
|
},
|
|
1986
|
-
onChange:
|
|
1987
|
-
|
|
2062
|
+
onChange: persistedDelivery
|
|
2063
|
+
? (change) => runAfterDocumentCommit(putOptions, () => change.added.map(({ entry }) => entry.hash), () => mapMaybePromise(this.handleChanges(change, {
|
|
1988
2064
|
document: prepared.document,
|
|
1989
2065
|
operation,
|
|
1990
2066
|
key: prepared.key,
|
|
1991
2067
|
unique: putOptions?.unique,
|
|
1992
2068
|
existing: existingLocalContext,
|
|
1993
|
-
})
|
|
1994
|
-
|
|
2069
|
+
}), () => {
|
|
2070
|
+
this.keepCache?.add(change.added[0].entry.hash);
|
|
2071
|
+
}))
|
|
2072
|
+
: (change) => this.handleChanges(change, {
|
|
2073
|
+
document: prepared.document,
|
|
2074
|
+
operation,
|
|
2075
|
+
key: prepared.key,
|
|
2076
|
+
unique: putOptions?.unique,
|
|
2077
|
+
existing: existingLocalContext,
|
|
2078
|
+
}),
|
|
1995
2079
|
replicate: putOptions?.replicate,
|
|
1996
2080
|
});
|
|
1997
2081
|
this.keepCache?.add(appended.entry.hash);
|
|
2082
|
+
if (persistedDelivery) {
|
|
2083
|
+
persistedDeliveryAlreadySettled.add(appended);
|
|
2084
|
+
}
|
|
1998
2085
|
return appended;
|
|
1999
2086
|
}
|
|
2000
2087
|
async putMany(docs, options) {
|
|
2001
|
-
|
|
2088
|
+
if (hasPersistedDelivery(options)) {
|
|
2089
|
+
asTrustedDocumentSharedLog(this.log).assertPersistedDeliveryOptions(options);
|
|
2090
|
+
}
|
|
2091
|
+
const result = await this._documentBackend.putMany(docs, options);
|
|
2092
|
+
if (!hasPersistedDelivery(options)) {
|
|
2093
|
+
return result;
|
|
2094
|
+
}
|
|
2095
|
+
const appendDelivery = persistedDocumentAppendDelivery.get(result);
|
|
2096
|
+
if (appendDelivery) {
|
|
2097
|
+
persistedDocumentAppendDelivery.delete(result);
|
|
2098
|
+
await this.deliverPersistedDocumentAppendCommits(appendDelivery, options);
|
|
2099
|
+
let entries;
|
|
2100
|
+
return {
|
|
2101
|
+
get entries() {
|
|
2102
|
+
return (entries ??= result.entries);
|
|
2103
|
+
},
|
|
2104
|
+
removed: result.removed,
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
const entries = result.entries;
|
|
2108
|
+
if (entries.length === 0) {
|
|
2109
|
+
return result;
|
|
2110
|
+
}
|
|
2111
|
+
await this.deliverPersistedDocumentEntries(entries, options);
|
|
2112
|
+
return { entries, removed: result.removed };
|
|
2002
2113
|
}
|
|
2003
2114
|
async putManyCompatDocumentBackend(docs, options) {
|
|
2004
2115
|
if (docs.length === 0) {
|
|
2005
2116
|
return { entries: [], removed: [] };
|
|
2006
2117
|
}
|
|
2007
2118
|
if (!this.canUsePlainPutManyFastPath(docs, options)) {
|
|
2119
|
+
if (hasPersistedDelivery(options)) {
|
|
2120
|
+
throw new Error("persisted putMany requires the independent batched document path");
|
|
2121
|
+
}
|
|
2008
2122
|
return this.putManySequential(docs, options);
|
|
2009
2123
|
}
|
|
2010
2124
|
const prepared = docs.map((doc) => this.preparePlainPut(doc));
|
|
2011
2125
|
if (this.hasDuplicatePreparedPutKeys(prepared)) {
|
|
2126
|
+
if (hasPersistedDelivery(options)) {
|
|
2127
|
+
throw new Error("persisted putMany requires distinct document keys");
|
|
2128
|
+
}
|
|
2012
2129
|
return this.putManySequential(docs, options);
|
|
2013
2130
|
}
|
|
2014
2131
|
const documentAppendCommit = await this.commitNativeDocumentAppendMany({
|
|
@@ -2024,18 +2141,12 @@ let Documents = (() => {
|
|
|
2024
2141
|
options,
|
|
2025
2142
|
});
|
|
2026
2143
|
if (!documentAppendCommit) {
|
|
2144
|
+
if (hasPersistedDelivery(options)) {
|
|
2145
|
+
throw new Error("persisted putMany requires native batched payload append support");
|
|
2146
|
+
}
|
|
2027
2147
|
return this.putManySequential(docs, options);
|
|
2028
2148
|
}
|
|
2029
|
-
await this.
|
|
2030
|
-
for (const commit of documentAppendCommit.commits) {
|
|
2031
|
-
this.keepCache?.add(commit.append.hash);
|
|
2032
|
-
}
|
|
2033
|
-
return {
|
|
2034
|
-
get entries() {
|
|
2035
|
-
return documentAppendCommit.entries;
|
|
2036
|
-
},
|
|
2037
|
-
removed: documentAppendCommit.removed,
|
|
2038
|
-
};
|
|
2149
|
+
return await this.finishPreparedPlainPutManyCommit(documentAppendCommit, options);
|
|
2039
2150
|
}
|
|
2040
2151
|
async putManySequential(docs, options) {
|
|
2041
2152
|
const entries = [];
|
|
@@ -2058,6 +2169,7 @@ let Documents = (() => {
|
|
|
2058
2169
|
return false;
|
|
2059
2170
|
}
|
|
2060
2171
|
canUsePlainPutFastPath(doc, options) {
|
|
2172
|
+
const persistedDelivery = hasPersistedDelivery(options);
|
|
2061
2173
|
return (this._mode !== "compat" &&
|
|
2062
2174
|
this.canPerformAllowsPlainPutFastPath(doc) &&
|
|
2063
2175
|
!this.immutable &&
|
|
@@ -2077,16 +2189,26 @@ let Documents = (() => {
|
|
|
2077
2189
|
!options?.meta?.timestamp &&
|
|
2078
2190
|
!options?.meta?.gidSeed &&
|
|
2079
2191
|
options?.replicate !== true &&
|
|
2080
|
-
(!options?.target ||
|
|
2081
|
-
|
|
2192
|
+
(!options?.target ||
|
|
2193
|
+
options.target === "none" ||
|
|
2194
|
+
(persistedDelivery && options.target === "replicators")) &&
|
|
2195
|
+
(options?.delivery === undefined ||
|
|
2196
|
+
options.delivery === false ||
|
|
2197
|
+
persistedDelivery) &&
|
|
2082
2198
|
!options?.checkRemote &&
|
|
2083
2199
|
options?.replicas === undefined);
|
|
2084
2200
|
}
|
|
2085
2201
|
canUsePlainPutManyFastPath(docs, options) {
|
|
2202
|
+
const persistedDelivery = hasPersistedDelivery(options);
|
|
2086
2203
|
return (options?.unique === true &&
|
|
2087
2204
|
options?.replicate !== true &&
|
|
2088
|
-
options?.target === "none"
|
|
2089
|
-
|
|
2205
|
+
(options?.target === "none" ||
|
|
2206
|
+
(persistedDelivery &&
|
|
2207
|
+
(options.target === undefined ||
|
|
2208
|
+
options.target === "replicators"))) &&
|
|
2209
|
+
(options?.delivery === undefined ||
|
|
2210
|
+
options.delivery === false ||
|
|
2211
|
+
persistedDelivery) &&
|
|
2090
2212
|
docs.every((doc) => this.canUsePlainPutFastPath(doc, options)));
|
|
2091
2213
|
}
|
|
2092
2214
|
async createPlainPutCommitPlan(prepared, existingHead, existingLocalContext, options, assumePlainPutFastPath = false) {
|
|
@@ -2135,41 +2257,43 @@ let Documents = (() => {
|
|
|
2135
2257
|
options,
|
|
2136
2258
|
unique: plan.unique,
|
|
2137
2259
|
existing: plan.existing,
|
|
2138
|
-
}), (documentAppendCommit) =>
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
document: plan.document,
|
|
2145
|
-
operation: documentAppendCommit.operation ??
|
|
2146
|
-
plan.operation ??
|
|
2147
|
-
new PutOperation({ data: plan.encodedDocument }),
|
|
2148
|
-
key: plan.key,
|
|
2149
|
-
unique: plan.unique,
|
|
2150
|
-
existing: plan.existing,
|
|
2151
|
-
})
|
|
2152
|
-
: this.handlePreparedPlainPutCommit(documentAppendCommit);
|
|
2153
|
-
return mapMaybePromise(handled, () => {
|
|
2154
|
-
this.keepCache?.add(documentAppendCommit.append.hash);
|
|
2155
|
-
return {
|
|
2156
|
-
get entry() {
|
|
2157
|
-
return documentAppendCommit.entry;
|
|
2260
|
+
}), (documentAppendCommit) => this.finishPreparedPlainPutCommit(documentAppendCommit, options, () => plan.useGenericChangeHandler
|
|
2261
|
+
? this.handleChanges({
|
|
2262
|
+
added: [
|
|
2263
|
+
{
|
|
2264
|
+
head: true,
|
|
2265
|
+
entry: documentAppendCommit.entry,
|
|
2158
2266
|
},
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2267
|
+
],
|
|
2268
|
+
removed: documentAppendCommit.removed,
|
|
2269
|
+
}, {
|
|
2270
|
+
document: plan.document,
|
|
2271
|
+
operation: documentAppendCommit.operation ??
|
|
2272
|
+
plan.operation ??
|
|
2273
|
+
new PutOperation({ data: plan.encodedDocument }),
|
|
2274
|
+
key: plan.key,
|
|
2275
|
+
unique: plan.unique,
|
|
2276
|
+
existing: plan.existing,
|
|
2277
|
+
})
|
|
2278
|
+
: this.handlePreparedPlainPutCommit(documentAppendCommit)));
|
|
2163
2279
|
}
|
|
2164
2280
|
commitNativeDocumentAppend(input) {
|
|
2281
|
+
if (!hasPersistedDelivery(input.options)) {
|
|
2282
|
+
return this.commitNativeDocumentAppendWithEvidence(input, undefined);
|
|
2283
|
+
}
|
|
2284
|
+
const localCommitEvidence = { committedHashes: new Set() };
|
|
2285
|
+
return runWithTrustedLocalCommitEvidence(input.options, localCommitEvidence, () => this.commitNativeDocumentAppendWithEvidence(input, localCommitEvidence));
|
|
2286
|
+
}
|
|
2287
|
+
commitNativeDocumentAppendWithEvidence(input, localCommitEvidence) {
|
|
2165
2288
|
const trustedLog = asTrustedDocumentSharedLog(this.log);
|
|
2289
|
+
const localAppendOptions = withoutPersistedDelivery(input.options);
|
|
2166
2290
|
const appendOptions = {
|
|
2167
|
-
...
|
|
2291
|
+
...localAppendOptions,
|
|
2168
2292
|
meta: {
|
|
2169
2293
|
next: input.next,
|
|
2170
|
-
...
|
|
2294
|
+
...localAppendOptions?.meta,
|
|
2171
2295
|
},
|
|
2172
|
-
replicate:
|
|
2296
|
+
replicate: localAppendOptions?.replicate,
|
|
2173
2297
|
};
|
|
2174
2298
|
const prepareNativeDocumentIndexWithAppendFacts = this.createNativeBackboneDocumentIndexAppendFactsPreparer(input);
|
|
2175
2299
|
const preferAppendFactsDocumentIndex = this.isNativeMode() && !!prepareNativeDocumentIndexWithAppendFacts;
|
|
@@ -2190,6 +2314,7 @@ let Documents = (() => {
|
|
|
2190
2314
|
resolveTrimmedEntries: input.resolveTrimmedEntries,
|
|
2191
2315
|
payloadData: input.operationPayloadBytes,
|
|
2192
2316
|
useNativeExistingDocumentContext: input.useNativeExistingDocumentContext,
|
|
2317
|
+
...(localCommitEvidence ? { localCommitEvidence } : undefined),
|
|
2193
2318
|
...(nativeDocumentIndexCommit
|
|
2194
2319
|
? {
|
|
2195
2320
|
nativeBackboneDocumentIndex: this.toNativeBackboneDocumentIndexCommitInput(input, nativeDocumentIndexCommit),
|
|
@@ -2211,14 +2336,14 @@ let Documents = (() => {
|
|
|
2211
2336
|
if (this.isNativeMode()) {
|
|
2212
2337
|
throw this.nativeModeError("requires payload-backed put operations");
|
|
2213
2338
|
}
|
|
2214
|
-
return mapMaybePromise(trustedLog.appendLocallyPrepared(input.operation, appendOptions, appendProperties), (appended) => this.createNativeCheckedDocumentAppendCommitFacts(input, appended, committedNativeDocumentIndex));
|
|
2339
|
+
return mapMaybePromise(trustedLog.appendLocallyPrepared(input.operation, appendOptions, appendProperties), (appended) => runAfterDocumentCommit(input.options, appended.appendCommit.hash, () => this.createNativeCheckedDocumentAppendCommitFacts(input, appended, committedNativeDocumentIndex)));
|
|
2215
2340
|
}
|
|
2216
2341
|
const commitOnlyAppend = this.isNativeMode()
|
|
2217
2342
|
? trustedLog.appendStrictNativeDocumentPayloadCommitOnly(input.operationPayloadBytes, appendOptions, appendProperties)
|
|
2218
2343
|
: trustedLog.appendLocallyPreparedPayloadCommitOnly(input.operationPayloadBytes, appendOptions, appendProperties);
|
|
2219
2344
|
return mapMaybePromise(commitOnlyAppend, (commitOnly) => {
|
|
2220
2345
|
if (commitOnly) {
|
|
2221
|
-
return this.createNativeCheckedDocumentAppendCommitFacts(input, commitOnly, committedNativeDocumentIndex);
|
|
2346
|
+
return runAfterDocumentCommit(input.options, commitOnly.appendCommit.hash, () => this.createNativeCheckedDocumentAppendCommitFacts(input, commitOnly, committedNativeDocumentIndex));
|
|
2222
2347
|
}
|
|
2223
2348
|
if (this.isNativeMode()) {
|
|
2224
2349
|
throw this.nativeModeError("requires native payload commit-only append");
|
|
@@ -2296,16 +2421,24 @@ let Documents = (() => {
|
|
|
2296
2421
|
appended = await trustedLog.appendLocallyPreparedPayload(input.operationPayloadBytes, appendOptions, appendProperties);
|
|
2297
2422
|
}
|
|
2298
2423
|
catch (error) {
|
|
2299
|
-
if (
|
|
2424
|
+
if (appendProperties.localCommitEvidence?.committedHashes.size ||
|
|
2425
|
+
!(error instanceof Error) ||
|
|
2300
2426
|
error.message !==
|
|
2301
2427
|
"appendLocallyPrepared payload-only path requires native append support") {
|
|
2302
2428
|
throw error;
|
|
2303
2429
|
}
|
|
2304
2430
|
appended = await trustedLog.appendLocallyPrepared(new PutOperation({ data: input.documentBytes }), appendOptions, appendProperties);
|
|
2305
2431
|
}
|
|
2306
|
-
return this.createDocumentAppendCommitFacts(input, appended, nativeBackboneDocumentIndex);
|
|
2432
|
+
return await runAfterDocumentCommit(input.options, appended.appendCommit.hash, () => this.createDocumentAppendCommitFacts(input, appended, nativeBackboneDocumentIndex));
|
|
2307
2433
|
}
|
|
2308
2434
|
async commitNativeDocumentAppendMany(input) {
|
|
2435
|
+
if (!hasPersistedDelivery(input.options)) {
|
|
2436
|
+
return this.commitNativeDocumentAppendManyWithEvidence(input, undefined);
|
|
2437
|
+
}
|
|
2438
|
+
const localCommitEvidence = { committedHashes: new Set() };
|
|
2439
|
+
return await runWithTrustedLocalCommitEvidence(input.options, localCommitEvidence, () => this.commitNativeDocumentAppendManyWithEvidence(input, localCommitEvidence));
|
|
2440
|
+
}
|
|
2441
|
+
async commitNativeDocumentAppendManyWithEvidence(input, localCommitEvidence) {
|
|
2309
2442
|
const trustedLog = asTrustedDocumentSharedLog(this.log);
|
|
2310
2443
|
const nativeBackboneDocumentIndexes = await this.prepareNativeBackboneDocumentIndexCommitBatch(input.puts);
|
|
2311
2444
|
const nativeBackboneDocumentIndexInputs = nativeBackboneDocumentIndexes?.map((commit, index) => this.toNativeBackboneDocumentIndexCommitInput(input.puts[index], commit, input.useNativeExistingDocumentContext === true));
|
|
@@ -2324,14 +2457,12 @@ let Documents = (() => {
|
|
|
2324
2457
|
}
|
|
2325
2458
|
return [next];
|
|
2326
2459
|
});
|
|
2327
|
-
const appended = await trustedLog.appendLocallyPreparedPayloadsManyIndependent(input.puts.map((put) => put.operationPayloadBytes), {
|
|
2328
|
-
...input.options,
|
|
2329
|
-
replicate: input.options?.replicate,
|
|
2330
|
-
}, {
|
|
2460
|
+
const appended = await trustedLog.appendLocallyPreparedPayloadsManyIndependent(input.puts.map((put) => put.operationPayloadBytes), withoutPersistedDelivery(input.options), {
|
|
2331
2461
|
resolveTrimmedEntries: input.resolveTrimmedEntries,
|
|
2332
2462
|
nexts,
|
|
2333
2463
|
nativeBackboneDocumentIndexes: nativeBackboneDocumentIndexInputs,
|
|
2334
2464
|
retainMaterializationBytes: this._hasLogTrim,
|
|
2465
|
+
...(localCommitEvidence ? { localCommitEvidence } : undefined),
|
|
2335
2466
|
});
|
|
2336
2467
|
if (!appended) {
|
|
2337
2468
|
if (this.isNativeMode()) {
|
|
@@ -2339,36 +2470,38 @@ let Documents = (() => {
|
|
|
2339
2470
|
}
|
|
2340
2471
|
return undefined;
|
|
2341
2472
|
}
|
|
2342
|
-
|
|
2343
|
-
input
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2473
|
+
return await runAfterDocumentCommit(input.options, () => appended.appendCommits.map((commit) => commit.hash), async () => {
|
|
2474
|
+
const appendInputs = input.puts.map((put, index) => ({
|
|
2475
|
+
input: nativeBackboneDocumentIndexes?.[index]
|
|
2476
|
+
? {
|
|
2477
|
+
...put,
|
|
2478
|
+
nativeBackboneDocumentIndex: nativeBackboneDocumentIndexes[index],
|
|
2479
|
+
}
|
|
2480
|
+
: put,
|
|
2481
|
+
appended: (() => {
|
|
2482
|
+
const materializeEntry = appended.materializeEntries?.[index];
|
|
2483
|
+
let entry;
|
|
2484
|
+
return {
|
|
2485
|
+
get entry() {
|
|
2486
|
+
return (entry ??= materializeEntry
|
|
2487
|
+
? materializeEntry()
|
|
2488
|
+
: appended.entries[index]);
|
|
2489
|
+
},
|
|
2490
|
+
removed: [],
|
|
2491
|
+
appendCommit: appended.appendCommits[index],
|
|
2492
|
+
};
|
|
2493
|
+
})(),
|
|
2494
|
+
}));
|
|
2495
|
+
const commits = await this.createDocumentAppendCommitFactsBatch(appendInputs);
|
|
2496
|
+
let entries;
|
|
2497
|
+
return {
|
|
2498
|
+
get entries() {
|
|
2499
|
+
return (entries ??= commits.map((commit) => commit.entry));
|
|
2500
|
+
},
|
|
2501
|
+
removed: appended.removed,
|
|
2502
|
+
commits,
|
|
2503
|
+
};
|
|
2504
|
+
});
|
|
2372
2505
|
}
|
|
2373
2506
|
prepareNativeBackboneDocumentIndexCommitBatch(inputs) {
|
|
2374
2507
|
if (!this._nativeBackboneDocumentIndexEnabled || inputs.length === 0) {
|
|
@@ -2659,6 +2792,40 @@ let Documents = (() => {
|
|
|
2659
2792
|
}),
|
|
2660
2793
|
});
|
|
2661
2794
|
}
|
|
2795
|
+
finishPreparedPlainPutCommit(commit, options, handle = () => this.handlePreparedPlainPutCommit(commit)) {
|
|
2796
|
+
return runAfterDocumentCommit(options, commit.append.hash, () => mapMaybePromise(handle(), () => {
|
|
2797
|
+
this.keepCache?.add(commit.append.hash);
|
|
2798
|
+
const persistedEntry = hasPersistedDelivery(options)
|
|
2799
|
+
? commit.entry
|
|
2800
|
+
: undefined;
|
|
2801
|
+
return {
|
|
2802
|
+
get entry() {
|
|
2803
|
+
return persistedEntry ?? commit.entry;
|
|
2804
|
+
},
|
|
2805
|
+
removed: commit.removed,
|
|
2806
|
+
};
|
|
2807
|
+
}));
|
|
2808
|
+
}
|
|
2809
|
+
finishPreparedPlainPutManyCommit(commit, options) {
|
|
2810
|
+
return runAfterDocumentCommit(options, () => commit.commits.map((item) => item.append.hash), () => mapMaybePromise(this.handlePreparedPlainPutManyCommit(commit), () => {
|
|
2811
|
+
for (const item of commit.commits) {
|
|
2812
|
+
this.keepCache?.add(item.append.hash);
|
|
2813
|
+
}
|
|
2814
|
+
const result = {
|
|
2815
|
+
get entries() {
|
|
2816
|
+
return commit.entries;
|
|
2817
|
+
},
|
|
2818
|
+
removed: commit.removed,
|
|
2819
|
+
};
|
|
2820
|
+
if (hasPersistedDelivery(options)) {
|
|
2821
|
+
persistedDocumentAppendDelivery.set(result, {
|
|
2822
|
+
appendCommits: commit.commits.map((item) => item.append),
|
|
2823
|
+
materializeEntries: () => commit.entries,
|
|
2824
|
+
});
|
|
2825
|
+
}
|
|
2826
|
+
return result;
|
|
2827
|
+
}));
|
|
2828
|
+
}
|
|
2662
2829
|
handlePreparedPlainPutCommit(commit) {
|
|
2663
2830
|
const shouldPrepareChange = this.hasDocumentChangeConsumers();
|
|
2664
2831
|
const removedAlreadyHandled = commit.nativeBackboneDocumentIndexTrimmedHeadsProcessed === true;
|
|
@@ -2935,8 +3102,7 @@ let Documents = (() => {
|
|
|
2935
3102
|
}
|
|
2936
3103
|
}
|
|
2937
3104
|
async handlePreparedPlainPutManyCommit(commit) {
|
|
2938
|
-
if (!this.hasDocumentChangeConsumers() &&
|
|
2939
|
-
commit.removed.length === 0) {
|
|
3105
|
+
if (!this.hasDocumentChangeConsumers() && commit.removed.length === 0) {
|
|
2940
3106
|
const stored = await asTrustedDocumentIndex(this._index)._putManyPreparedNativeBackboneDocumentIndexStored(commit.commits.map((put) => {
|
|
2941
3107
|
const existing = put.unique || put.existing === null ? null : put.existing;
|
|
2942
3108
|
return {
|
|
@@ -2985,16 +3151,15 @@ let Documents = (() => {
|
|
|
2985
3151
|
encodedValueParts: put.contextualEncodedValueParts,
|
|
2986
3152
|
},
|
|
2987
3153
|
})));
|
|
2988
|
-
indexedDocuments ??=
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
})));
|
|
3154
|
+
indexedDocuments ??= await asTrustedDocumentIndex(this._index)._putManyPreparedNativeBackboneDocumentIndexWithContext(putsToIndex.map((put) => ({
|
|
3155
|
+
value: put.document,
|
|
3156
|
+
id: put.key,
|
|
3157
|
+
context: put.context,
|
|
3158
|
+
nativeDocumentIndex: put.nativeBackboneDocumentIndex,
|
|
3159
|
+
options: {
|
|
3160
|
+
replace: put.replace,
|
|
3161
|
+
},
|
|
3162
|
+
})));
|
|
2998
3163
|
if (indexedDocuments) {
|
|
2999
3164
|
documentsChanged.added.push(...indexedDocuments);
|
|
3000
3165
|
}
|
|
@@ -3297,6 +3462,9 @@ let Documents = (() => {
|
|
|
3297
3462
|
return resolved ? resolved : undefined;
|
|
3298
3463
|
}
|
|
3299
3464
|
async del(id, options) {
|
|
3465
|
+
if (hasPersistedDelivery(options)) {
|
|
3466
|
+
throw new Error("persisted delivery is not supported for document deletes");
|
|
3467
|
+
}
|
|
3300
3468
|
return this._documentBackend.del(id, options);
|
|
3301
3469
|
}
|
|
3302
3470
|
async delCompatDocumentBackend(id, options) {
|
|
@@ -3481,8 +3649,7 @@ let Documents = (() => {
|
|
|
3481
3649
|
}
|
|
3482
3650
|
const existing = reference?.unique || reference?.existing === null
|
|
3483
3651
|
? null
|
|
3484
|
-
: isReferencedAppendEntry &&
|
|
3485
|
-
reference?.existing !== undefined
|
|
3652
|
+
: isReferencedAppendEntry && reference?.existing !== undefined
|
|
3486
3653
|
? reference.existing
|
|
3487
3654
|
: this.getNativeModeIndexedContext(key) || null;
|
|
3488
3655
|
if (!this.strictHistory && existing) {
|