@peerbit/document 9.13.8 → 9.13.9-70f50dc

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/src/search.ts CHANGED
@@ -903,7 +903,7 @@ export class DocumentIndex<
903
903
  return queue.queue.length + queue.keptInIndex;
904
904
  }
905
905
 
906
- return this._resumableIterators.getPending(cursorId)
906
+ return this._resumableIterators.getPending(cursorId);
907
907
  }
908
908
 
909
909
  get hasPending() {
@@ -2008,7 +2008,7 @@ export class DocumentIndex<
2008
2008
  let queryRequestCoerced: types.SearchRequest | types.SearchRequestIndexed =
2009
2009
  coerceQuery(queryRequest ?? {}, options);
2010
2010
 
2011
- let resolve = false;
2011
+ let resolve = options?.resolve !== false;
2012
2012
  if (
2013
2013
  options?.remote &&
2014
2014
  typeof options.remote !== "boolean" &&
@@ -2048,15 +2048,35 @@ export class DocumentIndex<
2048
2048
  buffer: BufferedResult<types.ResultTypeFromRequest<R, T, I> | I, I>[];
2049
2049
  }
2050
2050
  > = new Map();
2051
- const visited = new Set<string | number | bigint>();
2051
+ const visited = new Set<indexerTypes.IdPrimitive>();
2052
+ let indexedPlaceholders:
2053
+ | Map<
2054
+ indexerTypes.IdPrimitive,
2055
+ BufferedResult<types.ResultTypeFromRequest<R, T, I> | I, I>
2056
+ >
2057
+ | undefined;
2058
+ const ensureIndexedPlaceholders = () => {
2059
+ if (!indexedPlaceholders) {
2060
+ indexedPlaceholders = new Map<
2061
+ string | number | bigint,
2062
+ BufferedResult<types.ResultTypeFromRequest<R, T, I> | I, I>
2063
+ >();
2064
+ }
2065
+ return indexedPlaceholders;
2066
+ };
2052
2067
 
2053
2068
  let done = false;
2054
2069
  let drain = false; // if true, close on empty once (overrides manual)
2055
2070
  let first = false;
2056
2071
 
2057
2072
  // TODO handle join/leave while iterating
2058
- const controller = new AbortController();
2059
-
2073
+ const controller: AbortController | undefined = undefined;
2074
+ const ensureController = () => {
2075
+ if (!controller) {
2076
+ return new AbortController();
2077
+ }
2078
+ return controller;
2079
+ };
2060
2080
  let totalFetchedCounter = 0;
2061
2081
  let lastValueInOrder:
2062
2082
  | {
@@ -2126,7 +2146,7 @@ export class DocumentIndex<
2126
2146
 
2127
2147
  if (options.remote.reach?.discover) {
2128
2148
  warmupPromise = this.waitFor(options.remote.reach.discover, {
2129
- signal: controller.signal,
2149
+ signal: ensureController().signal,
2130
2150
  seek: "present",
2131
2151
  timeout: waitForTime ?? DEFAULT_TIMEOUT,
2132
2152
  });
@@ -2146,7 +2166,7 @@ export class DocumentIndex<
2146
2166
  eager: options.remote.reach?.eager,
2147
2167
  settle: "any",
2148
2168
  timeout: waitPolicy.timeout ?? DEFAULT_TIMEOUT,
2149
- signal: controller.signal,
2169
+ signal: ensureController().signal,
2150
2170
  onTimeout: waitPolicy.onTimeout,
2151
2171
  });
2152
2172
  warmupPromise = warmupPromise
@@ -2203,10 +2223,23 @@ export class DocumentIndex<
2203
2223
  >[] = peerBufferMap.get(from.hashcode())?.buffer || [];
2204
2224
 
2205
2225
  for (const result of results.results) {
2226
+ const indexKey = indexerTypes.toId(
2227
+ this.indexByResolver(result.value),
2228
+ ).primitive;
2206
2229
  if (result instanceof types.ResultValue) {
2207
- const indexKey = indexerTypes.toId(
2208
- this.indexByResolver(result.value),
2209
- ).primitive;
2230
+ const existingIndexed = indexedPlaceholders?.get(indexKey);
2231
+ if (existingIndexed) {
2232
+ existingIndexed.value =
2233
+ result.value as types.ResultTypeFromRequest<R, T, I>;
2234
+ existingIndexed.context = result.context;
2235
+ existingIndexed.from = from!;
2236
+ existingIndexed.indexed = await this.resolveIndexed<R>(
2237
+ result,
2238
+ results.results,
2239
+ );
2240
+ indexedPlaceholders?.delete(indexKey);
2241
+ continue;
2242
+ }
2210
2243
  if (visited.has(indexKey)) {
2211
2244
  continue;
2212
2245
  }
@@ -2222,23 +2255,25 @@ export class DocumentIndex<
2222
2255
  ),
2223
2256
  });
2224
2257
  } else {
2225
- const indexKey = indexerTypes.toId(
2226
- this.indexByResolver(result.value),
2227
- ).primitive;
2228
-
2229
- if (visited.has(indexKey)) {
2258
+ if (
2259
+ visited.has(indexKey) &&
2260
+ !indexedPlaceholders?.has(indexKey)
2261
+ ) {
2230
2262
  continue;
2231
2263
  }
2232
2264
  visited.add(indexKey);
2233
- buffer.push({
2265
+ const indexed = coerceWithContext(
2266
+ result.indexed || result.value,
2267
+ result.context,
2268
+ );
2269
+ const placeholder = {
2234
2270
  value: result.value,
2235
2271
  context: result.context,
2236
2272
  from,
2237
- indexed: coerceWithContext(
2238
- result.indexed || result.value,
2239
- result.context,
2240
- ),
2241
- });
2273
+ indexed,
2274
+ };
2275
+ buffer.push(placeholder);
2276
+ ensureIndexedPlaceholders().set(indexKey, placeholder);
2242
2277
  }
2243
2278
  }
2244
2279
 
@@ -2327,21 +2362,38 @@ export class DocumentIndex<
2327
2362
  peerBuffer.kept = Number(results.kept);
2328
2363
 
2329
2364
  for (const result of results.results) {
2330
- if (
2331
- visited.has(
2332
- indexerTypes.toId(this.indexByResolver(result.value))
2333
- .primitive,
2334
- )
2335
- ) {
2336
- continue;
2337
- }
2338
- visited.add(
2339
- indexerTypes.toId(this.indexByResolver(result.value))
2340
- .primitive,
2341
- );
2342
- let indexed: WithContext<I>;
2365
+ const keyPrimitive = indexerTypes.toId(
2366
+ this.indexByResolver(result.value),
2367
+ ).primitive;
2343
2368
  if (result instanceof types.ResultValue) {
2344
- indexed = await this.resolveIndexed<R>(
2369
+ const existingIndexed =
2370
+ indexedPlaceholders?.get(keyPrimitive);
2371
+ if (existingIndexed) {
2372
+ existingIndexed.value =
2373
+ result.value as types.ResultTypeFromRequest<
2374
+ R,
2375
+ T,
2376
+ I
2377
+ >;
2378
+ existingIndexed.context = result.context;
2379
+ existingIndexed.from = this.node.identity.publicKey;
2380
+ existingIndexed.indexed =
2381
+ await this.resolveIndexed<R>(
2382
+ result,
2383
+ results.results as types.ResultTypeFromRequest<
2384
+ R,
2385
+ T,
2386
+ I
2387
+ >[],
2388
+ );
2389
+ indexedPlaceholders?.delete(keyPrimitive);
2390
+ continue;
2391
+ }
2392
+ if (visited.has(keyPrimitive)) {
2393
+ continue;
2394
+ }
2395
+ visited.add(keyPrimitive);
2396
+ const indexed = await this.resolveIndexed<R>(
2345
2397
  result,
2346
2398
  results.results as types.ResultTypeFromRequest<
2347
2399
  R,
@@ -2349,22 +2401,40 @@ export class DocumentIndex<
2349
2401
  I
2350
2402
  >[],
2351
2403
  );
2404
+ peerBuffer.buffer.push({
2405
+ value: result.value as types.ResultTypeFromRequest<
2406
+ R,
2407
+ T,
2408
+ I
2409
+ >,
2410
+ context: result.context,
2411
+ from: this.node.identity.publicKey,
2412
+ indexed,
2413
+ });
2352
2414
  } else {
2353
- indexed = coerceWithContext(
2415
+ if (
2416
+ visited.has(keyPrimitive) &&
2417
+ !indexedPlaceholders?.has(keyPrimitive)
2418
+ ) {
2419
+ continue;
2420
+ }
2421
+ visited.add(keyPrimitive);
2422
+ const indexed = coerceWithContext(
2354
2423
  result.indexed || result.value,
2355
2424
  result.context,
2356
2425
  );
2426
+ const placeholder = {
2427
+ value: result.value,
2428
+ context: result.context,
2429
+ from: this.node.identity.publicKey,
2430
+ indexed,
2431
+ };
2432
+ peerBuffer.buffer.push(placeholder);
2433
+ ensureIndexedPlaceholders().set(
2434
+ keyPrimitive,
2435
+ placeholder,
2436
+ );
2357
2437
  }
2358
- peerBuffer.buffer.push({
2359
- value: result.value as types.ResultTypeFromRequest<
2360
- R,
2361
- T,
2362
- I
2363
- >,
2364
- context: result.context,
2365
- from: this.node.identity.publicKey,
2366
- indexed: indexed,
2367
- });
2368
2438
  }
2369
2439
  }
2370
2440
  })
@@ -2394,8 +2464,11 @@ export class DocumentIndex<
2394
2464
  .request(remoteCollectRequest, {
2395
2465
  ...options,
2396
2466
  signal: options?.signal
2397
- ? AbortSignal.any([options.signal, controller.signal])
2398
- : controller.signal,
2467
+ ? AbortSignal.any([
2468
+ options.signal,
2469
+ ensureController().signal,
2470
+ ])
2471
+ : ensureController().signal,
2399
2472
  priority: 1,
2400
2473
  mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
2401
2474
  })
@@ -2435,17 +2508,40 @@ export class DocumentIndex<
2435
2508
  >
2436
2509
  >
2437
2510
  ).response.results) {
2438
- const idPrimitive = indexerTypes.toId(
2511
+ const indexKey = indexerTypes.toId(
2439
2512
  this.indexByResolver(result.value),
2440
2513
  ).primitive;
2441
- if (visited.has(idPrimitive)) {
2442
- continue;
2443
- }
2444
- visited.add(idPrimitive);
2445
-
2446
- let indexed: WithContext<I>;
2447
2514
  if (result instanceof types.ResultValue) {
2448
- indexed = await this.resolveIndexed(
2515
+ const existingIndexed =
2516
+ indexedPlaceholders?.get(indexKey);
2517
+ if (existingIndexed) {
2518
+ existingIndexed.value =
2519
+ result.value as types.ResultTypeFromRequest<
2520
+ R,
2521
+ T,
2522
+ I
2523
+ >;
2524
+ existingIndexed.context = result.context;
2525
+ existingIndexed.from = from!;
2526
+ existingIndexed.indexed =
2527
+ await this.resolveIndexed(
2528
+ result,
2529
+ response.response
2530
+ .results as types.ResultTypeFromRequest<
2531
+ R,
2532
+ T,
2533
+ I
2534
+ >[],
2535
+ );
2536
+ indexedPlaceholders?.delete(indexKey);
2537
+ continue;
2538
+ }
2539
+ if (visited.has(indexKey)) {
2540
+ continue;
2541
+ }
2542
+ visited.add(indexKey);
2543
+
2544
+ const indexed = await this.resolveIndexed(
2449
2545
  result,
2450
2546
  response.response
2451
2547
  .results as types.ResultTypeFromRequest<
@@ -2454,23 +2550,41 @@ export class DocumentIndex<
2454
2550
  I
2455
2551
  >[],
2456
2552
  );
2553
+ peerBuffer.buffer.push({
2554
+ value:
2555
+ result.value as types.ResultTypeFromRequest<
2556
+ R,
2557
+ T,
2558
+ I
2559
+ >,
2560
+ context: result.context,
2561
+ from: from!,
2562
+ indexed,
2563
+ });
2457
2564
  } else {
2458
- indexed = coerceWithContext(
2565
+ if (
2566
+ visited.has(indexKey) &&
2567
+ !indexedPlaceholders?.has(indexKey)
2568
+ ) {
2569
+ continue;
2570
+ }
2571
+ visited.add(indexKey);
2572
+ const indexed = coerceWithContext(
2459
2573
  result.value,
2460
2574
  result.context,
2461
2575
  );
2576
+ const placeholder = {
2577
+ value: result.value,
2578
+ context: result.context,
2579
+ from: from!,
2580
+ indexed,
2581
+ };
2582
+ peerBuffer.buffer.push(placeholder);
2583
+ ensureIndexedPlaceholders().set(
2584
+ indexKey,
2585
+ placeholder,
2586
+ );
2462
2587
  }
2463
- peerBuffer.buffer.push({
2464
- value:
2465
- result.value as types.ResultTypeFromRequest<
2466
- R,
2467
- T,
2468
- I
2469
- >,
2470
- context: result.context,
2471
- from: from!,
2472
- indexed,
2473
- });
2474
2588
  }
2475
2589
  }
2476
2590
  }),
@@ -2533,6 +2647,10 @@ export class DocumentIndex<
2533
2647
  const idx = arr.buffer.findIndex((x) => x.value === result.value);
2534
2648
  if (idx >= 0) {
2535
2649
  arr.buffer.splice(idx, 1);
2650
+ const consumedId = indexerTypes.toId(
2651
+ this.indexByResolver(result.indexed),
2652
+ ).primitive;
2653
+ indexedPlaceholders?.delete(consumedId);
2536
2654
  }
2537
2655
  }
2538
2656
 
@@ -2579,7 +2697,9 @@ export class DocumentIndex<
2579
2697
 
2580
2698
  let cleanupAndDone = () => {
2581
2699
  cleanup();
2582
- controller.abort(new AbortError("Iterator closed"));
2700
+ (controller as AbortController | undefined)?.abort(
2701
+ new AbortError("Iterator closed"),
2702
+ );
2583
2703
  this.prefetch?.accumulator.clear(queryRequestCoerced);
2584
2704
  this.processCloseIteratorRequest(
2585
2705
  queryRequestCoerced,
@@ -2744,7 +2864,6 @@ export class DocumentIndex<
2744
2864
  };
2745
2865
 
2746
2866
  const onChange = async (evt: CustomEvent<DocumentsChange<T, I>>) => {
2747
-
2748
2867
  // Optional filter to mutate/suppress change events
2749
2868
  let filtered: DocumentsChange<T, I> | void = evt.detail;
2750
2869
  if (mergePolicy?.merge?.filter) {
@@ -2777,6 +2896,7 @@ export class DocumentIndex<
2777
2896
  ).primitive;
2778
2897
  if (removedIds.has(id)) {
2779
2898
  matchedRemovedIds.add(id);
2899
+ indexedPlaceholders?.delete(id);
2780
2900
  return false;
2781
2901
  }
2782
2902
  return true;
@@ -2838,23 +2958,37 @@ export class DocumentIndex<
2838
2958
  const id = indexerTypes.toId(
2839
2959
  this.indexByResolver(indexedCandidate),
2840
2960
  ).primitive;
2961
+ const existingIndexed = indexedPlaceholders?.get(id);
2962
+ if (existingIndexed) {
2963
+ if (resolve) {
2964
+ existingIndexed.value = added as any;
2965
+ existingIndexed.context = added.__context;
2966
+ existingIndexed.from = this.node.identity.publicKey;
2967
+ existingIndexed.indexed = indexedCandidate;
2968
+ indexedPlaceholders?.delete(id);
2969
+ }
2970
+ continue;
2971
+ }
2841
2972
  if (visited.has(id)) continue; // already presented
2842
2973
  visited.add(id);
2843
2974
  const valueForBuffer = resolve
2844
2975
  ? (added as any)
2845
2976
  : indexedCandidate;
2846
- buf.buffer.push({
2977
+ const placeholder = {
2847
2978
  value: valueForBuffer,
2848
2979
  context: added.__context,
2849
2980
  from: this.node.identity.publicKey,
2850
2981
  indexed: indexedCandidate,
2851
- });
2982
+ };
2983
+ buf.buffer.push(placeholder);
2984
+ if (!resolve) {
2985
+ ensureIndexedPlaceholders().set(id, placeholder);
2986
+ }
2852
2987
  hasRelevantChange = true;
2853
2988
  changeForCallback.added.push(added);
2854
2989
  }
2855
2990
  }
2856
2991
 
2857
-
2858
2992
  if (hasRelevantChange) {
2859
2993
  if (!pendingResultsReason) {
2860
2994
  pendingResultsReason = "change";
@@ -2907,10 +3041,10 @@ export class DocumentIndex<
2907
3041
  setTimeout(() => {
2908
3042
  signalUpdate();
2909
3043
  }, waitForTime);
2910
- controller.signal.addEventListener("abort", () => signalUpdate());
3044
+ ensureController().signal.addEventListener("abort", () => signalUpdate());
2911
3045
  fetchedFirstForRemote = new Set<string>();
2912
3046
  joinListener = this.attachJoinListener({
2913
- signal: controller.signal,
3047
+ signal: ensureController().signal,
2914
3048
  eager: options.remote.reach?.eager,
2915
3049
  onPeer: async (pk) => {
2916
3050
  if (done) return;