@peerbit/document 9.4.3-fb47029 → 9.4.3
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 +2 -7
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +1 -2
- package/dist/src/program.js.map +1 -1
- package/dist/src/resumable-iterator.d.ts +1 -1
- package/dist/src/resumable-iterator.d.ts.map +1 -1
- package/dist/src/resumable-iterator.js +2 -10
- package/dist/src/resumable-iterator.js.map +1 -1
- package/dist/src/search.d.ts +3 -24
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +46 -209
- package/dist/src/search.js.map +1 -1
- package/package.json +74 -75
- package/src/operation.ts +9 -9
- package/src/program.ts +2 -9
- package/src/resumable-iterator.ts +2 -10
- package/src/search.ts +68 -343
- package/dist/src/most-common-query-predictor.d.ts +0 -38
- package/dist/src/most-common-query-predictor.d.ts.map +0 -1
- package/dist/src/most-common-query-predictor.js +0 -115
- package/dist/src/most-common-query-predictor.js.map +0 -1
- package/dist/src/prefetch.d.ts +0 -22
- package/dist/src/prefetch.d.ts.map +0 -1
- package/dist/src/prefetch.js +0 -47
- package/dist/src/prefetch.js.map +0 -1
- package/src/most-common-query-predictor.ts +0 -161
- package/src/prefetch.ts +0 -80
package/src/search.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
sha256Base64Sync,
|
|
9
9
|
} from "@peerbit/crypto";
|
|
10
10
|
import * as types from "@peerbit/document-interface";
|
|
11
|
-
import { CachedIndex, type QueryCacheOptions } from "@peerbit/indexer-cache";
|
|
12
11
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
13
12
|
import { HashmapIndex } from "@peerbit/indexer-simple";
|
|
14
13
|
import { BORSH_ENCODING, type Encoding, Entry } from "@peerbit/log";
|
|
@@ -26,15 +25,12 @@ import {
|
|
|
26
25
|
type ReplicationDomain,
|
|
27
26
|
SharedLog,
|
|
28
27
|
} from "@peerbit/shared-log";
|
|
29
|
-
import {
|
|
28
|
+
import { SilentDelivery } from "@peerbit/stream-interface";
|
|
30
29
|
import { AbortError, waitFor } from "@peerbit/time";
|
|
31
30
|
import { concat, fromString } from "uint8arrays";
|
|
32
31
|
import { copySerialization } from "./borsh.js";
|
|
33
32
|
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
34
|
-
import type { QueryPredictor } from "./most-common-query-predictor.js";
|
|
35
|
-
import MostCommonQueryPredictor from "./most-common-query-predictor.js";
|
|
36
33
|
import { type Operation, isPutOperation } from "./operation.js";
|
|
37
|
-
import { Prefetch } from "./prefetch.js";
|
|
38
34
|
import type { ExtractArgs } from "./program.js";
|
|
39
35
|
import { ResumableIterators } from "./resumable-iterator.js";
|
|
40
36
|
|
|
@@ -47,7 +43,7 @@ type BufferedResult<T, I extends Record<string, any>> = {
|
|
|
47
43
|
from: PublicSignKey;
|
|
48
44
|
};
|
|
49
45
|
|
|
50
|
-
export type RemoteQueryOptions<
|
|
46
|
+
export type RemoteQueryOptions<R, D> = RPCRequestAllOptions<R> & {
|
|
51
47
|
replicate?: boolean;
|
|
52
48
|
minAge?: number;
|
|
53
49
|
throwOnMissing?: boolean;
|
|
@@ -62,13 +58,7 @@ export type RemoteQueryOptions<Q, R, D> = RPCRequestAllOptions<Q, R> & {
|
|
|
62
58
|
eager?: boolean; // whether to query newly joined peers before they have matured
|
|
63
59
|
};
|
|
64
60
|
export type QueryOptions<R, D, Resolve extends boolean | undefined> = {
|
|
65
|
-
remote?:
|
|
66
|
-
| boolean
|
|
67
|
-
| RemoteQueryOptions<
|
|
68
|
-
types.AbstractSearchRequest,
|
|
69
|
-
types.AbstractSearchResult,
|
|
70
|
-
D
|
|
71
|
-
>;
|
|
61
|
+
remote?: boolean | RemoteQueryOptions<types.AbstractSearchResult, D>;
|
|
72
62
|
local?: boolean;
|
|
73
63
|
resolve?: Resolve;
|
|
74
64
|
};
|
|
@@ -151,7 +141,7 @@ const introduceEntries = async <
|
|
|
151
141
|
R extends types.SearchRequest | types.SearchRequestIndexed,
|
|
152
142
|
>(
|
|
153
143
|
queryRequest: R,
|
|
154
|
-
responses:
|
|
144
|
+
responses: RPCResponse<types.AbstractSearchResult>[],
|
|
155
145
|
documentType: AbstractType<T>,
|
|
156
146
|
indexedType: AbstractType<I>,
|
|
157
147
|
sync: (
|
|
@@ -269,19 +259,6 @@ const isTransformerWithFunction = <T, I>(
|
|
|
269
259
|
return (options as TransformerAsFunction<T, I>).transform != null;
|
|
270
260
|
};
|
|
271
261
|
|
|
272
|
-
export type PrefetchOptions = {
|
|
273
|
-
predictor?: QueryPredictor;
|
|
274
|
-
ttl: number;
|
|
275
|
-
accumulator: Prefetch;
|
|
276
|
-
|
|
277
|
-
/* When `true` we assume every peer supports prefetch routing,
|
|
278
|
-
* so it is safe to drop SearchRequests that the predictor marks
|
|
279
|
-
* as `ignore === true`.
|
|
280
|
-
*
|
|
281
|
-
* Default: `false` – be conservative.
|
|
282
|
-
*/
|
|
283
|
-
strict?: boolean;
|
|
284
|
-
};
|
|
285
262
|
export type OpenOptions<
|
|
286
263
|
T,
|
|
287
264
|
I,
|
|
@@ -304,13 +281,9 @@ export type OpenOptions<
|
|
|
304
281
|
) => Promise<void>;
|
|
305
282
|
indexBy?: string | string[];
|
|
306
283
|
transform?: TransformOptions<T, I>;
|
|
307
|
-
|
|
308
|
-
resolver?: number;
|
|
309
|
-
query?: QueryCacheOptions;
|
|
310
|
-
};
|
|
284
|
+
cacheSize?: number;
|
|
311
285
|
compatibility: 6 | 7 | 8 | undefined;
|
|
312
286
|
maybeOpen: (value: T & Program) => Promise<T & Program>;
|
|
313
|
-
prefetch?: boolean | Partial<PrefetchOptions>;
|
|
314
287
|
};
|
|
315
288
|
|
|
316
289
|
type IndexableClass<I> = new (
|
|
@@ -359,7 +332,6 @@ export class DocumentIndex<
|
|
|
359
332
|
private indexByResolver: (obj: any) => string | Uint8Array;
|
|
360
333
|
index: indexerTypes.Index<WithContext<I>>;
|
|
361
334
|
private _resumableIterators: ResumableIterators<WithContext<I>>;
|
|
362
|
-
private _prefetch?: PrefetchOptions | undefined;
|
|
363
335
|
|
|
364
336
|
compatibility: 6 | 7 | 8 | undefined;
|
|
365
337
|
|
|
@@ -379,9 +351,6 @@ export class DocumentIndex<
|
|
|
379
351
|
private _resolverCache?: Cache<T>;
|
|
380
352
|
private isProgramValued: boolean;
|
|
381
353
|
private _maybeOpen: (value: T & Program) => Promise<T & Program>;
|
|
382
|
-
private canSearch?: CanSearch;
|
|
383
|
-
private canRead?: CanRead<I>;
|
|
384
|
-
private _joinListener?: (e: { detail: PublicSignKey }) => Promise<void>;
|
|
385
354
|
|
|
386
355
|
private _resultQueue: Map<
|
|
387
356
|
string,
|
|
@@ -417,21 +386,6 @@ export class DocumentIndex<
|
|
|
417
386
|
}
|
|
418
387
|
async open(properties: OpenOptions<T, I, D>) {
|
|
419
388
|
this._log = properties.log;
|
|
420
|
-
let prefectOptions =
|
|
421
|
-
typeof properties.prefetch === "object"
|
|
422
|
-
? properties.prefetch
|
|
423
|
-
: properties.prefetch
|
|
424
|
-
? {}
|
|
425
|
-
: undefined;
|
|
426
|
-
this._prefetch = prefectOptions
|
|
427
|
-
? {
|
|
428
|
-
...prefectOptions,
|
|
429
|
-
predictor:
|
|
430
|
-
prefectOptions.predictor || new MostCommonQueryPredictor(3),
|
|
431
|
-
ttl: prefectOptions.ttl ?? 5e3,
|
|
432
|
-
accumulator: prefectOptions.accumulator || new Prefetch(),
|
|
433
|
-
}
|
|
434
|
-
: undefined;
|
|
435
389
|
|
|
436
390
|
this.documentType = properties.documentType;
|
|
437
391
|
this.indexedTypeIsDocumentType =
|
|
@@ -439,8 +393,6 @@ export class DocumentIndex<
|
|
|
439
393
|
properties.transform?.type === properties.documentType;
|
|
440
394
|
|
|
441
395
|
this.compatibility = properties.compatibility;
|
|
442
|
-
this.canRead = properties.canRead;
|
|
443
|
-
this.canSearch = properties.canSearch;
|
|
444
396
|
|
|
445
397
|
@variant(0)
|
|
446
398
|
class IndexedClassWithContext {
|
|
@@ -466,30 +418,7 @@ export class DocumentIndex<
|
|
|
466
418
|
this.isProgramValued = isSubclassOf(this.documentType, Program);
|
|
467
419
|
this.dbType = properties.dbType;
|
|
468
420
|
this._resultQueue = new Map();
|
|
469
|
-
this._sync = (request, results) =>
|
|
470
|
-
let rq: types.SearchRequest | types.SearchRequestIndexed;
|
|
471
|
-
let rs: types.Results<
|
|
472
|
-
types.ResultTypeFromRequest<
|
|
473
|
-
types.SearchRequest | types.SearchRequestIndexed,
|
|
474
|
-
T,
|
|
475
|
-
I
|
|
476
|
-
>
|
|
477
|
-
>;
|
|
478
|
-
if (request instanceof types.PredictedSearchRequest) {
|
|
479
|
-
rq = request.request;
|
|
480
|
-
rs = request.results;
|
|
481
|
-
} else {
|
|
482
|
-
rq = request;
|
|
483
|
-
rs = results as types.Results<
|
|
484
|
-
types.ResultTypeFromRequest<
|
|
485
|
-
types.SearchRequest | types.SearchRequestIndexed,
|
|
486
|
-
T,
|
|
487
|
-
I
|
|
488
|
-
>
|
|
489
|
-
>;
|
|
490
|
-
}
|
|
491
|
-
return properties.replicate(rq, rs);
|
|
492
|
-
};
|
|
421
|
+
this._sync = (request, results) => properties.replicate(request, results);
|
|
493
422
|
|
|
494
423
|
const transformOptions = properties.transform;
|
|
495
424
|
this.transformer = transformOptions
|
|
@@ -508,9 +437,9 @@ export class DocumentIndex<
|
|
|
508
437
|
this._valueEncoding = BORSH_ENCODING(this.documentType);
|
|
509
438
|
|
|
510
439
|
this._resolverCache =
|
|
511
|
-
properties.
|
|
440
|
+
properties.cacheSize === 0
|
|
512
441
|
? undefined
|
|
513
|
-
: new Cache({ max: properties.
|
|
442
|
+
: new Cache({ max: properties.cacheSize ?? 100 }); // TODO choose limit better by default (adaptive)
|
|
514
443
|
|
|
515
444
|
this.index =
|
|
516
445
|
(await (
|
|
@@ -526,10 +455,6 @@ export class DocumentIndex<
|
|
|
526
455
|
/* maxBatchSize: MAX_BATCH_SIZE */
|
|
527
456
|
})) || new HashmapIndex<WithContext<I>>();
|
|
528
457
|
|
|
529
|
-
if (properties.cache?.query) {
|
|
530
|
-
this.index = new CachedIndex(this.index, properties.cache.query);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
458
|
this._resumableIterators = new ResumableIterators(this.index);
|
|
534
459
|
this._maybeOpen = properties.maybeOpen;
|
|
535
460
|
if (this.isProgramValued) {
|
|
@@ -540,103 +465,49 @@ export class DocumentIndex<
|
|
|
540
465
|
topic: sha256Base64Sync(
|
|
541
466
|
concat([this._log.log.id, fromString("/document")]),
|
|
542
467
|
),
|
|
543
|
-
responseHandler:
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
get prefetch() {
|
|
550
|
-
return this._prefetch;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
private async queryRPCResponseHandler(
|
|
554
|
-
query: types.AbstractSearchRequest,
|
|
555
|
-
ctx: { from?: PublicSignKey; message: DataMessage },
|
|
556
|
-
) {
|
|
557
|
-
if (!ctx.from) {
|
|
558
|
-
logger.info("Receieved query without from");
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
if (query instanceof types.PredictedSearchRequest) {
|
|
562
|
-
// put results in a waiting cache so that we eventually in the future will query a matching thing, we already have results available
|
|
563
|
-
this._prefetch?.accumulator.add(
|
|
564
|
-
{
|
|
565
|
-
message: ctx.message,
|
|
566
|
-
response: query,
|
|
567
|
-
from: ctx.from,
|
|
568
|
-
},
|
|
569
|
-
ctx.from!.hashcode(),
|
|
570
|
-
);
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (
|
|
575
|
-
this.prefetch?.predictor &&
|
|
576
|
-
(query instanceof types.SearchRequest ||
|
|
577
|
-
query instanceof types.SearchRequestIndexed)
|
|
578
|
-
) {
|
|
579
|
-
const { ignore } = this.prefetch.predictor.onRequest(query, {
|
|
580
|
-
from: ctx.from!,
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
if (ignore) {
|
|
584
|
-
if (this.prefetch.strict) {
|
|
468
|
+
responseHandler: async (query, ctx) => {
|
|
469
|
+
if (!ctx.from) {
|
|
470
|
+
logger.info("Receieved query without from");
|
|
585
471
|
return;
|
|
586
472
|
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
473
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
query:
|
|
602
|
-
| types.SearchRequest
|
|
603
|
-
| types.SearchRequestIndexed
|
|
604
|
-
| types.CollectNextRequest,
|
|
605
|
-
ctx: { from: PublicSignKey },
|
|
606
|
-
) {
|
|
607
|
-
if (
|
|
608
|
-
this.canSearch &&
|
|
609
|
-
(query instanceof types.SearchRequest ||
|
|
610
|
-
query instanceof types.CollectNextRequest) &&
|
|
611
|
-
!(await this.canSearch(
|
|
612
|
-
query as types.SearchRequest | types.CollectNextRequest,
|
|
613
|
-
ctx.from,
|
|
614
|
-
))
|
|
615
|
-
) {
|
|
616
|
-
return new types.NoAccess();
|
|
617
|
-
}
|
|
474
|
+
if (
|
|
475
|
+
properties.canSearch &&
|
|
476
|
+
(query instanceof types.SearchRequest ||
|
|
477
|
+
query instanceof types.CollectNextRequest) &&
|
|
478
|
+
!(await properties.canSearch(
|
|
479
|
+
query as types.SearchRequest | types.CollectNextRequest,
|
|
480
|
+
ctx.from,
|
|
481
|
+
))
|
|
482
|
+
) {
|
|
483
|
+
return new types.NoAccess();
|
|
484
|
+
}
|
|
618
485
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
486
|
+
if (query instanceof types.CloseIteratorRequest) {
|
|
487
|
+
this.processCloseIteratorRequest(query, ctx.from);
|
|
488
|
+
} else {
|
|
489
|
+
const results = await this.processQuery(
|
|
490
|
+
query as
|
|
491
|
+
| types.SearchRequest
|
|
492
|
+
| types.SearchRequestIndexed
|
|
493
|
+
| types.CollectNextRequest,
|
|
494
|
+
ctx.from,
|
|
495
|
+
false,
|
|
496
|
+
{
|
|
497
|
+
canRead: properties.canRead,
|
|
498
|
+
},
|
|
499
|
+
);
|
|
633
500
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
501
|
+
return new types.Results({
|
|
502
|
+
// Even if results might have length 0, respond, because then we now at least there are no matching results
|
|
503
|
+
results: results.results,
|
|
504
|
+
kept: results.kept,
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
responseType: types.AbstractSearchResult,
|
|
509
|
+
queryType: types.AbstractSearchRequest,
|
|
510
|
+
});
|
|
640
511
|
}
|
|
641
512
|
|
|
642
513
|
async afterOpen(): Promise<void> {
|
|
@@ -660,35 +531,6 @@ export class DocumentIndex<
|
|
|
660
531
|
this._resolverProgramCache!.set(id.primitive, programValue.value as T);
|
|
661
532
|
}
|
|
662
533
|
}
|
|
663
|
-
|
|
664
|
-
if (this.prefetch?.predictor) {
|
|
665
|
-
const predictor = this.prefetch.predictor;
|
|
666
|
-
this._joinListener = async (e: { detail: PublicSignKey }) => {
|
|
667
|
-
// create an iterator and send the peer the results
|
|
668
|
-
let request = predictor.predictedQuery(e.detail);
|
|
669
|
-
|
|
670
|
-
if (!request) {
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
const results = await this.handleSearchRequest(request, {
|
|
674
|
-
from: e.detail,
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
if (results instanceof types.Results) {
|
|
678
|
-
// start a resumable iterator for the peer
|
|
679
|
-
const query = new types.PredictedSearchRequest({
|
|
680
|
-
id: request.id,
|
|
681
|
-
request,
|
|
682
|
-
results,
|
|
683
|
-
});
|
|
684
|
-
await this._query.send(query, {
|
|
685
|
-
mode: new SilentDelivery({ to: [e.detail], redundancy: 1 }),
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
this._query.events.addEventListener("join", this._joinListener);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
534
|
return super.afterOpen();
|
|
693
535
|
}
|
|
694
536
|
async getPending(cursorId: string): Promise<number | undefined> {
|
|
@@ -703,7 +545,6 @@ export class DocumentIndex<
|
|
|
703
545
|
async close(from?: Program): Promise<boolean> {
|
|
704
546
|
const closed = await super.close(from);
|
|
705
547
|
if (closed) {
|
|
706
|
-
this._query.events.removeEventListener("join", this._joinListener);
|
|
707
548
|
this.clearAllResultQueues();
|
|
708
549
|
await this.index.stop?.();
|
|
709
550
|
}
|
|
@@ -819,13 +660,15 @@ export class DocumentIndex<
|
|
|
819
660
|
): Promise<types.Results<RT>[] | undefined> {
|
|
820
661
|
let coercedOptions = options;
|
|
821
662
|
if (options?.remote && typeof options.remote !== "boolean") {
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
663
|
+
{
|
|
664
|
+
coercedOptions = {
|
|
665
|
+
...options,
|
|
666
|
+
remote: {
|
|
667
|
+
...options.remote,
|
|
668
|
+
strategy: options.remote?.strategy ?? "fallback",
|
|
669
|
+
},
|
|
670
|
+
};
|
|
671
|
+
}
|
|
829
672
|
} else if (options?.remote === undefined) {
|
|
830
673
|
coercedOptions = {
|
|
831
674
|
...options,
|
|
@@ -1147,10 +990,6 @@ export class DocumentIndex<
|
|
|
1147
990
|
}
|
|
1148
991
|
}
|
|
1149
992
|
|
|
1150
|
-
get countIteratorsInProgress() {
|
|
1151
|
-
return this._resumableIterators.queues.size;
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
993
|
private clearAllResultQueues() {
|
|
1155
994
|
for (const [key, queue] of this._resultQueue) {
|
|
1156
995
|
clearTimeout(queue.timeout);
|
|
@@ -1186,13 +1025,8 @@ export class DocumentIndex<
|
|
|
1186
1025
|
options?: QueryDetailedOptions<T, D, boolean | undefined>,
|
|
1187
1026
|
): Promise<types.Results<RT>[]> {
|
|
1188
1027
|
const local = typeof options?.local === "boolean" ? options?.local : true;
|
|
1189
|
-
let remote:
|
|
1190
|
-
|
|
1191
|
-
types.AbstractSearchRequest,
|
|
1192
|
-
types.AbstractSearchResult,
|
|
1193
|
-
D
|
|
1194
|
-
>
|
|
1195
|
-
| undefined = undefined;
|
|
1028
|
+
let remote: RemoteQueryOptions<types.AbstractSearchResult, D> | undefined =
|
|
1029
|
+
undefined;
|
|
1196
1030
|
if (typeof options?.remote === "boolean") {
|
|
1197
1031
|
if (options?.remote) {
|
|
1198
1032
|
remote = {};
|
|
@@ -1232,11 +1066,6 @@ export class DocumentIndex<
|
|
|
1232
1066
|
|
|
1233
1067
|
let resolved: types.Results<types.ResultTypeFromRequest<R, T, I>>[] = [];
|
|
1234
1068
|
if (remote && (remote.strategy !== "fallback" || allResults.length === 0)) {
|
|
1235
|
-
if (queryRequest instanceof types.CloseIteratorRequest) {
|
|
1236
|
-
// don't wait for responses
|
|
1237
|
-
throw new Error("Unexpected");
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
1069
|
const replicatorGroups = await this._log.getCover(
|
|
1241
1070
|
remote.domain ?? { args: undefined },
|
|
1242
1071
|
{
|
|
@@ -1246,11 +1075,9 @@ export class DocumentIndex<
|
|
|
1246
1075
|
);
|
|
1247
1076
|
|
|
1248
1077
|
if (replicatorGroups) {
|
|
1078
|
+
const groupHashes: string[][] = replicatorGroups.map((x) => [x]);
|
|
1249
1079
|
const responseHandler = async (
|
|
1250
|
-
results:
|
|
1251
|
-
response: types.AbstractSearchResult;
|
|
1252
|
-
from?: PublicSignKey;
|
|
1253
|
-
}[],
|
|
1080
|
+
results: RPCResponse<types.AbstractSearchResult>[],
|
|
1254
1081
|
) => {
|
|
1255
1082
|
const resultInitialized = await introduceEntries(
|
|
1256
1083
|
queryRequest,
|
|
@@ -1264,105 +1091,19 @@ export class DocumentIndex<
|
|
|
1264
1091
|
resolved.push(r.response);
|
|
1265
1092
|
}
|
|
1266
1093
|
};
|
|
1267
|
-
|
|
1268
|
-
let extraPromises: Promise<void>[] | undefined = undefined;
|
|
1269
|
-
|
|
1270
|
-
const groupHashes: string[][] = replicatorGroups
|
|
1271
|
-
.filter((hash) => {
|
|
1272
|
-
if (hash === this.node.identity.publicKey.hashcode()) {
|
|
1273
|
-
return false;
|
|
1274
|
-
}
|
|
1275
|
-
const resultAlready = this._prefetch?.accumulator.consume(
|
|
1276
|
-
queryRequest,
|
|
1277
|
-
hash,
|
|
1278
|
-
);
|
|
1279
|
-
if (resultAlready) {
|
|
1280
|
-
(extraPromises || (extraPromises = [])).push(
|
|
1281
|
-
(async () => {
|
|
1282
|
-
let from = await this.node.services.pubsub.getPublicKey(hash);
|
|
1283
|
-
if (from) {
|
|
1284
|
-
return responseHandler([
|
|
1285
|
-
{
|
|
1286
|
-
response: resultAlready.response.results,
|
|
1287
|
-
from,
|
|
1288
|
-
},
|
|
1289
|
-
]);
|
|
1290
|
-
}
|
|
1291
|
-
})(),
|
|
1292
|
-
);
|
|
1293
|
-
return false;
|
|
1294
|
-
}
|
|
1295
|
-
return true;
|
|
1296
|
-
})
|
|
1297
|
-
.map((x) => [x]);
|
|
1298
|
-
|
|
1299
|
-
extraPromises && (await Promise.all(extraPromises));
|
|
1300
|
-
let tearDown: (() => void) | undefined = undefined;
|
|
1301
|
-
const search = this;
|
|
1302
|
-
|
|
1303
1094
|
try {
|
|
1304
|
-
|
|
1305
|
-
|
|
1095
|
+
if (queryRequest instanceof types.CloseIteratorRequest) {
|
|
1096
|
+
// don't wait for responses
|
|
1097
|
+
await this._query.request(queryRequest, { mode: remote!.mode });
|
|
1098
|
+
} else {
|
|
1099
|
+
await queryAll(
|
|
1306
1100
|
this._query,
|
|
1307
1101
|
groupHashes,
|
|
1308
1102
|
queryRequest,
|
|
1309
1103
|
responseHandler,
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
responseInterceptor(fn) {
|
|
1314
|
-
const listener = (evt: {
|
|
1315
|
-
detail: {
|
|
1316
|
-
consumable: RPCResponse<
|
|
1317
|
-
types.PredictedSearchRequest<any>
|
|
1318
|
-
>;
|
|
1319
|
-
};
|
|
1320
|
-
}) => {
|
|
1321
|
-
const consumable =
|
|
1322
|
-
search._prefetch?.accumulator.consume(
|
|
1323
|
-
queryRequest,
|
|
1324
|
-
evt.detail.consumable.from!.hashcode(),
|
|
1325
|
-
);
|
|
1326
|
-
|
|
1327
|
-
if (consumable) {
|
|
1328
|
-
fn({
|
|
1329
|
-
message: consumable.message,
|
|
1330
|
-
response: consumable.response.results,
|
|
1331
|
-
from: consumable.from,
|
|
1332
|
-
});
|
|
1333
|
-
}
|
|
1334
|
-
};
|
|
1335
|
-
|
|
1336
|
-
for (const groups of groupHashes) {
|
|
1337
|
-
for (const hash of groups) {
|
|
1338
|
-
const consumable =
|
|
1339
|
-
search._prefetch?.accumulator.consume(
|
|
1340
|
-
queryRequest,
|
|
1341
|
-
hash,
|
|
1342
|
-
);
|
|
1343
|
-
if (consumable) {
|
|
1344
|
-
fn({
|
|
1345
|
-
message: consumable.message,
|
|
1346
|
-
response: consumable.response.results,
|
|
1347
|
-
from: consumable.from,
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
search.prefetch?.accumulator.addEventListener(
|
|
1353
|
-
"add",
|
|
1354
|
-
listener,
|
|
1355
|
-
);
|
|
1356
|
-
tearDown = () => {
|
|
1357
|
-
search.prefetch?.accumulator.removeEventListener(
|
|
1358
|
-
"add",
|
|
1359
|
-
listener,
|
|
1360
|
-
);
|
|
1361
|
-
};
|
|
1362
|
-
},
|
|
1363
|
-
}
|
|
1364
|
-
: remote,
|
|
1365
|
-
));
|
|
1104
|
+
remote,
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1366
1107
|
} catch (error) {
|
|
1367
1108
|
if (error instanceof MissingResponsesError) {
|
|
1368
1109
|
logger.warn("Did not reciveve responses from all shard");
|
|
@@ -1372,8 +1113,6 @@ export class DocumentIndex<
|
|
|
1372
1113
|
} else {
|
|
1373
1114
|
throw error;
|
|
1374
1115
|
}
|
|
1375
|
-
} finally {
|
|
1376
|
-
tearDown && (tearDown as any)();
|
|
1377
1116
|
}
|
|
1378
1117
|
} else {
|
|
1379
1118
|
// TODO send without direction out to the world? or just assume we can insert?
|
|
@@ -1661,7 +1400,6 @@ export class DocumentIndex<
|
|
|
1661
1400
|
|
|
1662
1401
|
// TODO buffer more than deleted?
|
|
1663
1402
|
// TODO batch to multiple 'to's
|
|
1664
|
-
|
|
1665
1403
|
const collectRequest = new types.CollectNextRequest({
|
|
1666
1404
|
id: queryRequestCoerced.id,
|
|
1667
1405
|
amount: n - buffer.buffer.length,
|
|
@@ -1726,21 +1464,9 @@ export class DocumentIndex<
|
|
|
1726
1464
|
);
|
|
1727
1465
|
} else {
|
|
1728
1466
|
// Fetch remotely
|
|
1729
|
-
const idTranslation =
|
|
1730
|
-
this._prefetch?.accumulator.getTranslationMap(
|
|
1731
|
-
queryRequestCoerced,
|
|
1732
|
-
);
|
|
1733
|
-
let remoteCollectRequest: types.CollectNextRequest = collectRequest;
|
|
1734
|
-
if (idTranslation) {
|
|
1735
|
-
remoteCollectRequest = new types.CollectNextRequest({
|
|
1736
|
-
id: idTranslation.get(peer) || collectRequest.id,
|
|
1737
|
-
amount: collectRequest.amount,
|
|
1738
|
-
});
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
1467
|
promises.push(
|
|
1742
1468
|
this._query
|
|
1743
|
-
.request(
|
|
1469
|
+
.request(collectRequest, {
|
|
1744
1470
|
...options,
|
|
1745
1471
|
signal: controller.signal,
|
|
1746
1472
|
priority: 1,
|
|
@@ -1901,7 +1627,6 @@ export class DocumentIndex<
|
|
|
1901
1627
|
const closeRequest = new types.CloseIteratorRequest({
|
|
1902
1628
|
id: queryRequestCoerced.id,
|
|
1903
1629
|
});
|
|
1904
|
-
this.prefetch?.accumulator.clear(queryRequestCoerced);
|
|
1905
1630
|
const promises: Promise<any>[] = [];
|
|
1906
1631
|
for (const [peer, buffer] of peerBufferMap) {
|
|
1907
1632
|
if (buffer.kept === 0) {
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { type PublicSignKey } from "@peerbit/crypto";
|
|
2
|
-
import type * as types from "@peerbit/document-interface";
|
|
3
|
-
export declare const idAgnosticQueryKey: (query: types.SearchRequest | types.SearchRequestIndexed) => string;
|
|
4
|
-
export interface QueryPredictor {
|
|
5
|
-
onRequest: (request: types.SearchRequest | types.SearchRequestIndexed, ctx: {
|
|
6
|
-
from: PublicSignKey;
|
|
7
|
-
}) => {
|
|
8
|
-
ignore: boolean;
|
|
9
|
-
};
|
|
10
|
-
predictedQuery: (from: PublicSignKey) => types.SearchRequest | types.SearchRequestIndexed | undefined;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Learns the most common recent queries and predicts the most frequent one.
|
|
14
|
-
* If we just pre-empted a peer with some query, the *first* matching request
|
|
15
|
-
* that arrives from that peer within `ignoreWindow` ms is ignored.
|
|
16
|
-
*/
|
|
17
|
-
export default class MostCommonQueryPredictor implements QueryPredictor {
|
|
18
|
-
private readonly threshold;
|
|
19
|
-
private readonly ttl;
|
|
20
|
-
private readonly ignoreWindow;
|
|
21
|
-
private readonly queries;
|
|
22
|
-
/**
|
|
23
|
-
* predicted:
|
|
24
|
-
* requestKey → Map<peerHash, timestamp>
|
|
25
|
-
*/
|
|
26
|
-
private readonly predicted;
|
|
27
|
-
constructor(threshold: number, ttl?: number, // 10 min
|
|
28
|
-
ignoreWindow?: number);
|
|
29
|
-
private cleanupQueries;
|
|
30
|
-
private cleanupPredictions;
|
|
31
|
-
onRequest(request: types.SearchRequest | types.SearchRequestIndexed, { from }: {
|
|
32
|
-
from: PublicSignKey;
|
|
33
|
-
}): {
|
|
34
|
-
ignore: boolean;
|
|
35
|
-
};
|
|
36
|
-
predictedQuery(from: PublicSignKey): types.SearchRequest | types.SearchRequestIndexed | undefined;
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=most-common-query-predictor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"most-common-query-predictor.d.ts","sourceRoot":"","sources":["../../src/most-common-query-predictor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,KAAK,KAAK,MAAM,6BAA6B,CAAC;AAc1D,eAAO,MAAM,kBAAkB,GAC9B,OAAO,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,oBAAoB,WACX,CAAC;AAI9C,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,CACV,OAAO,EAAE,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,oBAAoB,EACzD,GAAG,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,KACxB;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAEzB,cAAc,EAAE,CACf,IAAI,EAAE,aAAa,KACf,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,oBAAoB,GAAG,SAAS,CAAC;CAClE;AASD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAyB,YAAW,cAAc;IAUrE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAX9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IAEzD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;gBAGlD,SAAS,EAAE,MAAM,EACjB,GAAG,SAAiB,EAAE,SAAS;IAC/B,YAAY,SAAQ;IAItC,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,kBAAkB;IAe1B,SAAS,CACR,OAAO,EAAE,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,oBAAoB,EACzD,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,GAC/B;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE;IAsCtB,cAAc,CACb,IAAI,EAAE,aAAa,GACjB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,oBAAoB,GAAG,SAAS;CAiC/D"}
|