@peerbit/document 13.1.5 → 13.1.7
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/src/program.d.ts.map +1 -1
- package/dist/src/program.js +1 -0
- package/dist/src/program.js.map +1 -1
- package/dist/src/resumable-iterator.d.ts +5 -0
- package/dist/src/resumable-iterator.d.ts.map +1 -1
- package/dist/src/resumable-iterator.js +58 -20
- package/dist/src/resumable-iterator.js.map +1 -1
- package/dist/src/search.d.ts +7 -7
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +454 -203
- package/dist/src/search.js.map +1 -1
- package/package.json +20 -20
- package/src/program.ts +4 -0
- package/src/resumable-iterator.ts +68 -20
- package/src/search.ts +475 -160
package/dist/src/search.js
CHANGED
|
@@ -40,7 +40,7 @@ import { tryProjectDocumentIndexSimple, } from "./native-rust.js";
|
|
|
40
40
|
import { CachedIndex } from "@peerbit/indexer-cache";
|
|
41
41
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
42
42
|
import { HashmapIndex } from "@peerbit/indexer-simple";
|
|
43
|
-
import { BORSH_ENCODING
|
|
43
|
+
import { BORSH_ENCODING } from "@peerbit/log";
|
|
44
44
|
import { logger as loggerFn } from "@peerbit/logger";
|
|
45
45
|
import { ClosedError, Program } from "@peerbit/program";
|
|
46
46
|
import { MissingResponsesError, RPC, queryAll, } from "@peerbit/rpc";
|
|
@@ -48,7 +48,7 @@ import { SharedLog, } from "@peerbit/shared-log";
|
|
|
48
48
|
import { DataMessage, FOREGROUND_READ_MESSAGE_PRIORITY, SilentDelivery, } from "@peerbit/stream-interface";
|
|
49
49
|
import { AbortError, TimeoutError, waitFor } from "@peerbit/time";
|
|
50
50
|
import pDefer, {} from "p-defer";
|
|
51
|
-
import { concat, fromString } from "uint8arrays";
|
|
51
|
+
import { concat, equals, fromString } from "uint8arrays";
|
|
52
52
|
import { copySerialization } from "./borsh.js";
|
|
53
53
|
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
54
54
|
import MostCommonQueryPredictor, { idAgnosticQueryKey, } from "./most-common-query-predictor.js";
|
|
@@ -377,6 +377,7 @@ function isSubclassOf(SubClass, SuperClass) {
|
|
|
377
377
|
const DEFAULT_TIMEOUT = 1e4;
|
|
378
378
|
const DEFAULT_KEEP_REMOTE_ITERATOR_TIMEOUT = 3e5;
|
|
379
379
|
const DISCOVER_TIMEOUT_FALLBACK = 500;
|
|
380
|
+
const CLOSE_ITERATOR_REQUEST_TIMEOUT = 5e3;
|
|
380
381
|
const DEFAULT_INDEX_BY = "id";
|
|
381
382
|
export const INDEX_CONTEXT_SHAPE = {
|
|
382
383
|
__context: {
|
|
@@ -551,33 +552,76 @@ let DocumentIndex = (() => {
|
|
|
551
552
|
this._prefetch.accumulator = new Prefetch();
|
|
552
553
|
}
|
|
553
554
|
}
|
|
554
|
-
/**
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
|
|
559
|
-
async
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
555
|
+
/**
|
|
556
|
+
* Resolve documents without bypassing the resolver/program caches. Cache and
|
|
557
|
+
* identity-index hits are collected first; only the remaining heads cross the
|
|
558
|
+
* log read boundary, and those reads stay aligned in one batch.
|
|
559
|
+
*/
|
|
560
|
+
async resolveDocumentsWithBatchedHeads(values) {
|
|
561
|
+
const resolved = new Array(values.length);
|
|
562
|
+
const heads = new Array(values.length);
|
|
563
|
+
const unresolvedPositions = [];
|
|
564
|
+
for (let i = 0; i < values.length; i++) {
|
|
565
|
+
const value = values[i];
|
|
566
|
+
const cached = await this.resolveDocument({
|
|
567
|
+
...value,
|
|
568
|
+
headEntry: null,
|
|
569
|
+
});
|
|
570
|
+
if (cached) {
|
|
571
|
+
resolved[i] = cached;
|
|
570
572
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
+
else {
|
|
574
|
+
unresolvedPositions.push(i);
|
|
573
575
|
}
|
|
574
576
|
}
|
|
577
|
+
if (unresolvedPositions.length === 0) {
|
|
578
|
+
return { resolved, heads };
|
|
579
|
+
}
|
|
580
|
+
const unresolvedHeads = await this._log.log.getMany(unresolvedPositions.map((position) => values[position].head));
|
|
581
|
+
for (let i = 0; i < unresolvedPositions.length; i++) {
|
|
582
|
+
const position = unresolvedPositions[i];
|
|
583
|
+
const head = unresolvedHeads[i];
|
|
584
|
+
heads[position] = head;
|
|
585
|
+
resolved[position] = await this.resolveDocument({
|
|
586
|
+
...values[position],
|
|
587
|
+
headEntry: head ?? null,
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
return { resolved, heads };
|
|
575
591
|
}
|
|
576
592
|
async wrapPushResults(matches, resolve) {
|
|
577
593
|
if (!matches.length)
|
|
578
594
|
return [];
|
|
595
|
+
const headsByMatch = [];
|
|
596
|
+
const resolvedByMatch = [];
|
|
597
|
+
if (!resolve) {
|
|
598
|
+
headsByMatch.push(...(await this._log.log.getMany(matches.map((match) => match.__context.head))));
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
const indexedPositions = [];
|
|
602
|
+
for (let i = 0; i < matches.length; i++) {
|
|
603
|
+
if (!(matches[i] instanceof this.documentType)) {
|
|
604
|
+
indexedPositions.push(i);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
const indexedBatch = indexedPositions.length
|
|
608
|
+
? await this.resolveDocumentsWithBatchedHeads(indexedPositions.map((position) => {
|
|
609
|
+
const indexed = matches[position];
|
|
610
|
+
return {
|
|
611
|
+
indexed,
|
|
612
|
+
head: indexed.__context.head,
|
|
613
|
+
};
|
|
614
|
+
}))
|
|
615
|
+
: { resolved: [], heads: [] };
|
|
616
|
+
for (let i = 0; i < indexedPositions.length; i++) {
|
|
617
|
+
const position = indexedPositions[i];
|
|
618
|
+
resolvedByMatch[position] = indexedBatch.resolved[i];
|
|
619
|
+
headsByMatch[position] = indexedBatch.heads[i];
|
|
620
|
+
}
|
|
621
|
+
}
|
|
579
622
|
const results = [];
|
|
580
|
-
for (
|
|
623
|
+
for (let i = 0; i < matches.length; i++) {
|
|
624
|
+
const match = matches[i];
|
|
581
625
|
if (resolve) {
|
|
582
626
|
if (match instanceof this.documentType) {
|
|
583
627
|
const doc = match;
|
|
@@ -592,10 +636,7 @@ let DocumentIndex = (() => {
|
|
|
592
636
|
continue;
|
|
593
637
|
}
|
|
594
638
|
const indexed = match;
|
|
595
|
-
const resolved =
|
|
596
|
-
indexed,
|
|
597
|
-
head: indexed.__context.head,
|
|
598
|
-
});
|
|
639
|
+
const resolved = resolvedByMatch[i];
|
|
599
640
|
if (resolved) {
|
|
600
641
|
results.push(new types.ResultValue({
|
|
601
642
|
context: indexed.__context,
|
|
@@ -605,7 +646,7 @@ let DocumentIndex = (() => {
|
|
|
605
646
|
}));
|
|
606
647
|
continue;
|
|
607
648
|
}
|
|
608
|
-
const head =
|
|
649
|
+
const head = headsByMatch[i];
|
|
609
650
|
results.push(new types.ResultIndexedValue({
|
|
610
651
|
context: indexed.__context,
|
|
611
652
|
source: serialize(indexed),
|
|
@@ -615,7 +656,7 @@ let DocumentIndex = (() => {
|
|
|
615
656
|
}
|
|
616
657
|
else {
|
|
617
658
|
const indexed = match;
|
|
618
|
-
const head =
|
|
659
|
+
const head = headsByMatch[i];
|
|
619
660
|
results.push(new types.ResultIndexedValue({
|
|
620
661
|
context: indexed.__context,
|
|
621
662
|
source: serialize(indexed),
|
|
@@ -631,14 +672,21 @@ let DocumentIndex = (() => {
|
|
|
631
672
|
return [];
|
|
632
673
|
}
|
|
633
674
|
const drained = queueEntries.splice(0);
|
|
675
|
+
const resolvedBatch = resolve
|
|
676
|
+
? await this.resolveDocumentsWithBatchedHeads(drained.map((entry) => ({
|
|
677
|
+
indexed: entry.value,
|
|
678
|
+
head: entry.value.__context.head,
|
|
679
|
+
})))
|
|
680
|
+
: undefined;
|
|
681
|
+
const heads = resolvedBatch
|
|
682
|
+
? resolvedBatch.heads
|
|
683
|
+
: await this._log.log.getMany(drained.map((entry) => entry.value.__context.head));
|
|
634
684
|
const results = [];
|
|
635
|
-
for (
|
|
685
|
+
for (let i = 0; i < drained.length; i++) {
|
|
686
|
+
const entry = drained[i];
|
|
636
687
|
const indexedUnwrapped = Object.assign(Object.create(this.indexedType.prototype), entry.value);
|
|
637
688
|
if (resolve) {
|
|
638
|
-
const value =
|
|
639
|
-
indexed: entry.value,
|
|
640
|
-
head: entry.value.__context.head,
|
|
641
|
-
});
|
|
689
|
+
const value = resolvedBatch.resolved[i];
|
|
642
690
|
if (value) {
|
|
643
691
|
results.push(new types.ResultValue({
|
|
644
692
|
context: entry.value.__context,
|
|
@@ -648,7 +696,7 @@ let DocumentIndex = (() => {
|
|
|
648
696
|
}));
|
|
649
697
|
continue;
|
|
650
698
|
}
|
|
651
|
-
const head =
|
|
699
|
+
const head = heads[i];
|
|
652
700
|
results.push(new types.ResultIndexedValue({
|
|
653
701
|
context: entry.value.__context,
|
|
654
702
|
source: serialize(indexedUnwrapped),
|
|
@@ -657,7 +705,7 @@ let DocumentIndex = (() => {
|
|
|
657
705
|
}));
|
|
658
706
|
}
|
|
659
707
|
else {
|
|
660
|
-
const head =
|
|
708
|
+
const head = heads[i];
|
|
661
709
|
results.push(new types.ResultIndexedValue({
|
|
662
710
|
context: entry.value.__context,
|
|
663
711
|
source: serialize(indexedUnwrapped),
|
|
@@ -697,6 +745,7 @@ let DocumentIndex = (() => {
|
|
|
697
745
|
let pendingAdded = added;
|
|
698
746
|
do {
|
|
699
747
|
const batches = [];
|
|
748
|
+
let claimedIds = [];
|
|
700
749
|
const queued = await this.drainQueuedResults(queue.queue, resolveFlag);
|
|
701
750
|
if (queued.length) {
|
|
702
751
|
batches.push(...queued);
|
|
@@ -710,6 +759,13 @@ let DocumentIndex = (() => {
|
|
|
710
759
|
const wrapped = await this.wrapPushResults(matches, resolveFlag);
|
|
711
760
|
if (wrapped.length) {
|
|
712
761
|
batches.push(...wrapped);
|
|
762
|
+
claimedIds = wrapped
|
|
763
|
+
.map((result) => result instanceof types.ResultValue && result.indexed
|
|
764
|
+
? indexerTypes.toId(this.indexByResolver(result.indexed))
|
|
765
|
+
: result instanceof types.ResultIndexedValue
|
|
766
|
+
? indexerTypes.toId(this.indexByResolver(result.value))
|
|
767
|
+
: undefined)
|
|
768
|
+
.filter((id) => id !== undefined);
|
|
713
769
|
}
|
|
714
770
|
}
|
|
715
771
|
if (batches.length) {
|
|
@@ -727,6 +783,9 @@ let DocumentIndex = (() => {
|
|
|
727
783
|
redundancy: 1,
|
|
728
784
|
}),
|
|
729
785
|
});
|
|
786
|
+
if (claimedIds.length) {
|
|
787
|
+
await this._resumableIterators.markYielded(_iteratorId, claimedIds);
|
|
788
|
+
}
|
|
730
789
|
}
|
|
731
790
|
pendingAdded = queue.pendingAdded ?? [];
|
|
732
791
|
queue.pendingAdded = undefined;
|
|
@@ -2235,7 +2294,9 @@ let DocumentIndex = (() => {
|
|
|
2235
2294
|
delete obj.__context;
|
|
2236
2295
|
return { value: obj };
|
|
2237
2296
|
}
|
|
2238
|
-
const head =
|
|
2297
|
+
const head = value.headEntry === undefined
|
|
2298
|
+
? await this._log.log.get(value.head)
|
|
2299
|
+
: (value.headEntry ?? undefined);
|
|
2239
2300
|
if (!head) {
|
|
2240
2301
|
return undefined; // we could end up here if we recently pruned the document and other peers never persisted the entry
|
|
2241
2302
|
// TODO update changes in index before removing entries from log entry storage
|
|
@@ -2326,7 +2387,7 @@ let DocumentIndex = (() => {
|
|
|
2326
2387
|
}
|
|
2327
2388
|
this._resultQueue.set(query.idString, prevQueued);
|
|
2328
2389
|
}
|
|
2329
|
-
const
|
|
2390
|
+
const candidates = [];
|
|
2330
2391
|
const resolveDocumentsFlag = resolvesDocuments(fromQuery);
|
|
2331
2392
|
const replicateIndexFlag = replicatesIndex(fromQuery);
|
|
2332
2393
|
for (const result of toIterate) {
|
|
@@ -2342,11 +2403,24 @@ let DocumentIndex = (() => {
|
|
|
2342
2403
|
!(await options.canRead(indexedUnwrapped, from))) {
|
|
2343
2404
|
continue;
|
|
2344
2405
|
}
|
|
2406
|
+
candidates.push({ result, indexed: indexedUnwrapped });
|
|
2407
|
+
}
|
|
2408
|
+
const resolvedBatch = resolveDocumentsFlag
|
|
2409
|
+
? await this.resolveDocumentsWithBatchedHeads(candidates.map(({ result }) => ({
|
|
2410
|
+
indexed: result.value,
|
|
2411
|
+
head: result.value.__context.head,
|
|
2412
|
+
})))
|
|
2413
|
+
: undefined;
|
|
2414
|
+
const heads = resolvedBatch
|
|
2415
|
+
? resolvedBatch.heads
|
|
2416
|
+
: candidates.length > 0
|
|
2417
|
+
? await this._log.log.getMany(candidates.map(({ result }) => result.value.__context.head))
|
|
2418
|
+
: [];
|
|
2419
|
+
const filteredResults = [];
|
|
2420
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
2421
|
+
const { result, indexed: indexedUnwrapped } = candidates[i];
|
|
2345
2422
|
if (resolveDocumentsFlag) {
|
|
2346
|
-
const value =
|
|
2347
|
-
indexed: result.value,
|
|
2348
|
-
head: result.value.__context.head,
|
|
2349
|
-
});
|
|
2423
|
+
const value = resolvedBatch.resolved[i];
|
|
2350
2424
|
if (!value) {
|
|
2351
2425
|
continue;
|
|
2352
2426
|
}
|
|
@@ -2359,7 +2433,7 @@ let DocumentIndex = (() => {
|
|
|
2359
2433
|
}
|
|
2360
2434
|
else {
|
|
2361
2435
|
const context = result.value.__context;
|
|
2362
|
-
const head =
|
|
2436
|
+
const head = heads[i];
|
|
2363
2437
|
if (replicateIndexFlag) {
|
|
2364
2438
|
if (!head) {
|
|
2365
2439
|
continue;
|
|
@@ -2721,6 +2795,7 @@ let DocumentIndex = (() => {
|
|
|
2721
2795
|
};
|
|
2722
2796
|
let extraPromises = undefined;
|
|
2723
2797
|
const seenRemoteHashes = new Set();
|
|
2798
|
+
const selectedRemoteHashes = [];
|
|
2724
2799
|
const groupHashes = replicatorGroups
|
|
2725
2800
|
.filter((hash) => {
|
|
2726
2801
|
if (hash === this.node.identity.publicKey.hashcode()) {
|
|
@@ -2735,6 +2810,7 @@ let DocumentIndex = (() => {
|
|
|
2735
2810
|
return false;
|
|
2736
2811
|
}
|
|
2737
2812
|
fetchFirstForRemote?.add(hash);
|
|
2813
|
+
selectedRemoteHashes.push(hash);
|
|
2738
2814
|
const resultAlready = this._prefetch?.accumulator.consume(queryRequest, hash);
|
|
2739
2815
|
if (resultAlready) {
|
|
2740
2816
|
(extraPromises || (extraPromises = [])).push((async () => {
|
|
@@ -2753,6 +2829,7 @@ let DocumentIndex = (() => {
|
|
|
2753
2829
|
return true;
|
|
2754
2830
|
})
|
|
2755
2831
|
.map((x) => [x]);
|
|
2832
|
+
options?.onRemoteTargets?.(selectedRemoteHashes);
|
|
2756
2833
|
extraPromises && (await Promise.all(extraPromises));
|
|
2757
2834
|
let tearDown = undefined;
|
|
2758
2835
|
const search = this;
|
|
@@ -2857,16 +2934,20 @@ let DocumentIndex = (() => {
|
|
|
2857
2934
|
// Use an iterator so large results respect message size limits.
|
|
2858
2935
|
const iterator = this.iterate(coercedRequest, searchOptions);
|
|
2859
2936
|
const allResults = [];
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
allResults.
|
|
2937
|
+
try {
|
|
2938
|
+
while (iterator.done() !== true &&
|
|
2939
|
+
coercedRequest.fetch > allResults.length) {
|
|
2940
|
+
// We might need to pull .next multiple time due to data message size limitations
|
|
2941
|
+
for (const result of await iterator.next(coercedRequest.fetch - allResults.length)) {
|
|
2942
|
+
allResults.push(result);
|
|
2943
|
+
}
|
|
2865
2944
|
}
|
|
2945
|
+
// Deduplicate and return values directly
|
|
2946
|
+
return dedup(allResults, this.indexByResolver);
|
|
2947
|
+
}
|
|
2948
|
+
finally {
|
|
2949
|
+
await iterator.close();
|
|
2866
2950
|
}
|
|
2867
|
-
await iterator.close();
|
|
2868
|
-
// Deduplicate and return values directly
|
|
2869
|
-
return dedup(allResults, this.indexByResolver);
|
|
2870
2951
|
}
|
|
2871
2952
|
resolveIndexed(result, results) {
|
|
2872
2953
|
if (isResultIndexedValue(result)) {
|
|
@@ -3062,6 +3143,48 @@ let DocumentIndex = (() => {
|
|
|
3062
3143
|
return tracked;
|
|
3063
3144
|
};
|
|
3064
3145
|
const peerBufferMap = new Map();
|
|
3146
|
+
const remoteIteratorPeersToClose = new Set();
|
|
3147
|
+
const staleRemoteIteratorIdsToClose = new Map();
|
|
3148
|
+
const retiredRemoteIteratorPeers = new Set();
|
|
3149
|
+
const pendingMissingResponseRetryPeers = new Set();
|
|
3150
|
+
const missingResponseRetryAttempts = new Map();
|
|
3151
|
+
const maxMissingResponseRetryAttempts = 2;
|
|
3152
|
+
const retireRemoteIteratorPeer = (peer) => {
|
|
3153
|
+
remoteIteratorPeersToClose.add(peer);
|
|
3154
|
+
retiredRemoteIteratorPeers.add(peer);
|
|
3155
|
+
const peerBuffer = peerBufferMap.get(peer);
|
|
3156
|
+
if (!peerBuffer || peerBuffer.buffer.length === 0) {
|
|
3157
|
+
peerBufferMap.delete(peer);
|
|
3158
|
+
}
|
|
3159
|
+
else {
|
|
3160
|
+
// Keep already-received values available to the caller, but do not
|
|
3161
|
+
// issue another CollectNextRequest until a fresh iteration succeeds.
|
|
3162
|
+
peerBuffer.kept = 0;
|
|
3163
|
+
}
|
|
3164
|
+
};
|
|
3165
|
+
const recordMissingResponseGroups = (missingGroups) => {
|
|
3166
|
+
const selfHash = this.node.identity.publicKey.hashcode();
|
|
3167
|
+
for (const group of missingGroups) {
|
|
3168
|
+
for (const hash of group) {
|
|
3169
|
+
if (hash && hash !== selfHash) {
|
|
3170
|
+
retireRemoteIteratorPeer(hash);
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
if (!retryMissingResponseGroups) {
|
|
3174
|
+
continue;
|
|
3175
|
+
}
|
|
3176
|
+
const target = group.find((hash) => {
|
|
3177
|
+
if (!hash || hash === selfHash)
|
|
3178
|
+
return false;
|
|
3179
|
+
const attempts = missingResponseRetryAttempts.get(hash) ?? 0;
|
|
3180
|
+
return attempts < maxMissingResponseRetryAttempts;
|
|
3181
|
+
});
|
|
3182
|
+
if (!target)
|
|
3183
|
+
continue;
|
|
3184
|
+
pendingMissingResponseRetryPeers.add(target);
|
|
3185
|
+
missingResponseRetryAttempts.set(target, (missingResponseRetryAttempts.get(target) ?? 0) + 1);
|
|
3186
|
+
}
|
|
3187
|
+
};
|
|
3065
3188
|
const visited = new Set();
|
|
3066
3189
|
let indexedPlaceholders;
|
|
3067
3190
|
const ensureIndexedPlaceholders = () => {
|
|
@@ -3241,6 +3364,15 @@ let DocumentIndex = (() => {
|
|
|
3241
3364
|
}
|
|
3242
3365
|
}
|
|
3243
3366
|
const fetchFirst = async (n, fetchOptions) => {
|
|
3367
|
+
const remoteRequestOptions = typeof options?.remote === "object" ? options.remote : undefined;
|
|
3368
|
+
const fetchSignals = [
|
|
3369
|
+
options?.signal,
|
|
3370
|
+
remoteRequestOptions?.signal,
|
|
3371
|
+
ensureController().signal,
|
|
3372
|
+
].filter((signal) => signal != null);
|
|
3373
|
+
const fetchSignal = fetchSignals.length === 1
|
|
3374
|
+
? fetchSignals[0]
|
|
3375
|
+
: AbortSignal.any(fetchSignals);
|
|
3244
3376
|
await warmupPromise;
|
|
3245
3377
|
let hasMore = false;
|
|
3246
3378
|
let missingResponses = false;
|
|
@@ -3253,43 +3385,56 @@ let DocumentIndex = (() => {
|
|
|
3253
3385
|
const skipRemoteDueToDiscovery = typeof options?.remote === "object" &&
|
|
3254
3386
|
options.remote.reach?.discover &&
|
|
3255
3387
|
discoveredTargetHashes?.length === 0;
|
|
3388
|
+
const queryRemote = options?.remote !== false && !skipRemoteDueToDiscovery;
|
|
3389
|
+
const remoteFrom = fetchOptions?.from ??
|
|
3390
|
+
initialRemoteTargets ??
|
|
3391
|
+
remoteRequestOptions?.from;
|
|
3392
|
+
if (queryRemote) {
|
|
3393
|
+
const selfHash = this.node.identity.publicKey.hashcode();
|
|
3394
|
+
for (const peer of remoteFrom ?? []) {
|
|
3395
|
+
if (peer !== selfHash) {
|
|
3396
|
+
remoteIteratorPeersToClose.add(peer);
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3256
3400
|
queryRequestCoerced.fetch = n;
|
|
3257
3401
|
await this.queryCommence(queryRequestCoerced, {
|
|
3258
3402
|
local: fetchOptions?.from != null ? false : options?.local,
|
|
3259
|
-
remote:
|
|
3403
|
+
remote: queryRemote
|
|
3260
3404
|
? {
|
|
3261
|
-
...
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
from: fetchOptions?.from ??
|
|
3265
|
-
initialRemoteTargets ??
|
|
3266
|
-
(typeof options?.remote === "object"
|
|
3267
|
-
? options.remote.from
|
|
3268
|
-
: undefined),
|
|
3405
|
+
...remoteRequestOptions,
|
|
3406
|
+
from: remoteFrom,
|
|
3407
|
+
signal: fetchSignal,
|
|
3269
3408
|
}
|
|
3270
3409
|
: false,
|
|
3271
3410
|
resolve,
|
|
3272
|
-
signal:
|
|
3411
|
+
signal: fetchSignal,
|
|
3273
3412
|
onResponse: async (response, from) => {
|
|
3274
3413
|
if (!from) {
|
|
3275
3414
|
logger.error("Missing response from");
|
|
3276
3415
|
return;
|
|
3277
3416
|
}
|
|
3417
|
+
const fromHash = from.hashcode();
|
|
3418
|
+
remoteIteratorPeersToClose.add(fromHash);
|
|
3419
|
+
retiredRemoteIteratorPeers.delete(fromHash);
|
|
3278
3420
|
if (response instanceof types.NoAccess) {
|
|
3279
3421
|
logger.error("Dont have access");
|
|
3280
3422
|
return;
|
|
3281
3423
|
}
|
|
3282
3424
|
else if (isResults(response)) {
|
|
3283
3425
|
const results = response;
|
|
3284
|
-
const existingBuffer = peerBufferMap.get(
|
|
3426
|
+
const existingBuffer = peerBufferMap.get(fromHash);
|
|
3285
3427
|
const buffer = existingBuffer?.buffer || [];
|
|
3286
3428
|
if (results.kept === 0n && results.results.length === 0) {
|
|
3287
3429
|
if (keepRemoteAlive) {
|
|
3288
|
-
peerBufferMap.set(
|
|
3430
|
+
peerBufferMap.set(fromHash, {
|
|
3289
3431
|
buffer,
|
|
3290
3432
|
kept: 0,
|
|
3291
3433
|
});
|
|
3292
3434
|
}
|
|
3435
|
+
else {
|
|
3436
|
+
remoteIteratorPeersToClose.delete(fromHash);
|
|
3437
|
+
}
|
|
3293
3438
|
return;
|
|
3294
3439
|
}
|
|
3295
3440
|
const reqFetch = queryRequestCoerced.fetch ?? 0;
|
|
@@ -3298,6 +3443,9 @@ let DocumentIndex = (() => {
|
|
|
3298
3443
|
if (effectiveKept > 0) {
|
|
3299
3444
|
hasMore = true;
|
|
3300
3445
|
}
|
|
3446
|
+
else if (!keepRemoteAlive) {
|
|
3447
|
+
remoteIteratorPeersToClose.delete(fromHash);
|
|
3448
|
+
}
|
|
3301
3449
|
for (const result of results.results) {
|
|
3302
3450
|
const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
|
|
3303
3451
|
if (isResultValue(result)) {
|
|
@@ -3342,7 +3490,7 @@ let DocumentIndex = (() => {
|
|
|
3342
3490
|
ensureIndexedPlaceholders().set(indexKey, placeholder);
|
|
3343
3491
|
}
|
|
3344
3492
|
}
|
|
3345
|
-
peerBufferMap.set(
|
|
3493
|
+
peerBufferMap.set(fromHash, {
|
|
3346
3494
|
buffer,
|
|
3347
3495
|
kept: effectiveKept,
|
|
3348
3496
|
});
|
|
@@ -3353,29 +3501,21 @@ let DocumentIndex = (() => {
|
|
|
3353
3501
|
},
|
|
3354
3502
|
onMissingResponses: (error) => {
|
|
3355
3503
|
missingResponses = true;
|
|
3356
|
-
if (!retryMissingResponseGroups) {
|
|
3357
|
-
return;
|
|
3358
|
-
}
|
|
3359
3504
|
const missingGroups = error.missingGroups;
|
|
3360
3505
|
if (!missingGroups?.length) {
|
|
3361
3506
|
return;
|
|
3362
3507
|
}
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
const attempts = missingResponseRetryAttempts.get(hash) ?? 0;
|
|
3369
|
-
return attempts < maxMissingResponseRetryAttempts;
|
|
3370
|
-
});
|
|
3371
|
-
if (!target)
|
|
3372
|
-
continue;
|
|
3373
|
-
pendingMissingResponseRetryPeers.add(target);
|
|
3374
|
-
missingResponseRetryAttempts.set(target, (missingResponseRetryAttempts.get(target) ?? 0) + 1);
|
|
3508
|
+
recordMissingResponseGroups(missingGroups);
|
|
3509
|
+
},
|
|
3510
|
+
onRemoteTargets: (targets) => {
|
|
3511
|
+
for (const peer of targets) {
|
|
3512
|
+
remoteIteratorPeersToClose.add(peer);
|
|
3375
3513
|
}
|
|
3376
3514
|
},
|
|
3377
3515
|
}, fetchOptions?.fetchedFirstForRemote);
|
|
3378
|
-
if (missingResponses &&
|
|
3516
|
+
if (missingResponses &&
|
|
3517
|
+
retryMissingResponseGroups &&
|
|
3518
|
+
pendingMissingResponseRetryPeers.size > 0) {
|
|
3379
3519
|
hasMore = true;
|
|
3380
3520
|
unsetDone();
|
|
3381
3521
|
}
|
|
@@ -3400,6 +3540,18 @@ let DocumentIndex = (() => {
|
|
|
3400
3540
|
if (pendingMissingResponseRetryPeers.size > 0) {
|
|
3401
3541
|
const retryTargets = [...pendingMissingResponseRetryPeers];
|
|
3402
3542
|
pendingMissingResponseRetryPeers.clear();
|
|
3543
|
+
const idTranslation = this._prefetch?.accumulator.getTranslationMap(queryRequestCoerced);
|
|
3544
|
+
for (const peer of retryTargets) {
|
|
3545
|
+
const staleRemoteIteratorId = idTranslation?.get(peer);
|
|
3546
|
+
if (staleRemoteIteratorId) {
|
|
3547
|
+
const staleIds = staleRemoteIteratorIdsToClose.get(peer) ?? [];
|
|
3548
|
+
if (!staleIds.some((id) => equals(id, staleRemoteIteratorId))) {
|
|
3549
|
+
staleIds.push(staleRemoteIteratorId);
|
|
3550
|
+
staleRemoteIteratorIdsToClose.set(peer, staleIds);
|
|
3551
|
+
}
|
|
3552
|
+
idTranslation.delete(peer);
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3403
3555
|
return setFetchPromise(fetchFirst(n, {
|
|
3404
3556
|
from: retryTargets,
|
|
3405
3557
|
// retries for missing groups should not be suppressed by first-fetch dedupe
|
|
@@ -3409,6 +3561,12 @@ let DocumentIndex = (() => {
|
|
|
3409
3561
|
const promises = [];
|
|
3410
3562
|
let resultsLeft = 0;
|
|
3411
3563
|
for (const [peer, buffer] of peerBufferMap) {
|
|
3564
|
+
if (retiredRemoteIteratorPeers.has(peer)) {
|
|
3565
|
+
if (buffer.buffer.length === 0) {
|
|
3566
|
+
peerBufferMap.delete(peer);
|
|
3567
|
+
}
|
|
3568
|
+
continue;
|
|
3569
|
+
}
|
|
3412
3570
|
if (buffer.buffer.length < n) {
|
|
3413
3571
|
const hasExistingRemoteResults = buffer.kept > 0;
|
|
3414
3572
|
if (!hasExistingRemoteResults && !keepRemoteAlive) {
|
|
@@ -3503,6 +3661,7 @@ let DocumentIndex = (() => {
|
|
|
3503
3661
|
}
|
|
3504
3662
|
else {
|
|
3505
3663
|
// Fetch remotely
|
|
3664
|
+
remoteIteratorPeersToClose.add(peer);
|
|
3506
3665
|
const idTranslation = this._prefetch?.accumulator.getTranslationMap(queryRequestCoerced);
|
|
3507
3666
|
let remoteCollectRequest = collectRequest;
|
|
3508
3667
|
if (idTranslation) {
|
|
@@ -3511,97 +3670,118 @@ let DocumentIndex = (() => {
|
|
|
3511
3670
|
amount: collectRequest.amount,
|
|
3512
3671
|
});
|
|
3513
3672
|
}
|
|
3673
|
+
const remoteRequestOptions = typeof options?.remote === "object" ? options.remote : undefined;
|
|
3674
|
+
const collectSignals = [
|
|
3675
|
+
options?.signal,
|
|
3676
|
+
remoteRequestOptions?.signal,
|
|
3677
|
+
ensureController().signal,
|
|
3678
|
+
].filter((signal) => signal != null);
|
|
3679
|
+
const collectSignal = collectSignals.length === 1
|
|
3680
|
+
? collectSignals[0]
|
|
3681
|
+
: AbortSignal.any(collectSignals);
|
|
3514
3682
|
promises.push(this._query
|
|
3515
3683
|
.request(remoteCollectRequest, {
|
|
3516
3684
|
...options,
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
options.signal,
|
|
3520
|
-
ensureController().signal,
|
|
3521
|
-
])
|
|
3522
|
-
: ensureController().signal,
|
|
3685
|
+
...remoteRequestOptions,
|
|
3686
|
+
signal: collectSignal,
|
|
3523
3687
|
priority: getRemoteQueryPriority(options?.remote),
|
|
3524
3688
|
mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
|
|
3525
3689
|
})
|
|
3526
|
-
.then((response) =>
|
|
3527
|
-
.
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
return;
|
|
3690
|
+
.then((response) => {
|
|
3691
|
+
if (!response.some((result) => result.from?.hashcode() === peer)) {
|
|
3692
|
+
const missingGroups = [[peer]];
|
|
3693
|
+
if (remoteRequestOptions?.throwOnMissing) {
|
|
3694
|
+
retireRemoteIteratorPeer(peer);
|
|
3695
|
+
throw new MissingResponsesError("Did not receive responses from all shards: " +
|
|
3696
|
+
JSON.stringify(missingGroups), missingGroups);
|
|
3534
3697
|
}
|
|
3535
|
-
|
|
3698
|
+
recordMissingResponseGroups(missingGroups);
|
|
3699
|
+
return;
|
|
3700
|
+
}
|
|
3701
|
+
return introduceEntries(queryRequestCoerced, response, this.documentType, this.indexedType, this._sync, options)
|
|
3702
|
+
.then(async (responses) => {
|
|
3703
|
+
return Promise.all(responses.map(async (response, i) => {
|
|
3704
|
+
resultsLeft += Number(response.response.kept);
|
|
3705
|
+
const from = responses[i].from;
|
|
3706
|
+
if (!from) {
|
|
3707
|
+
logger.error("Missing from for sorted query");
|
|
3708
|
+
return;
|
|
3709
|
+
}
|
|
3536
3710
|
if (!keepRemoteAlive &&
|
|
3537
|
-
|
|
3538
|
-
|
|
3711
|
+
response.response.kept === 0n) {
|
|
3712
|
+
remoteIteratorPeersToClose.delete(peer);
|
|
3539
3713
|
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3714
|
+
if (response.response.results.length === 0) {
|
|
3715
|
+
if (!keepRemoteAlive &&
|
|
3716
|
+
peerBufferMap.get(peer)?.buffer.length === 0) {
|
|
3717
|
+
peerBufferMap.delete(peer); // No more results
|
|
3718
|
+
}
|
|
3545
3719
|
}
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
const existingIndexed = indexedPlaceholders?.get(indexKey);
|
|
3551
|
-
if (existingIndexed) {
|
|
3552
|
-
existingIndexed.value =
|
|
3553
|
-
result.value;
|
|
3554
|
-
existingIndexed.context = result.context;
|
|
3555
|
-
existingIndexed.from = from;
|
|
3556
|
-
existingIndexed.indexed =
|
|
3557
|
-
await this.resolveIndexed(result, response.response
|
|
3558
|
-
.results);
|
|
3559
|
-
indexedPlaceholders?.delete(indexKey);
|
|
3560
|
-
continue;
|
|
3561
|
-
}
|
|
3562
|
-
if (visited.has(indexKey) &&
|
|
3563
|
-
!evictStaleBuffered(indexKey, result.context)) {
|
|
3564
|
-
continue;
|
|
3565
|
-
}
|
|
3566
|
-
visited.add(indexKey);
|
|
3567
|
-
const indexed = await this.resolveIndexed(result, response.response
|
|
3568
|
-
.results);
|
|
3569
|
-
peerBuffer.buffer.push({
|
|
3570
|
-
value: result.value,
|
|
3571
|
-
context: result.context,
|
|
3572
|
-
from: from,
|
|
3573
|
-
indexed,
|
|
3574
|
-
});
|
|
3720
|
+
else {
|
|
3721
|
+
const peerBuffer = peerBufferMap.get(peer);
|
|
3722
|
+
if (!peerBuffer) {
|
|
3723
|
+
return;
|
|
3575
3724
|
}
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3725
|
+
peerBuffer.kept = Number(response.response.kept);
|
|
3726
|
+
for (const result of response.response.results) {
|
|
3727
|
+
const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
|
|
3728
|
+
if (isResultValue(result)) {
|
|
3729
|
+
const existingIndexed = indexedPlaceholders?.get(indexKey);
|
|
3730
|
+
if (existingIndexed) {
|
|
3731
|
+
existingIndexed.value =
|
|
3732
|
+
result.value;
|
|
3733
|
+
existingIndexed.context = result.context;
|
|
3734
|
+
existingIndexed.from = from;
|
|
3735
|
+
existingIndexed.indexed =
|
|
3736
|
+
await this.resolveIndexed(result, response.response
|
|
3737
|
+
.results);
|
|
3738
|
+
indexedPlaceholders?.delete(indexKey);
|
|
3739
|
+
continue;
|
|
3740
|
+
}
|
|
3741
|
+
if (visited.has(indexKey) &&
|
|
3742
|
+
!evictStaleBuffered(indexKey, result.context)) {
|
|
3743
|
+
continue;
|
|
3744
|
+
}
|
|
3745
|
+
visited.add(indexKey);
|
|
3746
|
+
const indexed = await this.resolveIndexed(result, response.response
|
|
3747
|
+
.results);
|
|
3748
|
+
peerBuffer.buffer.push({
|
|
3749
|
+
value: result.value,
|
|
3750
|
+
context: result.context,
|
|
3751
|
+
from: from,
|
|
3752
|
+
indexed,
|
|
3753
|
+
});
|
|
3754
|
+
}
|
|
3755
|
+
else {
|
|
3756
|
+
const indexedResult = result;
|
|
3757
|
+
if (visited.has(indexKey) &&
|
|
3758
|
+
!indexedPlaceholders?.has(indexKey) &&
|
|
3759
|
+
!evictStaleBuffered(indexKey, indexedResult.context)) {
|
|
3760
|
+
continue;
|
|
3761
|
+
}
|
|
3762
|
+
visited.add(indexKey);
|
|
3763
|
+
const indexed = coerceWithContext(indexedResult.value, indexedResult.context);
|
|
3764
|
+
const placeholder = {
|
|
3765
|
+
value: indexedResult.value,
|
|
3766
|
+
context: indexedResult.context,
|
|
3767
|
+
from: from,
|
|
3768
|
+
indexed,
|
|
3769
|
+
};
|
|
3770
|
+
peerBuffer.buffer.push(placeholder);
|
|
3771
|
+
ensureIndexedPlaceholders().set(indexKey, placeholder);
|
|
3582
3772
|
}
|
|
3583
|
-
visited.add(indexKey);
|
|
3584
|
-
const indexed = coerceWithContext(indexedResult.value, indexedResult.context);
|
|
3585
|
-
const placeholder = {
|
|
3586
|
-
value: indexedResult.value,
|
|
3587
|
-
context: indexedResult.context,
|
|
3588
|
-
from: from,
|
|
3589
|
-
indexed,
|
|
3590
|
-
};
|
|
3591
|
-
peerBuffer.buffer.push(placeholder);
|
|
3592
|
-
ensureIndexedPlaceholders().set(indexKey, placeholder);
|
|
3593
3773
|
}
|
|
3594
3774
|
}
|
|
3595
|
-
}
|
|
3596
|
-
})
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
}))
|
|
3775
|
+
}));
|
|
3776
|
+
})
|
|
3777
|
+
.catch((e) => {
|
|
3778
|
+
logger.error("Failed to collect sorted results from: " +
|
|
3779
|
+
peer +
|
|
3780
|
+
". " +
|
|
3781
|
+
e?.message);
|
|
3782
|
+
peerBufferMap.delete(peer);
|
|
3783
|
+
});
|
|
3784
|
+
}));
|
|
3605
3785
|
}
|
|
3606
3786
|
}
|
|
3607
3787
|
else {
|
|
@@ -3624,7 +3804,7 @@ let DocumentIndex = (() => {
|
|
|
3624
3804
|
}
|
|
3625
3805
|
}
|
|
3626
3806
|
}
|
|
3627
|
-
return resultsLeft === 0; // 0 results left to fetch and 0 pending results
|
|
3807
|
+
return (resultsLeft === 0 && pendingMissingResponseRetryPeers.size === 0); // 0 results left to fetch and 0 pending results
|
|
3628
3808
|
}));
|
|
3629
3809
|
};
|
|
3630
3810
|
const next = async (n) => {
|
|
@@ -3706,35 +3886,83 @@ let DocumentIndex = (() => {
|
|
|
3706
3886
|
this.processCloseIteratorRequest(queryRequestCoerced, this.node.identity.publicKey);
|
|
3707
3887
|
done = true;
|
|
3708
3888
|
};
|
|
3709
|
-
|
|
3889
|
+
const outerSignal = options?.signal;
|
|
3890
|
+
let outerAbortListener;
|
|
3891
|
+
let closeStarted = false;
|
|
3892
|
+
let closePromise;
|
|
3893
|
+
const performClose = async () => {
|
|
3894
|
+
const idTranslation = this._prefetch?.accumulator.getTranslationMap(queryRequestCoerced);
|
|
3895
|
+
const remoteIteratorIds = idTranslation
|
|
3896
|
+
? new Map(idTranslation)
|
|
3897
|
+
: undefined;
|
|
3710
3898
|
cleanupAndDone();
|
|
3711
3899
|
// Keep-open iterators can still have active remote state even when
|
|
3712
3900
|
// their pending count has already drained to zero.
|
|
3713
|
-
const closeRequest = new types.CloseIteratorRequest({
|
|
3714
|
-
id: queryRequestCoerced.id,
|
|
3715
|
-
});
|
|
3716
3901
|
const selfHash = this.node.identity.publicKey.hashcode();
|
|
3717
|
-
const
|
|
3902
|
+
const activeRemotePeers = new Set(keepRemoteAlive
|
|
3718
3903
|
? [...peerBufferMap.keys()].filter((peer) => peer !== selfHash)
|
|
3719
3904
|
: [...peerBufferMap.entries()]
|
|
3720
3905
|
.filter(([peer, buffer]) => peer !== selfHash && buffer.kept > 0)
|
|
3721
|
-
.map(([peer]) => peer);
|
|
3906
|
+
.map(([peer]) => peer));
|
|
3907
|
+
for (const peer of remoteIteratorPeersToClose) {
|
|
3908
|
+
if (peer !== selfHash) {
|
|
3909
|
+
activeRemotePeers.add(peer);
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
const staleRemoteIteratorIds = new Map([...staleRemoteIteratorIdsToClose].map(([peer, ids]) => [
|
|
3913
|
+
peer,
|
|
3914
|
+
[...ids],
|
|
3915
|
+
]));
|
|
3916
|
+
const remotePeers = new Set([
|
|
3917
|
+
...activeRemotePeers,
|
|
3918
|
+
...staleRemoteIteratorIds.keys(),
|
|
3919
|
+
]);
|
|
3722
3920
|
peerBufferMap.clear();
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3921
|
+
retiredRemoteIteratorPeers.clear();
|
|
3922
|
+
remoteIteratorPeersToClose.clear();
|
|
3923
|
+
staleRemoteIteratorIdsToClose.clear();
|
|
3924
|
+
if (remotePeers.size === 0) {
|
|
3925
|
+
return;
|
|
3926
|
+
}
|
|
3927
|
+
const remoteCloseOptions = typeof options?.remote === "object" ? options.remote : undefined;
|
|
3928
|
+
const closeSignal = AbortSignal.timeout(CLOSE_ITERATOR_REQUEST_TIMEOUT);
|
|
3929
|
+
await Promise.allSettled([...remotePeers].flatMap((peer) => {
|
|
3930
|
+
const ids = [];
|
|
3931
|
+
if (activeRemotePeers.has(peer)) {
|
|
3932
|
+
ids.push(remoteIteratorIds?.get(peer) ?? queryRequestCoerced.id);
|
|
3933
|
+
}
|
|
3934
|
+
for (const staleRemoteIteratorId of staleRemoteIteratorIds.get(peer) ?? []) {
|
|
3935
|
+
if (!ids.some((id) => equals(id, staleRemoteIteratorId))) {
|
|
3936
|
+
ids.push(staleRemoteIteratorId);
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
return ids.map((id) => {
|
|
3940
|
+
const closeRequest = new types.CloseIteratorRequest({ id });
|
|
3941
|
+
return this._query.send(closeRequest, {
|
|
3942
|
+
...remoteCloseOptions,
|
|
3943
|
+
signal: closeSignal,
|
|
3944
|
+
priority: getRemoteQueryPriority(options?.remote),
|
|
3945
|
+
mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
|
|
3946
|
+
});
|
|
3947
|
+
});
|
|
3948
|
+
}));
|
|
3949
|
+
};
|
|
3950
|
+
const close = () => {
|
|
3951
|
+
if (closeStarted)
|
|
3952
|
+
return closePromise;
|
|
3953
|
+
closeStarted = true;
|
|
3954
|
+
if (outerAbortListener) {
|
|
3955
|
+
outerSignal?.removeEventListener("abort", outerAbortListener);
|
|
3956
|
+
outerAbortListener = undefined;
|
|
3957
|
+
}
|
|
3958
|
+
closePromise = performClose();
|
|
3959
|
+
return closePromise;
|
|
3728
3960
|
};
|
|
3729
|
-
options?.signal && options.signal.addEventListener("abort", close);
|
|
3730
3961
|
let doneFn = () => {
|
|
3731
3962
|
return done;
|
|
3732
3963
|
};
|
|
3733
3964
|
let joinListener;
|
|
3734
3965
|
let fetchedFirstForRemote = undefined;
|
|
3735
|
-
const pendingMissingResponseRetryPeers = new Set();
|
|
3736
|
-
const missingResponseRetryAttempts = new Map();
|
|
3737
|
-
const maxMissingResponseRetryAttempts = 2;
|
|
3738
3966
|
let joinFetchesInFlight = 0;
|
|
3739
3967
|
let updateDeferred;
|
|
3740
3968
|
const updateWaiters = new Set();
|
|
@@ -4107,7 +4335,8 @@ let DocumentIndex = (() => {
|
|
|
4107
4335
|
continue;
|
|
4108
4336
|
}
|
|
4109
4337
|
}
|
|
4110
|
-
const
|
|
4338
|
+
const indexId = indexerTypes.toId(this.indexByResolver(indexedCandidate));
|
|
4339
|
+
const id = indexId.primitive;
|
|
4111
4340
|
const existingIndexed = indexedPlaceholders?.get(id);
|
|
4112
4341
|
if (existingIndexed) {
|
|
4113
4342
|
if (resolve) {
|
|
@@ -4149,6 +4378,7 @@ let DocumentIndex = (() => {
|
|
|
4149
4378
|
if (!resolve) {
|
|
4150
4379
|
ensureIndexedPlaceholders().set(id, placeholder);
|
|
4151
4380
|
}
|
|
4381
|
+
await this._resumableIterators.markYielded(queryRequestCoerced.idString, [indexId]);
|
|
4152
4382
|
hasRelevantChange = true;
|
|
4153
4383
|
}
|
|
4154
4384
|
}
|
|
@@ -4385,6 +4615,15 @@ let DocumentIndex = (() => {
|
|
|
4385
4615
|
}
|
|
4386
4616
|
}
|
|
4387
4617
|
};
|
|
4618
|
+
if (outerSignal) {
|
|
4619
|
+
outerAbortListener = () => {
|
|
4620
|
+
void close();
|
|
4621
|
+
};
|
|
4622
|
+
outerSignal.addEventListener("abort", outerAbortListener, { once: true });
|
|
4623
|
+
if (outerSignal.aborted) {
|
|
4624
|
+
void close();
|
|
4625
|
+
}
|
|
4626
|
+
}
|
|
4388
4627
|
return {
|
|
4389
4628
|
close,
|
|
4390
4629
|
next,
|
|
@@ -4454,49 +4693,61 @@ let DocumentIndex = (() => {
|
|
|
4454
4693
|
const drainBatchSize = replicate ? 1000 : 100;
|
|
4455
4694
|
let result = [];
|
|
4456
4695
|
let c = 0;
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4696
|
+
try {
|
|
4697
|
+
while (doneFn() !== true) {
|
|
4698
|
+
let batch = await next(drainBatchSize);
|
|
4699
|
+
c += batch.length;
|
|
4700
|
+
if (c > WARNING_WHEN_ITERATING_FOR_MORE_THAN) {
|
|
4701
|
+
warn("Iterating for more than " +
|
|
4702
|
+
WARNING_WHEN_ITERATING_FOR_MORE_THAN +
|
|
4703
|
+
" results");
|
|
4704
|
+
}
|
|
4705
|
+
if (batch.length > 0) {
|
|
4706
|
+
result.push(...batch);
|
|
4707
|
+
continue;
|
|
4708
|
+
}
|
|
4709
|
+
await waitForUpdateAndResetDeferred();
|
|
4468
4710
|
}
|
|
4469
|
-
|
|
4711
|
+
return result;
|
|
4712
|
+
}
|
|
4713
|
+
finally {
|
|
4714
|
+
await close();
|
|
4470
4715
|
}
|
|
4471
|
-
cleanupAndDone();
|
|
4472
|
-
return result;
|
|
4473
4716
|
},
|
|
4474
4717
|
first: async () => {
|
|
4475
|
-
|
|
4476
|
-
|
|
4718
|
+
try {
|
|
4719
|
+
if (doneFn()) {
|
|
4720
|
+
return undefined;
|
|
4721
|
+
}
|
|
4722
|
+
let batch = await next(1);
|
|
4723
|
+
return batch[0];
|
|
4724
|
+
}
|
|
4725
|
+
finally {
|
|
4726
|
+
await close();
|
|
4477
4727
|
}
|
|
4478
|
-
let batch = await next(1);
|
|
4479
|
-
cleanupAndDone();
|
|
4480
|
-
return batch[0];
|
|
4481
4728
|
},
|
|
4482
4729
|
[Symbol.asyncIterator]: async function* () {
|
|
4483
4730
|
drain = true;
|
|
4484
4731
|
const drainBatchSize = replicate ? 1000 : 100;
|
|
4485
4732
|
let c = 0;
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4733
|
+
try {
|
|
4734
|
+
while (doneFn() !== true) {
|
|
4735
|
+
const batch = await next(drainBatchSize);
|
|
4736
|
+
c += batch.length;
|
|
4737
|
+
if (c > WARNING_WHEN_ITERATING_FOR_MORE_THAN) {
|
|
4738
|
+
warn("Iterating for more than " +
|
|
4739
|
+
WARNING_WHEN_ITERATING_FOR_MORE_THAN +
|
|
4740
|
+
" results");
|
|
4741
|
+
}
|
|
4742
|
+
for (const entry of batch) {
|
|
4743
|
+
yield entry;
|
|
4744
|
+
}
|
|
4745
|
+
await waitForUpdateAndResetDeferred();
|
|
4496
4746
|
}
|
|
4497
|
-
await waitForUpdateAndResetDeferred();
|
|
4498
4747
|
}
|
|
4499
|
-
|
|
4748
|
+
finally {
|
|
4749
|
+
await close();
|
|
4750
|
+
}
|
|
4500
4751
|
},
|
|
4501
4752
|
};
|
|
4502
4753
|
}
|