@peerbit/document 7.1.2 → 7.1.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/benchmark/memory/child.d.ts +2 -0
- package/dist/benchmark/memory/child.d.ts.map +1 -0
- package/dist/benchmark/memory/{insert.js → child.js} +1 -2
- package/dist/benchmark/memory/child.js.map +1 -0
- package/dist/benchmark/memory/index.js +9 -50
- package/dist/benchmark/memory/index.js.map +1 -1
- package/dist/src/domain.d.ts +14 -0
- package/dist/src/domain.d.ts.map +1 -0
- package/dist/src/domain.js +33 -0
- package/dist/src/domain.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +0 -1
- package/dist/src/program.js.map +1 -1
- package/dist/src/resumable-iterator.d.ts +20 -0
- package/dist/src/resumable-iterator.d.ts.map +1 -0
- package/dist/src/resumable-iterator.js +39 -0
- package/dist/src/resumable-iterator.js.map +1 -0
- package/dist/src/search.d.ts +11 -10
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +31 -28
- package/dist/src/search.js.map +1 -1
- package/package.json +9 -9
- package/src/domain.ts +55 -0
- package/src/index.ts +1 -0
- package/src/program.ts +0 -1
- package/src/resumable-iterator.ts +58 -0
- package/src/search.ts +49 -56
- package/dist/benchmark/memory/insert.d.ts +0 -2
- package/dist/benchmark/memory/insert.d.ts.map +0 -1
- package/dist/benchmark/memory/insert.js.map +0 -1
package/src/search.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { copySerialization } from "./borsh.js";
|
|
|
26
26
|
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
27
27
|
import { type Operation, isPutOperation } from "./operation.js";
|
|
28
28
|
import type { ExtractArgs } from "./program.js";
|
|
29
|
+
import { ResumableIterators } from "./resumable-iterator.js";
|
|
29
30
|
|
|
30
31
|
const logger = loggerFn({ module: "document-index" });
|
|
31
32
|
|
|
@@ -119,7 +120,7 @@ if (!(await this.canRead(message.sender))) {
|
|
|
119
120
|
} */
|
|
120
121
|
|
|
121
122
|
export type CanSearch = (
|
|
122
|
-
request:
|
|
123
|
+
request: types.SearchRequest | types.CollectNextRequest,
|
|
123
124
|
from: PublicSignKey,
|
|
124
125
|
) => Promise<boolean> | boolean;
|
|
125
126
|
|
|
@@ -214,10 +215,7 @@ export class DocumentIndex<
|
|
|
214
215
|
D extends ReplicationDomain<any, Operation>,
|
|
215
216
|
> extends Program<OpenOptions<T, I, D>> {
|
|
216
217
|
@field({ type: RPC })
|
|
217
|
-
_query: RPC<
|
|
218
|
-
indexerTypes.AbstractSearchRequest,
|
|
219
|
-
types.AbstractSearchResult<T>
|
|
220
|
-
>;
|
|
218
|
+
_query: RPC<types.AbstractSearchRequest, types.AbstractSearchResult<T>>;
|
|
221
219
|
|
|
222
220
|
// Original document representation
|
|
223
221
|
documentType: AbstractType<T>;
|
|
@@ -236,6 +234,7 @@ export class DocumentIndex<
|
|
|
236
234
|
private indexBy: string[];
|
|
237
235
|
private indexByResolver: (obj: any) => string | Uint8Array;
|
|
238
236
|
index: indexerTypes.Index<IDocumentWithContext<I>>;
|
|
237
|
+
private _resumableIterators: ResumableIterators<IDocumentWithContext<I>>;
|
|
239
238
|
|
|
240
239
|
// Transformation, indexer
|
|
241
240
|
/* fields: IndexableFields<T, I>; */
|
|
@@ -261,10 +260,7 @@ export class DocumentIndex<
|
|
|
261
260
|
>;
|
|
262
261
|
|
|
263
262
|
constructor(properties?: {
|
|
264
|
-
query?: RPC<
|
|
265
|
-
indexerTypes.AbstractSearchRequest,
|
|
266
|
-
types.AbstractSearchResult<T>
|
|
267
|
-
>;
|
|
263
|
+
query?: RPC<types.AbstractSearchRequest, types.AbstractSearchResult<T>>;
|
|
268
264
|
}) {
|
|
269
265
|
super();
|
|
270
266
|
this._query = properties?.query || new RPC();
|
|
@@ -344,12 +340,14 @@ export class DocumentIndex<
|
|
|
344
340
|
nested: {
|
|
345
341
|
match: (obj: any): obj is types.IDocumentStore<any> =>
|
|
346
342
|
obj instanceof this.dbType,
|
|
347
|
-
|
|
343
|
+
iterate: async (obj: types.IDocumentStore<any>, query) =>
|
|
348
344
|
obj.index.search(query),
|
|
349
345
|
},
|
|
350
346
|
/* maxBatchSize: MAX_BATCH_SIZE */
|
|
351
347
|
})) || new HashmapIndex<IDocumentWithContext<I>>();
|
|
352
348
|
|
|
349
|
+
this._resumableIterators = new ResumableIterators(this.index);
|
|
350
|
+
|
|
353
351
|
await this._query.open({
|
|
354
352
|
topic: sha256Base64Sync(
|
|
355
353
|
concat([this._log.log.id, fromString("/document")]),
|
|
@@ -362,26 +360,24 @@ export class DocumentIndex<
|
|
|
362
360
|
|
|
363
361
|
if (
|
|
364
362
|
properties.canSearch &&
|
|
365
|
-
(query instanceof
|
|
366
|
-
query instanceof
|
|
363
|
+
(query instanceof types.SearchRequest ||
|
|
364
|
+
query instanceof types.CollectNextRequest) &&
|
|
367
365
|
!(await properties.canSearch(
|
|
368
|
-
query as
|
|
369
|
-
| indexerTypes.SearchRequest
|
|
370
|
-
| indexerTypes.CollectNextRequest,
|
|
366
|
+
query as types.SearchRequest | types.CollectNextRequest,
|
|
371
367
|
ctx.from,
|
|
372
368
|
))
|
|
373
369
|
) {
|
|
374
370
|
return new types.NoAccess();
|
|
375
371
|
}
|
|
376
372
|
|
|
377
|
-
if (query instanceof
|
|
373
|
+
if (query instanceof types.CloseIteratorRequest) {
|
|
378
374
|
this.processCloseIteratorRequest(query, ctx.from);
|
|
379
375
|
} else {
|
|
380
376
|
const results = await this.processQuery(
|
|
381
377
|
query as
|
|
382
|
-
|
|
|
383
|
-
|
|
|
384
|
-
|
|
|
378
|
+
| types.SearchRequest
|
|
379
|
+
| types.SearchRequest
|
|
380
|
+
| types.CollectNextRequest,
|
|
385
381
|
ctx.from,
|
|
386
382
|
false,
|
|
387
383
|
{
|
|
@@ -397,17 +393,17 @@ export class DocumentIndex<
|
|
|
397
393
|
}
|
|
398
394
|
},
|
|
399
395
|
responseType: types.AbstractSearchResult,
|
|
400
|
-
queryType:
|
|
396
|
+
queryType: types.AbstractSearchRequest,
|
|
401
397
|
});
|
|
402
398
|
}
|
|
403
399
|
|
|
404
|
-
getPending(cursorId: string): number | undefined {
|
|
400
|
+
async getPending(cursorId: string): Promise<number | undefined> {
|
|
405
401
|
const queue = this._resultQueue.get(cursorId);
|
|
406
402
|
if (queue) {
|
|
407
403
|
return queue.queue.length + queue.keptInIndex;
|
|
408
404
|
}
|
|
409
405
|
|
|
410
|
-
return this.
|
|
406
|
+
return this._resumableIterators.getPending(cursorId);
|
|
411
407
|
}
|
|
412
408
|
|
|
413
409
|
async close(from?: Program): Promise<boolean> {
|
|
@@ -472,11 +468,9 @@ export class DocumentIndex<
|
|
|
472
468
|
} else {
|
|
473
469
|
this._resolverCache.del(key.primitive);
|
|
474
470
|
}
|
|
475
|
-
return this.index.del(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}),
|
|
479
|
-
);
|
|
471
|
+
return this.index.del({
|
|
472
|
+
query: [indexerTypes.getMatcher(this.indexBy, key.key)],
|
|
473
|
+
});
|
|
480
474
|
}
|
|
481
475
|
|
|
482
476
|
public async getDetailed(
|
|
@@ -486,7 +480,7 @@ export class DocumentIndex<
|
|
|
486
480
|
let results: types.Results<T>[] | undefined;
|
|
487
481
|
if (key instanceof Uint8Array) {
|
|
488
482
|
results = await this.queryDetailed(
|
|
489
|
-
new
|
|
483
|
+
new types.SearchRequest({
|
|
490
484
|
query: [
|
|
491
485
|
new indexerTypes.ByteMatchQuery({ key: this.indexBy, value: key }),
|
|
492
486
|
],
|
|
@@ -501,7 +495,7 @@ export class DocumentIndex<
|
|
|
501
495
|
typeof indexableKey === "bigint"
|
|
502
496
|
) {
|
|
503
497
|
results = await this.queryDetailed(
|
|
504
|
-
new
|
|
498
|
+
new types.SearchRequest({
|
|
505
499
|
query: [
|
|
506
500
|
new indexerTypes.IntegerCompare({
|
|
507
501
|
key: this.indexBy,
|
|
@@ -514,7 +508,7 @@ export class DocumentIndex<
|
|
|
514
508
|
);
|
|
515
509
|
} else if (typeof indexableKey === "string") {
|
|
516
510
|
results = await this.queryDetailed(
|
|
517
|
-
new
|
|
511
|
+
new types.SearchRequest({
|
|
518
512
|
query: [
|
|
519
513
|
new indexerTypes.StringMatch({
|
|
520
514
|
key: this.indexBy,
|
|
@@ -526,7 +520,7 @@ export class DocumentIndex<
|
|
|
526
520
|
);
|
|
527
521
|
} else if (indexableKey instanceof Uint8Array) {
|
|
528
522
|
results = await this.queryDetailed(
|
|
529
|
-
new
|
|
523
|
+
new types.SearchRequest({
|
|
530
524
|
query: [
|
|
531
525
|
new indexerTypes.ByteMatchQuery({
|
|
532
526
|
key: this.indexBy,
|
|
@@ -586,7 +580,7 @@ export class DocumentIndex<
|
|
|
586
580
|
}
|
|
587
581
|
|
|
588
582
|
async processQuery(
|
|
589
|
-
query:
|
|
583
|
+
query: types.SearchRequest | types.CollectNextRequest,
|
|
590
584
|
from: PublicSignKey,
|
|
591
585
|
isLocal: boolean,
|
|
592
586
|
options?: {
|
|
@@ -605,13 +599,13 @@ export class DocumentIndex<
|
|
|
605
599
|
let indexedResult:
|
|
606
600
|
| indexerTypes.IndexedResults<IDocumentWithContext<I>>
|
|
607
601
|
| undefined = undefined;
|
|
608
|
-
if (query instanceof
|
|
609
|
-
indexedResult = await this.
|
|
610
|
-
} else if (query instanceof
|
|
602
|
+
if (query instanceof types.SearchRequest) {
|
|
603
|
+
indexedResult = await this._resumableIterators.iterateAndFetch(query);
|
|
604
|
+
} else if (query instanceof types.CollectNextRequest) {
|
|
611
605
|
indexedResult =
|
|
612
606
|
prevQueued?.keptInIndex === 0
|
|
613
|
-
?
|
|
614
|
-
: await this.
|
|
607
|
+
? []
|
|
608
|
+
: await this._resumableIterators.next(query);
|
|
615
609
|
} else {
|
|
616
610
|
throw new Error("Unsupported");
|
|
617
611
|
}
|
|
@@ -619,14 +613,16 @@ export class DocumentIndex<
|
|
|
619
613
|
let resultSize = 0;
|
|
620
614
|
|
|
621
615
|
let toIterate = prevQueued
|
|
622
|
-
? [...prevQueued.queue, ...indexedResult
|
|
623
|
-
: indexedResult
|
|
616
|
+
? [...prevQueued.queue, ...indexedResult]
|
|
617
|
+
: indexedResult;
|
|
624
618
|
|
|
625
619
|
if (prevQueued) {
|
|
626
620
|
this._resultQueue.delete(query.idString);
|
|
627
621
|
prevQueued = undefined;
|
|
628
622
|
}
|
|
629
623
|
|
|
624
|
+
let kept = (await this._resumableIterators.getPending(query.idString)) ?? 0;
|
|
625
|
+
|
|
630
626
|
if (!isLocal) {
|
|
631
627
|
prevQueued = {
|
|
632
628
|
from,
|
|
@@ -634,7 +630,7 @@ export class DocumentIndex<
|
|
|
634
630
|
timeout: setTimeout(() => {
|
|
635
631
|
this._resultQueue.delete(query.idString);
|
|
636
632
|
}, 6e4),
|
|
637
|
-
keptInIndex:
|
|
633
|
+
keptInIndex: kept,
|
|
638
634
|
};
|
|
639
635
|
this._resultQueue.set(query.idString, prevQueued);
|
|
640
636
|
}
|
|
@@ -667,7 +663,7 @@ export class DocumentIndex<
|
|
|
667
663
|
}
|
|
668
664
|
const results: types.Results<T> = new types.Results({
|
|
669
665
|
results: filteredResults,
|
|
670
|
-
kept: BigInt(
|
|
666
|
+
kept: BigInt(kept + (prevQueued?.queue.length || 0)),
|
|
671
667
|
});
|
|
672
668
|
|
|
673
669
|
if (!isLocal && results.kept === 0n) {
|
|
@@ -679,9 +675,9 @@ export class DocumentIndex<
|
|
|
679
675
|
|
|
680
676
|
clearResultsQueue(
|
|
681
677
|
query:
|
|
682
|
-
|
|
|
683
|
-
|
|
|
684
|
-
|
|
|
678
|
+
| types.SearchRequest
|
|
679
|
+
| types.CollectNextRequest
|
|
680
|
+
| types.CloseIteratorRequest,
|
|
685
681
|
) {
|
|
686
682
|
const queue = this._resultQueue.get(query.idString);
|
|
687
683
|
if (queue) {
|
|
@@ -690,7 +686,7 @@ export class DocumentIndex<
|
|
|
690
686
|
}
|
|
691
687
|
}
|
|
692
688
|
async processCloseIteratorRequest(
|
|
693
|
-
query:
|
|
689
|
+
query: types.CloseIteratorRequest,
|
|
694
690
|
publicKey: PublicSignKey,
|
|
695
691
|
): Promise<void> {
|
|
696
692
|
const queueData = this._resultQueue.get(query.idString);
|
|
@@ -699,7 +695,7 @@ export class DocumentIndex<
|
|
|
699
695
|
return;
|
|
700
696
|
}
|
|
701
697
|
this.clearResultsQueue(query);
|
|
702
|
-
return this.
|
|
698
|
+
return this._resumableIterators.close(query);
|
|
703
699
|
}
|
|
704
700
|
|
|
705
701
|
/**
|
|
@@ -709,7 +705,7 @@ export class DocumentIndex<
|
|
|
709
705
|
* @returns
|
|
710
706
|
*/
|
|
711
707
|
public async queryDetailed(
|
|
712
|
-
queryRequest:
|
|
708
|
+
queryRequest: types.SearchRequest,
|
|
713
709
|
options?: QueryDetailedOptions<T, D>,
|
|
714
710
|
): Promise<types.Results<T>[]> {
|
|
715
711
|
const local = typeof options?.local === "boolean" ? options?.local : true;
|
|
@@ -777,7 +773,7 @@ export class DocumentIndex<
|
|
|
777
773
|
}
|
|
778
774
|
};
|
|
779
775
|
try {
|
|
780
|
-
if (queryRequest instanceof
|
|
776
|
+
if (queryRequest instanceof types.CloseIteratorRequest) {
|
|
781
777
|
// don't wait for responses
|
|
782
778
|
await this._query.request(queryRequest, { mode: remote!.mode });
|
|
783
779
|
} else {
|
|
@@ -830,7 +826,7 @@ export class DocumentIndex<
|
|
|
830
826
|
* @returns
|
|
831
827
|
*/
|
|
832
828
|
public async search(
|
|
833
|
-
queryRequest:
|
|
829
|
+
queryRequest: types.SearchRequest,
|
|
834
830
|
options?: SearchOptions<T, D>,
|
|
835
831
|
): Promise<T[]> {
|
|
836
832
|
// Set fetch to search size, or max value (default to max u32 (4294967295))
|
|
@@ -841,10 +837,7 @@ export class DocumentIndex<
|
|
|
841
837
|
|
|
842
838
|
// So that this call will not do any remote requests
|
|
843
839
|
const allResults: T[] = [];
|
|
844
|
-
while (
|
|
845
|
-
iterator.done() === false &&
|
|
846
|
-
queryRequest.fetch > allResults.length
|
|
847
|
-
) {
|
|
840
|
+
while (iterator.done() !== true && queryRequest.fetch > allResults.length) {
|
|
848
841
|
// We might need to pull .next multiple time due to data message size limitations
|
|
849
842
|
for (const result of await iterator.next(
|
|
850
843
|
queryRequest.fetch - allResults.length,
|
|
@@ -866,7 +859,7 @@ export class DocumentIndex<
|
|
|
866
859
|
* @returns
|
|
867
860
|
*/
|
|
868
861
|
public iterate(
|
|
869
|
-
queryRequest:
|
|
862
|
+
queryRequest: types.SearchRequest,
|
|
870
863
|
options?: QueryOptions<T, D>,
|
|
871
864
|
): ResultsIterator<T> {
|
|
872
865
|
let fetchPromise: Promise<any> | undefined = undefined;
|
|
@@ -986,7 +979,7 @@ export class DocumentIndex<
|
|
|
986
979
|
|
|
987
980
|
// TODO buffer more than deleted?
|
|
988
981
|
// TODO batch to multiple 'to's
|
|
989
|
-
const collectRequest = new
|
|
982
|
+
const collectRequest = new types.CollectNextRequest({
|
|
990
983
|
id: queryRequest.id,
|
|
991
984
|
amount: n - buffer.buffer.length,
|
|
992
985
|
});
|
|
@@ -1179,7 +1172,7 @@ export class DocumentIndex<
|
|
|
1179
1172
|
const close = async () => {
|
|
1180
1173
|
controller.abort(new AbortError("Iterator closed"));
|
|
1181
1174
|
|
|
1182
|
-
const closeRequest = new
|
|
1175
|
+
const closeRequest = new types.CloseIteratorRequest({
|
|
1183
1176
|
id: queryRequest.id,
|
|
1184
1177
|
});
|
|
1185
1178
|
const promises: Promise<any>[] = [];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../benchmark/memory/insert.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"insert.js","sourceRoot":"","sources":["../../../benchmark/memory/insert.ts"],"names":[],"mappings":"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"}
|