@peerbit/document 6.0.7-aa577a5 → 6.0.7-cccc078

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.
Files changed (37) hide show
  1. package/dist/benchmark/index.js +13 -14
  2. package/dist/benchmark/index.js.map +1 -1
  3. package/dist/benchmark/memory/index.d.ts +2 -0
  4. package/dist/benchmark/memory/index.d.ts.map +1 -0
  5. package/dist/benchmark/memory/index.js +122 -0
  6. package/dist/benchmark/memory/index.js.map +1 -0
  7. package/dist/benchmark/memory/insert.d.ts +2 -0
  8. package/dist/benchmark/memory/insert.d.ts.map +1 -0
  9. package/dist/benchmark/memory/insert.js +133 -0
  10. package/dist/benchmark/memory/insert.js.map +1 -0
  11. package/dist/benchmark/memory/utils.d.ts +13 -0
  12. package/dist/benchmark/memory/utils.d.ts.map +1 -0
  13. package/dist/benchmark/memory/utils.js +2 -0
  14. package/dist/benchmark/memory/utils.js.map +1 -0
  15. package/dist/benchmark/replication.js +27 -29
  16. package/dist/benchmark/replication.js.map +1 -1
  17. package/dist/src/borsh.d.ts +2 -0
  18. package/dist/src/borsh.d.ts.map +1 -0
  19. package/dist/src/borsh.js +16 -0
  20. package/dist/src/borsh.js.map +1 -0
  21. package/dist/src/index.d.ts +0 -1
  22. package/dist/src/index.d.ts.map +1 -1
  23. package/dist/src/index.js +0 -1
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/program.d.ts +16 -19
  26. package/dist/src/program.d.ts.map +1 -1
  27. package/dist/src/program.js +57 -68
  28. package/dist/src/program.js.map +1 -1
  29. package/dist/src/search.d.ts +46 -32
  30. package/dist/src/search.d.ts.map +1 -1
  31. package/dist/src/search.js +236 -133
  32. package/dist/src/search.js.map +1 -1
  33. package/package.json +16 -11
  34. package/src/borsh.ts +19 -0
  35. package/src/index.ts +0 -1
  36. package/src/program.ts +118 -118
  37. package/src/search.ts +438 -218
@@ -8,18 +8,20 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { field, serialize, variant } from "@dao-xyz/borsh";
11
- import { BORSH_ENCODING, Entry } from "@peerbit/log";
12
- import { Program } from "@peerbit/program";
11
+ import { Cache } from "@peerbit/cache";
12
+ import { PublicSignKey, sha256Base64Sync, } from "@peerbit/crypto";
13
13
  import * as types from "@peerbit/document-interface";
14
- import { RPC, queryAll, MissingResponsesError } from "@peerbit/rpc";
14
+ import * as indexerTypes from "@peerbit/indexer-interface";
15
+ import { HashmapIndex } from "@peerbit/indexer-simple";
16
+ import { BORSH_ENCODING, Entry } from "@peerbit/log";
15
17
  import { logger as loggerFn } from "@peerbit/logger";
16
- import { PublicSignKey, sha256Base64Sync } from "@peerbit/crypto";
18
+ import { Program } from "@peerbit/program";
19
+ import { MissingResponsesError, RPC, queryAll, } from "@peerbit/rpc";
17
20
  import { SharedLog } from "@peerbit/shared-log";
18
- import { concat, fromString } from "uint8arrays";
19
21
  import { SilentDelivery } from "@peerbit/stream-interface";
20
22
  import { AbortError } from "@peerbit/time";
21
- import { Cache } from "@peerbit/cache";
22
- import { HashmapIndexEngine } from "@peerbit/document-index-simple";
23
+ import { concat, fromString } from "uint8arrays";
24
+ import { copySerialization } from "./borsh.js";
23
25
  import { MAX_BATCH_SIZE } from "./constants.js";
24
26
  const logger = loggerFn({ module: "document-index" });
25
27
  let Operation = class Operation /* <T> */ {
@@ -37,10 +39,7 @@ let PutOperation = class PutOperation extends Operation /* <T> */ {
37
39
  /* _value?: T; */
38
40
  constructor(props) {
39
41
  super();
40
- if (props) {
41
- this.data = props.data;
42
- /* this._value = props.value; */
43
- }
42
+ this.data = props.data;
44
43
  }
45
44
  };
46
45
  __decorate([
@@ -76,8 +75,8 @@ let DeleteOperation = class DeleteOperation extends Operation {
76
75
  }
77
76
  };
78
77
  __decorate([
79
- field({ type: types.IdKey }),
80
- __metadata("design:type", types.IdKey)
78
+ field({ type: indexerTypes.IdKey }),
79
+ __metadata("design:type", indexerTypes.IdKey)
81
80
  ], DeleteOperation.prototype, "key", void 0);
82
81
  DeleteOperation = __decorate([
83
82
  variant(2),
@@ -112,33 +111,44 @@ const dedup = (allResult, dedupBy) => {
112
111
  const unique = new Set();
113
112
  const dedup = [];
114
113
  for (const result of allResult) {
115
- const key = types.toIdeable(dedupBy(result));
116
- if (unique.has(key)) {
114
+ const key = indexerTypes.toId(dedupBy(result));
115
+ const primitive = key.primitive;
116
+ if (unique.has(primitive)) {
117
117
  continue;
118
118
  }
119
- unique.add(key);
119
+ unique.add(primitive);
120
120
  dedup.push(result);
121
121
  }
122
122
  return dedup;
123
123
  };
124
124
  const DEFAULT_INDEX_BY = "id";
125
+ const isTransformerWithFunction = (options) => {
126
+ return options.transform != null;
127
+ };
125
128
  let DocumentIndex = class DocumentIndex extends Program {
126
129
  _query;
127
- engine;
128
- type;
130
+ // Original document representation
131
+ documentType;
132
+ // transform options
133
+ transformer;
134
+ // The indexed document wrapped in a context
135
+ wrappedIndexedType;
136
+ // The database type, for recursive indexing
129
137
  dbType;
138
+ indexedTypeIsDocumentType;
130
139
  // Index key
131
140
  indexBy;
132
- indexByArr;
133
141
  indexByResolver;
142
+ index;
134
143
  // Transformation, indexer
135
- fields;
144
+ /* fields: IndexableFields<T, I>; */
136
145
  _valueEncoding;
137
146
  _sync;
138
147
  _log;
139
148
  _resolverProgramCache;
140
149
  _resolverCache;
141
150
  _isProgramValues;
151
+ _resultQueue;
142
152
  constructor(properties) {
143
153
  super();
144
154
  this._query = properties?.query || new RPC();
@@ -148,35 +158,55 @@ let DocumentIndex = class DocumentIndex extends Program {
148
158
  }
149
159
  async open(properties) {
150
160
  this._log = properties.log;
151
- this.type = properties.type;
161
+ this.documentType = properties.documentType;
162
+ this.indexedTypeIsDocumentType =
163
+ !properties.transform?.type ||
164
+ properties.transform?.type === properties.documentType;
165
+ class IndexedClassWithContex {
166
+ __context;
167
+ constructor(value, context) {
168
+ Object.assign(this, value);
169
+ this.__context = context;
170
+ }
171
+ }
172
+ __decorate([
173
+ field({ type: types.Context }),
174
+ __metadata("design:type", types.Context)
175
+ ], IndexedClassWithContex.prototype, "__context", void 0);
176
+ // copy all prototype values from indexedType to IndexedClassWithContex
177
+ copySerialization((properties.transform?.type || properties.documentType), IndexedClassWithContex);
178
+ this.wrappedIndexedType = IndexedClassWithContex;
152
179
  // if this.type is a class that extends Program we want to do special functionality
153
- this._isProgramValues = this.type instanceof Program;
180
+ this._isProgramValues = this.documentType instanceof Program;
154
181
  this.dbType = properties.dbType;
182
+ this._resultQueue = new Map();
155
183
  this._sync = properties.sync;
156
- this.fields = properties.fields;
157
- this.indexBy = properties.indexBy || DEFAULT_INDEX_BY;
158
- this.indexByArr = Array.isArray(this.indexBy)
159
- ? this.indexBy
160
- : [this.indexBy];
161
- this.indexByResolver =
162
- typeof this.indexBy === "string"
163
- ? (obj) => obj[this.indexBy]
164
- : (obj) => types.extractFieldValue(obj, this.indexBy);
165
- this._valueEncoding = BORSH_ENCODING(this.type);
184
+ const transformOptions = properties.transform;
185
+ this.transformer = transformOptions
186
+ ? isTransformerWithFunction(transformOptions)
187
+ ? (obj, context) => transformOptions.transform(obj, context)
188
+ : transformOptions.type
189
+ ? (obj, context) => new transformOptions.type(obj, context)
190
+ : (obj) => obj
191
+ : (obj) => obj; // TODO types
192
+ const maybeArr = properties.indexBy || DEFAULT_INDEX_BY;
193
+ this.indexBy = Array.isArray(maybeArr) ? maybeArr : [maybeArr];
194
+ this.indexByResolver = (obj) => indexerTypes.extractFieldValue(obj, this.indexBy);
195
+ this._valueEncoding = BORSH_ENCODING(this.documentType);
166
196
  if (this._isProgramValues) {
167
197
  this._resolverProgramCache = new Map();
168
198
  }
169
- this._resolverCache = new Cache({ max: 1000 }); // TODO choose limit better (adaptive)
170
- this.engine = properties.engine || new HashmapIndexEngine();
171
- await this.engine.init({
172
- indexBy: this.indexBy,
173
- nested: {
174
- match: (obj) => obj instanceof this.dbType,
175
- query: async (obj, query) => obj.index.search(query)
176
- },
177
- maxBatchSize: MAX_BATCH_SIZE
178
- });
179
- await this.engine.start?.();
199
+ this._resolverCache = new Cache({ max: 10 }); // TODO choose limit better (adaptive)
200
+ this.index =
201
+ (await (await this.node.indexer.scope(sha256Base64Sync(concat([this._log.log.id, fromString("/document-index")])))).init({
202
+ indexBy: this.indexBy,
203
+ schema: this.wrappedIndexedType,
204
+ nested: {
205
+ match: (obj) => obj instanceof this.dbType,
206
+ query: async (obj, query) => obj.index.search(query),
207
+ },
208
+ /* maxBatchSize: MAX_BATCH_SIZE */
209
+ })) || new HashmapIndex();
180
210
  await this._query.open({
181
211
  topic: sha256Base64Sync(concat([this._log.log.id, fromString("/document")])),
182
212
  responseHandler: async (query, ctx) => {
@@ -185,45 +215,53 @@ let DocumentIndex = class DocumentIndex extends Program {
185
215
  return;
186
216
  }
187
217
  if (properties.canSearch &&
188
- (query instanceof types.SearchRequest ||
189
- query instanceof types.CollectNextRequest) &&
218
+ (query instanceof indexerTypes.SearchRequest ||
219
+ query instanceof indexerTypes.CollectNextRequest) &&
190
220
  !(await properties.canSearch(query, ctx.from))) {
191
221
  return new types.NoAccess();
192
222
  }
193
- if (query instanceof types.CloseIteratorRequest) {
223
+ if (query instanceof indexerTypes.CloseIteratorRequest) {
194
224
  this.processCloseIteratorRequest(query, ctx.from);
195
225
  }
196
226
  else {
197
- const results = await this.processQuery(query, ctx.from, {
198
- canRead: properties.canRead
227
+ const results = await this.processQuery(query, ctx.from, false, {
228
+ canRead: properties.canRead,
199
229
  });
200
230
  return new types.Results({
201
231
  // Even if results might have length 0, respond, because then we now at least there are no matching results
202
232
  results: results.results,
203
- kept: results.kept
233
+ kept: results.kept,
204
234
  });
205
235
  }
206
236
  },
207
237
  responseType: types.AbstractSearchResult,
208
- queryType: types.AbstractSearchRequest
238
+ queryType: indexerTypes.AbstractSearchRequest,
209
239
  });
210
240
  }
241
+ getPending(cursorId) {
242
+ const queue = this._resultQueue.get(cursorId);
243
+ if (queue) {
244
+ return queue.queue.length + queue.keptInIndex;
245
+ }
246
+ return this.index.getPending(cursorId);
247
+ }
211
248
  async close(from) {
212
249
  const closed = await super.close(from);
213
250
  if (closed) {
214
- await this.engine.stop?.();
251
+ await this.index.stop?.();
215
252
  }
216
253
  return closed;
217
254
  }
218
255
  async drop(from) {
219
- const closed = await super.drop(from);
220
- if (closed) {
221
- await this.engine.stop?.();
256
+ const dropped = await super.drop(from);
257
+ if (dropped) {
258
+ await this.index.drop?.();
259
+ await this.index.stop?.();
222
260
  }
223
- return closed;
261
+ return dropped;
224
262
  }
225
263
  async get(key, options) {
226
- return (await this.getDetailed(key instanceof types.IdKey ? key : types.toId(key), options))?.[0]?.results[0]?.value;
264
+ return (await this.getDetailed(key instanceof indexerTypes.IdKey ? key : indexerTypes.toId(key), options))?.[0]?.results[0]?.value;
227
265
  }
228
266
  async put(value, entry, id) {
229
267
  const idString = id.primitive;
@@ -233,73 +271,78 @@ let DocumentIndex = class DocumentIndex extends Program {
233
271
  else {
234
272
  this._resolverCache.add(idString, value);
235
273
  }
274
+ const existing = await this.index.get(id);
236
275
  const context = new types.Context({
237
- created: (await this.engine.get(id))?.context.created ||
276
+ created: existing?.value.__context.created ||
238
277
  entry.meta.clock.timestamp.wallTime,
239
278
  modified: entry.meta.clock.timestamp.wallTime,
240
279
  head: entry.hash,
241
- gid: entry.gid
242
- });
243
- const valueToIndex = await this.fields(value, context);
244
- this.engine.put({
245
- id,
246
- indexed: valueToIndex,
247
- context,
248
- size: entry.payload.data.byteLength
249
- /* reference:
250
- valueToIndex === value || value instanceof Program
251
- ? { value }
252
- : undefined */
280
+ gid: entry.gid,
281
+ size: entry.payloadByteLength,
253
282
  });
283
+ const valueToIndex = await this.transformer(value, context);
284
+ const wrappedValueToIndex = new this.wrappedIndexedType(valueToIndex, context);
285
+ await this.index.put(wrappedValueToIndex);
254
286
  }
255
287
  del(key) {
256
- const keyObject = types.toId(key);
257
288
  if (this._isProgramValues) {
258
- this._resolverProgramCache.delete(key);
289
+ this._resolverProgramCache.delete(key.primitive);
259
290
  }
260
291
  else {
261
- this._resolverCache.del(key);
292
+ this._resolverCache.del(key.primitive);
262
293
  }
263
- return this.engine.del(keyObject);
294
+ return this.index.del(new indexerTypes.DeleteRequest({
295
+ query: [indexerTypes.getMatcher(this.indexBy, key.key)],
296
+ }));
264
297
  }
265
298
  async getDetailed(key, options) {
266
299
  let results;
267
300
  if (key instanceof Uint8Array) {
268
- results = await this.queryDetailed(new types.SearchRequest({
301
+ results = await this.queryDetailed(new indexerTypes.SearchRequest({
269
302
  query: [
270
- new types.ByteMatchQuery({ key: this.indexByArr, value: key })
271
- ]
303
+ new indexerTypes.ByteMatchQuery({ key: this.indexBy, value: key }),
304
+ ],
272
305
  }), options);
273
306
  }
274
307
  else {
275
- const indexableKey = types.toIdeable(key);
308
+ const indexableKey = indexerTypes.toIdeable(key);
276
309
  if (typeof indexableKey === "number" ||
277
310
  typeof indexableKey === "bigint") {
278
- results = await this.queryDetailed(new types.SearchRequest({
311
+ results = await this.queryDetailed(new indexerTypes.SearchRequest({
279
312
  query: [
280
- new types.IntegerCompare({
281
- key: this.indexByArr,
282
- compare: types.Compare.Equal,
283
- value: indexableKey
284
- })
285
- ]
313
+ new indexerTypes.IntegerCompare({
314
+ key: this.indexBy,
315
+ compare: indexerTypes.Compare.Equal,
316
+ value: indexableKey,
317
+ }),
318
+ ],
286
319
  }), options);
287
320
  }
288
- else {
289
- results = await this.queryDetailed(new types.SearchRequest({
321
+ else if (typeof indexableKey === "string") {
322
+ results = await this.queryDetailed(new indexerTypes.SearchRequest({
290
323
  query: [
291
- new types.StringMatch({
292
- key: this.indexByArr,
293
- value: indexableKey
294
- })
295
- ]
324
+ new indexerTypes.StringMatch({
325
+ key: this.indexBy,
326
+ value: indexableKey,
327
+ }),
328
+ ],
329
+ }), options);
330
+ }
331
+ else if (indexableKey instanceof Uint8Array) {
332
+ results = await this.queryDetailed(new indexerTypes.SearchRequest({
333
+ query: [
334
+ new indexerTypes.ByteMatchQuery({
335
+ key: this.indexBy,
336
+ value: indexableKey,
337
+ }),
338
+ ],
296
339
  }), options);
297
340
  }
298
341
  }
299
342
  return results;
300
343
  }
301
344
  getSize() {
302
- return this.engine.getSize();
345
+ return this.index.getSize();
303
346
  }
304
347
  async resolveDocument(value) {
305
348
  const cached = this._resolverCache.get(value.id.primitive) ||
@@ -307,10 +350,13 @@ let DocumentIndex = class DocumentIndex extends Program {
307
350
  if (cached != null) {
308
351
  return { value: cached };
309
352
  }
310
- if (value.indexed instanceof this.type) {
311
- return { value: value.indexed };
353
+ if (this.indexedTypeIsDocumentType) {
354
+ // cast value to T, i.e. convert the class but keep all properties except the __context
355
+ const obj = Object.assign(Object.create(this.documentType.prototype), value.value);
356
+ delete obj.__context;
357
+ return { value: obj };
312
358
  }
313
- const head = await await this._log.log.get(value.context.head);
359
+ const head = await this._log.log.get(value.value.__context.head);
314
360
  if (!head) {
315
361
  return undefined; // we could end up here if we recently pruned the document and other peers never persisted the entry
316
362
  // TODO update changes in index before removing entries from log entry storage
@@ -318,47 +364,98 @@ let DocumentIndex = class DocumentIndex extends Program {
318
364
  const payloadValue = await head.getPayloadValue();
319
365
  if (payloadValue instanceof PutOperation) {
320
366
  return {
321
- value: this.valueEncoding.decoder(payloadValue.data)
367
+ value: this.valueEncoding.decoder(payloadValue.data),
322
368
  /* size: payloadValue.data.byteLength */
323
369
  };
324
370
  }
325
371
  throw new Error("Unexpected value type when getting document: " +
326
372
  payloadValue?.constructor?.name || typeof payloadValue);
327
373
  }
328
- async processQuery(query, from, options) {
374
+ async processQuery(query, from, isLocal, options) {
329
375
  // We do special case for querying the id as we can do it faster than iterating
376
+ let prevQueued = isLocal
377
+ ? undefined
378
+ : this._resultQueue.get(query.idString);
379
+ if (prevQueued && !from.equals(prevQueued.from)) {
380
+ throw new Error("Different from in queued results");
381
+ }
330
382
  let indexedResult = undefined;
331
- if (query instanceof types.SearchRequest) {
332
- indexedResult = await this.engine.query(query, from);
383
+ if (query instanceof indexerTypes.SearchRequest) {
384
+ indexedResult = await this.index.query(query);
333
385
  }
334
- else if (query instanceof types.CollectNextRequest) {
335
- indexedResult = await this.engine.next(query, from);
386
+ else if (query instanceof indexerTypes.CollectNextRequest) {
387
+ indexedResult =
388
+ prevQueued?.keptInIndex === 0
389
+ ? { kept: 0, results: [] }
390
+ : await this.index.next(query);
336
391
  }
337
392
  else {
338
393
  throw new Error("Unsupported");
339
394
  }
340
395
  const filteredResults = [];
341
- for (const result of indexedResult.results) {
396
+ let resultSize = 0;
397
+ let toIterate = prevQueued
398
+ ? [...prevQueued.queue, ...indexedResult.results]
399
+ : indexedResult.results;
400
+ if (prevQueued) {
401
+ this._resultQueue.delete(query.idString);
402
+ prevQueued = undefined;
403
+ }
404
+ if (!isLocal) {
405
+ prevQueued = {
406
+ from,
407
+ queue: [],
408
+ timeout: setTimeout(() => {
409
+ this._resultQueue.delete(query.idString);
410
+ }, 6e4),
411
+ keptInIndex: indexedResult.kept,
412
+ };
413
+ this._resultQueue.set(query.idString, prevQueued);
414
+ }
415
+ for (const result of toIterate) {
416
+ if (!isLocal) {
417
+ resultSize += result.value.__context.size;
418
+ if (resultSize > MAX_BATCH_SIZE) {
419
+ prevQueued.queue.push(result);
420
+ continue;
421
+ }
422
+ }
342
423
  const value = await this.resolveDocument(result);
343
424
  if (!value ||
344
425
  (options?.canRead && !(await options.canRead(value.value, from)))) {
345
426
  continue;
346
427
  }
347
428
  filteredResults.push(new types.ResultWithSource({
348
- context: result.context,
429
+ context: result.value.__context,
349
430
  value: value.value,
350
431
  source: serialize(value.value),
351
- indexed: result.indexed
432
+ indexed: result.value,
352
433
  }));
353
434
  }
354
435
  const results = new types.Results({
355
436
  results: filteredResults,
356
- kept: BigInt(indexedResult.kept)
437
+ kept: BigInt(indexedResult.kept + (prevQueued?.queue.length || 0)),
357
438
  });
439
+ if (!isLocal && results.kept === 0n) {
440
+ this.clearResultsQueue(query);
441
+ }
358
442
  return results;
359
443
  }
444
+ clearResultsQueue(query) {
445
+ const queue = this._resultQueue.get(query.idString);
446
+ if (queue) {
447
+ clearTimeout(queue.timeout);
448
+ this._resultQueue.delete(query.idString);
449
+ }
450
+ }
360
451
  async processCloseIteratorRequest(query, publicKey) {
361
- return this.engine.close(query, publicKey);
452
+ const queueData = this._resultQueue.get(query.idString);
453
+ if (queueData && !queueData.from.equals(publicKey)) {
454
+ logger.info("Ignoring close iterator request from different peer");
455
+ return;
456
+ }
457
+ this.clearResultsQueue(query);
458
+ return this.index.close(query);
362
459
  }
363
460
  /**
364
461
  * Query and retrieve results with most details
@@ -367,7 +464,7 @@ let DocumentIndex = class DocumentIndex extends Program {
367
464
  * @returns
368
465
  */
369
466
  async queryDetailed(queryRequest, options) {
370
- const local = typeof options?.local == "boolean" ? options?.local : true;
467
+ const local = typeof options?.local === "boolean" ? options?.local : true;
371
468
  let remote = undefined;
372
469
  if (typeof options?.remote === "boolean") {
373
470
  if (options?.remote) {
@@ -392,7 +489,7 @@ let DocumentIndex = class DocumentIndex extends Program {
392
489
  }
393
490
  const allResults = [];
394
491
  if (local) {
395
- const results = await this.processQuery(queryRequest, this.node.identity.publicKey);
492
+ const results = await this.processQuery(queryRequest, this.node.identity.publicKey, true);
396
493
  if (results.results.length > 0) {
397
494
  options?.onResponse &&
398
495
  (await options.onResponse(results, this.node.identity.publicKey));
@@ -406,12 +503,12 @@ let DocumentIndex = class DocumentIndex extends Program {
406
503
  const fn = async () => {
407
504
  const rs = [];
408
505
  const responseHandler = async (results) => {
409
- for (const r of await introduceEntries(results, this.type, this._sync, options)) {
506
+ for (const r of await introduceEntries(results, this.documentType, this._sync, options)) {
410
507
  rs.push(r.response);
411
508
  }
412
509
  };
413
510
  try {
414
- if (queryRequest instanceof types.CloseIteratorRequest) {
511
+ if (queryRequest instanceof indexerTypes.CloseIteratorRequest) {
415
512
  // don't wait for responses
416
513
  await this._query.request(queryRequest, { mode: remote.mode });
417
514
  }
@@ -467,7 +564,7 @@ let DocumentIndex = class DocumentIndex extends Program {
467
564
  */
468
565
  async search(queryRequest, options) {
469
566
  // Set fetch to search size, or max value (default to max u32 (4294967295))
470
- queryRequest.fetch = options?.size ?? 0xffffffff;
567
+ queryRequest.fetch = queryRequest.fetch ?? 0xffffffff;
471
568
  // So that the iterator is pre-fetching the right amount of entries
472
569
  const iterator = this.iterate(queryRequest, options);
473
570
  // So that this call will not do any remote requests
@@ -524,7 +621,7 @@ let DocumentIndex = class DocumentIndex extends Program {
524
621
  }
525
622
  const buffer = [];
526
623
  for (const result of results.results) {
527
- const indexKey = types.toIdeable(this.indexByResolver(result.value));
624
+ const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
528
625
  if (visited.has(indexKey)) {
529
626
  continue;
530
627
  }
@@ -532,21 +629,24 @@ let DocumentIndex = class DocumentIndex extends Program {
532
629
  buffer.push({
533
630
  value: result.value,
534
631
  context: result.context,
535
- from: from,
632
+ from,
536
633
  indexed: result.indexed ||
537
- (await this.fields(result.value, result.context))
634
+ (await this.transformer(result.value, result.context)),
538
635
  });
539
636
  }
540
637
  peerBufferMap.set(from.hashcode(), {
541
638
  buffer,
542
- kept: Number(response.kept)
639
+ kept: Number(response.kept),
543
640
  });
544
641
  }
545
642
  else {
546
643
  throw new Error("Unsupported result type: " + response?.constructor?.name);
547
644
  }
548
- }
645
+ },
549
646
  });
647
+ if (done) {
648
+ this.clearResultsQueue(queryRequest);
649
+ }
550
650
  return done;
551
651
  };
552
652
  const fetchAtLeast = async (n) => {
@@ -571,13 +671,13 @@ let DocumentIndex = class DocumentIndex extends Program {
571
671
  }
572
672
  // TODO buffer more than deleted?
573
673
  // TODO batch to multiple 'to's
574
- const collectRequest = new types.CollectNextRequest({
674
+ const collectRequest = new indexerTypes.CollectNextRequest({
575
675
  id: queryRequest.id,
576
- amount: n - buffer.buffer.length
676
+ amount: n - buffer.buffer.length,
577
677
  });
578
678
  // Fetch locally?
579
679
  if (peer === this.node.identity.publicKey.hashcode()) {
580
- promises.push(this.processQuery(collectRequest, this.node.identity.publicKey)
680
+ promises.push(this.processQuery(collectRequest, this.node.identity.publicKey, true)
581
681
  .then(async (results) => {
582
682
  resultsLeft += Number(results.kept);
583
683
  if (results.results.length === 0) {
@@ -592,16 +692,18 @@ let DocumentIndex = class DocumentIndex extends Program {
592
692
  }
593
693
  peerBuffer.kept = Number(results.kept);
594
694
  for (const result of results.results) {
595
- if (visited.has(types.toIdeable(this.indexByResolver(result.value)))) {
695
+ if (visited.has(indexerTypes.toId(this.indexByResolver(result.value))
696
+ .primitive)) {
596
697
  continue;
597
698
  }
598
- visited.add(types.toIdeable(this.indexByResolver(result.value)));
699
+ visited.add(indexerTypes.toId(this.indexByResolver(result.value))
700
+ .primitive);
599
701
  peerBuffer.buffer.push({
600
702
  value: result.value,
601
703
  context: result.context,
602
704
  from: this.node.identity.publicKey,
603
705
  indexed: result.indexed ||
604
- (await this.fields(result.value, result.context))
706
+ (await this.transformer(result.value, result.context)),
605
707
  });
606
708
  }
607
709
  }
@@ -618,9 +720,9 @@ let DocumentIndex = class DocumentIndex extends Program {
618
720
  ...options,
619
721
  signal: controller.signal,
620
722
  priority: 1,
621
- mode: new SilentDelivery({ to: [peer], redundancy: 1 })
723
+ mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
622
724
  })
623
- .then((response) => introduceEntries(response, this.type, this._sync, options)
725
+ .then((response) => introduceEntries(response, this.documentType, this._sync, options)
624
726
  .then((responses) => {
625
727
  responses.map((response) => {
626
728
  resultsLeft += Number(response.response.kept);
@@ -640,15 +742,15 @@ let DocumentIndex = class DocumentIndex extends Program {
640
742
  }
641
743
  peerBuffer.kept = Number(response.response.kept);
642
744
  for (const result of response.response.results) {
643
- if (visited.has(types.toIdeable(this.indexByResolver(result.value)))) {
745
+ if (visited.has(indexerTypes.toId(this.indexByResolver(result.value)).primitive)) {
644
746
  continue;
645
747
  }
646
- visited.add(types.toIdeable(this.indexByResolver(result.value)));
748
+ visited.add(indexerTypes.toId(this.indexByResolver(result.value)).primitive);
647
749
  peerBuffer.buffer.push({
648
750
  value: result.value,
649
751
  context: result.context,
650
752
  from: response.from,
651
- indexed: this.fields(result.value, result.context)
753
+ indexed: this.transformer(result.value, result.context),
652
754
  });
653
755
  }
654
756
  }
@@ -681,7 +783,8 @@ let DocumentIndex = class DocumentIndex extends Program {
681
783
  // TODO everything below is not very optimized
682
784
  const fetchedAll = await fetchAtLeast(n);
683
785
  // get n next top entries, shift and pull more results
684
- const results = await types.resolvedSort(peerBuffers(), queryRequest.sort);
786
+ const peerBuffersArr = peerBuffers();
787
+ const results = peerBuffersArr.sort((a, b) => indexerTypes.extractSortCompare(a.indexed, b.indexed, queryRequest.sort));
685
788
  const pendingMoreResults = n < results.length;
686
789
  const batch = results.splice(0, n);
687
790
  for (const result of batch) {
@@ -690,7 +793,7 @@ let DocumentIndex = class DocumentIndex extends Program {
690
793
  logger.error("Unexpected empty result buffer");
691
794
  continue;
692
795
  }
693
- const idx = arr.buffer.findIndex((x) => x.value == result.value);
796
+ const idx = arr.buffer.findIndex((x) => x.value === result.value);
694
797
  if (idx >= 0) {
695
798
  arr.buffer.splice(idx, 1);
696
799
  }
@@ -700,8 +803,8 @@ let DocumentIndex = class DocumentIndex extends Program {
700
803
  };
701
804
  const close = async () => {
702
805
  controller.abort(new AbortError("Iterator closed"));
703
- const closeRequest = new types.CloseIteratorRequest({
704
- id: queryRequest.id
806
+ const closeRequest = new indexerTypes.CloseIteratorRequest({
807
+ id: queryRequest.id,
705
808
  });
706
809
  const promises = [];
707
810
  for (const [peer, buffer] of peerBufferMap) {
@@ -717,7 +820,7 @@ let DocumentIndex = class DocumentIndex extends Program {
717
820
  // Close remote
718
821
  promises.push(this._query.send(closeRequest, {
719
822
  ...options,
720
- mode: new SilentDelivery({ to: [peer], redundancy: 1 })
823
+ mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
721
824
  }));
722
825
  }
723
826
  }
@@ -726,7 +829,7 @@ let DocumentIndex = class DocumentIndex extends Program {
726
829
  return {
727
830
  close,
728
831
  next,
729
- done: () => done
832
+ done: () => done,
730
833
  };
731
834
  }
732
835
  };