@peerbit/shared-log 12.1.3 → 12.2.0-3333888
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/pid-convergence.d.ts +2 -0
- package/dist/benchmark/pid-convergence.d.ts.map +1 -0
- package/dist/benchmark/pid-convergence.js +138 -0
- package/dist/benchmark/pid-convergence.js.map +1 -0
- package/dist/benchmark/rateless-iblt-sender-startsync.d.ts +2 -0
- package/dist/benchmark/rateless-iblt-sender-startsync.d.ts.map +1 -0
- package/dist/benchmark/rateless-iblt-sender-startsync.js +104 -0
- package/dist/benchmark/rateless-iblt-sender-startsync.js.map +1 -0
- package/dist/benchmark/rateless-iblt-startsync-cache.d.ts +2 -0
- package/dist/benchmark/rateless-iblt-startsync-cache.d.ts.map +1 -0
- package/dist/benchmark/rateless-iblt-startsync-cache.js +112 -0
- package/dist/benchmark/rateless-iblt-startsync-cache.js.map +1 -0
- package/dist/benchmark/sync-catchup.d.ts +3 -0
- package/dist/benchmark/sync-catchup.d.ts.map +1 -0
- package/dist/benchmark/sync-catchup.js +109 -0
- package/dist/benchmark/sync-catchup.js.map +1 -0
- package/dist/src/index.d.ts +10 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +66 -32
- package/dist/src/index.js.map +1 -1
- package/dist/src/like.d.ts +71 -0
- package/dist/src/like.d.ts.map +1 -0
- package/dist/src/like.js +2 -0
- package/dist/src/like.js.map +1 -0
- package/dist/src/sync/index.d.ts +14 -0
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/rateless-iblt.d.ts +14 -22
- package/dist/src/sync/rateless-iblt.d.ts.map +1 -1
- package/dist/src/sync/rateless-iblt.js +139 -22
- package/dist/src/sync/rateless-iblt.js.map +1 -1
- package/dist/src/sync/simple.d.ts +3 -1
- package/dist/src/sync/simple.d.ts.map +1 -1
- package/dist/src/sync/simple.js +24 -2
- package/dist/src/sync/simple.js.map +1 -1
- package/package.json +20 -20
- package/src/index.ts +95 -37
- package/src/like.ts +84 -0
- package/src/sync/index.ts +19 -0
- package/src/sync/rateless-iblt.ts +193 -40
- package/src/sync/simple.ts +26 -3
|
@@ -4,18 +4,24 @@ import { type PublicSignKey, randomBytes, toBase64 } from "@peerbit/crypto";
|
|
|
4
4
|
import { type Index } from "@peerbit/indexer-interface";
|
|
5
5
|
import type { Entry, Log } from "@peerbit/log";
|
|
6
6
|
import { logger as loggerFn } from "@peerbit/logger";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
DecoderWrapper,
|
|
9
|
+
EncoderWrapper,
|
|
10
|
+
ready as ribltReady,
|
|
11
|
+
} from "@peerbit/riblt";
|
|
8
12
|
import type { RPC, RequestContext } from "@peerbit/rpc";
|
|
9
13
|
import { SilentDelivery } from "@peerbit/stream-interface";
|
|
10
14
|
import { type EntryWithRefs } from "../exchange-heads.js";
|
|
11
|
-
import { type Numbers } from "../integers.js";
|
|
12
15
|
import { TransportMessage } from "../message.js";
|
|
13
16
|
import {
|
|
14
17
|
type EntryReplicated,
|
|
15
|
-
type ReplicationRangeIndexable,
|
|
16
18
|
matchEntriesInRangeQuery,
|
|
17
19
|
} from "../ranges.js";
|
|
18
|
-
import type {
|
|
20
|
+
import type {
|
|
21
|
+
SyncableKey,
|
|
22
|
+
SynchronizerComponents,
|
|
23
|
+
Syncronizer,
|
|
24
|
+
} from "./index.js";
|
|
19
25
|
import { SimpleSyncronizer } from "./simple.js";
|
|
20
26
|
|
|
21
27
|
export const logger = loggerFn("peerbit:shared-log:rateless");
|
|
@@ -142,6 +148,7 @@ const buildEncoderOrDecoderFromRange = async <
|
|
|
142
148
|
entryIndex: Index<EntryReplicated<D>>,
|
|
143
149
|
type: T,
|
|
144
150
|
): Promise<E | false> => {
|
|
151
|
+
await ribltReady;
|
|
145
152
|
const encoder =
|
|
146
153
|
type === "encoder" ? new EncoderWrapper() : new DecoderWrapper();
|
|
147
154
|
|
|
@@ -180,6 +187,13 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
180
187
|
simple: SimpleSyncronizer<D>;
|
|
181
188
|
|
|
182
189
|
startedOrCompletedSynchronizations: Cache<string>;
|
|
190
|
+
private localRangeEncoderCacheVersion = 0;
|
|
191
|
+
private localRangeEncoderCache: Map<
|
|
192
|
+
string,
|
|
193
|
+
{ encoder: EncoderWrapper; version: number; lastUsed: number }
|
|
194
|
+
> = new Map();
|
|
195
|
+
private localRangeEncoderCacheMax = 2;
|
|
196
|
+
|
|
183
197
|
ingoingSyncProcesses: Map<
|
|
184
198
|
string,
|
|
185
199
|
{
|
|
@@ -207,14 +221,7 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
207
221
|
>;
|
|
208
222
|
|
|
209
223
|
constructor(
|
|
210
|
-
readonly properties:
|
|
211
|
-
rpc: RPC<TransportMessage, TransportMessage>;
|
|
212
|
-
rangeIndex: Index<ReplicationRangeIndexable<D>, any>;
|
|
213
|
-
entryIndex: Index<EntryReplicated<D>, any>;
|
|
214
|
-
log: Log<any>;
|
|
215
|
-
coordinateToHash: Cache<string>;
|
|
216
|
-
numbers: Numbers<D>;
|
|
217
|
-
},
|
|
224
|
+
readonly properties: SynchronizerComponents<D>,
|
|
218
225
|
) {
|
|
219
226
|
this.simple = new SimpleSyncronizer(properties);
|
|
220
227
|
this.outgoingSyncProcesses = new Map();
|
|
@@ -222,6 +229,91 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
222
229
|
this.startedOrCompletedSynchronizations = new Cache({ max: 1e4 });
|
|
223
230
|
}
|
|
224
231
|
|
|
232
|
+
private clearLocalRangeEncoderCache() {
|
|
233
|
+
for (const [, cached] of this.localRangeEncoderCache) {
|
|
234
|
+
cached.encoder.free();
|
|
235
|
+
}
|
|
236
|
+
this.localRangeEncoderCache.clear();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private invalidateLocalRangeEncoderCache() {
|
|
240
|
+
this.localRangeEncoderCacheVersion += 1;
|
|
241
|
+
this.clearLocalRangeEncoderCache();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private localRangeEncoderCacheKey(ranges: {
|
|
245
|
+
start1: NumberOrBigint;
|
|
246
|
+
end1: NumberOrBigint;
|
|
247
|
+
start2: NumberOrBigint;
|
|
248
|
+
end2: NumberOrBigint;
|
|
249
|
+
}) {
|
|
250
|
+
return `${String(ranges.start1)}:${String(ranges.end1)}:${String(
|
|
251
|
+
ranges.start2,
|
|
252
|
+
)}:${String(ranges.end2)}`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private decoderFromCachedEncoder(encoder: EncoderWrapper): DecoderWrapper {
|
|
256
|
+
const clone = encoder.clone();
|
|
257
|
+
const decoder = clone.to_decoder();
|
|
258
|
+
clone.free();
|
|
259
|
+
return decoder;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private async getLocalDecoderForRange(ranges: {
|
|
263
|
+
start1: NumberOrBigint;
|
|
264
|
+
end1: NumberOrBigint;
|
|
265
|
+
start2: NumberOrBigint;
|
|
266
|
+
end2: NumberOrBigint;
|
|
267
|
+
}): Promise<DecoderWrapper | false> {
|
|
268
|
+
const key = this.localRangeEncoderCacheKey(ranges);
|
|
269
|
+
const cached = this.localRangeEncoderCache.get(key);
|
|
270
|
+
if (cached && cached.version === this.localRangeEncoderCacheVersion) {
|
|
271
|
+
cached.lastUsed = Date.now();
|
|
272
|
+
return this.decoderFromCachedEncoder(cached.encoder);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const encoder = (await buildEncoderOrDecoderFromRange(
|
|
276
|
+
ranges,
|
|
277
|
+
this.properties.entryIndex,
|
|
278
|
+
"encoder",
|
|
279
|
+
)) as EncoderWrapper | false;
|
|
280
|
+
if (!encoder) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const now = Date.now();
|
|
285
|
+
const existing = this.localRangeEncoderCache.get(key);
|
|
286
|
+
if (existing) {
|
|
287
|
+
existing.encoder.free();
|
|
288
|
+
}
|
|
289
|
+
this.localRangeEncoderCache.set(key, {
|
|
290
|
+
encoder,
|
|
291
|
+
version: this.localRangeEncoderCacheVersion,
|
|
292
|
+
lastUsed: now,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
while (this.localRangeEncoderCache.size > this.localRangeEncoderCacheMax) {
|
|
296
|
+
let oldestKey: string | undefined;
|
|
297
|
+
let oldestUsed = Number.POSITIVE_INFINITY;
|
|
298
|
+
for (const [candidateKey, value] of this.localRangeEncoderCache) {
|
|
299
|
+
if (value.lastUsed < oldestUsed) {
|
|
300
|
+
oldestUsed = value.lastUsed;
|
|
301
|
+
oldestKey = candidateKey;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (!oldestKey) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
const victim = this.localRangeEncoderCache.get(oldestKey);
|
|
308
|
+
if (victim) {
|
|
309
|
+
victim.encoder.free();
|
|
310
|
+
}
|
|
311
|
+
this.localRangeEncoderCache.delete(oldestKey);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return this.decoderFromCachedEncoder(encoder);
|
|
315
|
+
}
|
|
316
|
+
|
|
225
317
|
async onMaybeMissingEntries(properties: {
|
|
226
318
|
entries: Map<string, EntryReplicated<D>>;
|
|
227
319
|
targets: string[];
|
|
@@ -233,7 +325,6 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
233
325
|
// such as those assigned to range boundaries.
|
|
234
326
|
|
|
235
327
|
let entriesToSyncNaively: Map<string, EntryReplicated<D>> = new Map();
|
|
236
|
-
let allCoordinatesToSyncWithIblt: bigint[] = [];
|
|
237
328
|
let minSyncIbltSize = 333; // TODO: make configurable
|
|
238
329
|
let maxSyncWithSimpleMethod = 1e3;
|
|
239
330
|
|
|
@@ -246,13 +337,59 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
246
337
|
return;
|
|
247
338
|
}
|
|
248
339
|
|
|
249
|
-
|
|
340
|
+
const nonBoundaryEntries: EntryReplicated<D>[] = [];
|
|
250
341
|
for (const entry of properties.entries.values()) {
|
|
251
342
|
if (entry.assignedToRangeBoundary) {
|
|
252
343
|
entriesToSyncNaively.set(entry.hash, entry);
|
|
253
344
|
} else {
|
|
254
|
-
|
|
345
|
+
nonBoundaryEntries.push(entry);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const priorityFn = this.properties.sync?.priority;
|
|
350
|
+
const maxSimpleEntries = this.properties.sync?.maxSimpleEntries;
|
|
351
|
+
const maxAdditionalNaive =
|
|
352
|
+
priorityFn &&
|
|
353
|
+
typeof maxSimpleEntries === "number" &&
|
|
354
|
+
Number.isFinite(maxSimpleEntries) &&
|
|
355
|
+
maxSimpleEntries > 0
|
|
356
|
+
? Math.max(
|
|
357
|
+
0,
|
|
358
|
+
Math.min(
|
|
359
|
+
Math.floor(maxSimpleEntries),
|
|
360
|
+
maxSyncWithSimpleMethod - entriesToSyncNaively.size,
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
: 0;
|
|
364
|
+
|
|
365
|
+
if (priorityFn && maxAdditionalNaive > 0 && nonBoundaryEntries.length > 0) {
|
|
366
|
+
let index = 0;
|
|
367
|
+
const scored: {
|
|
368
|
+
entry: EntryReplicated<D>;
|
|
369
|
+
index: number;
|
|
370
|
+
priority: number;
|
|
371
|
+
}[] = [];
|
|
372
|
+
for (const entry of nonBoundaryEntries) {
|
|
373
|
+
const priorityValue = priorityFn(entry);
|
|
374
|
+
scored.push({
|
|
375
|
+
entry,
|
|
376
|
+
index,
|
|
377
|
+
priority: Number.isFinite(priorityValue) ? priorityValue : 0,
|
|
378
|
+
});
|
|
379
|
+
index += 1;
|
|
380
|
+
}
|
|
381
|
+
scored.sort((a, b) => b.priority - a.priority || a.index - b.index);
|
|
382
|
+
for (const { entry } of scored.slice(0, maxAdditionalNaive)) {
|
|
383
|
+
entriesToSyncNaively.set(entry.hash, entry);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
let allCoordinatesToSyncWithIblt: bigint[] = [];
|
|
388
|
+
for (const entry of nonBoundaryEntries) {
|
|
389
|
+
if (entriesToSyncNaively.has(entry.hash)) {
|
|
390
|
+
continue;
|
|
255
391
|
}
|
|
392
|
+
allCoordinatesToSyncWithIblt.push(coerceBigInt(entry.hashNumber));
|
|
256
393
|
}
|
|
257
394
|
|
|
258
395
|
if (entriesToSyncNaively.size > 0) {
|
|
@@ -268,31 +405,44 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
268
405
|
entriesToSyncNaively.size > maxSyncWithSimpleMethod
|
|
269
406
|
) {
|
|
270
407
|
// Fallback: if nothing left for IBLT (or simple set is too large), include all in IBLT
|
|
271
|
-
allCoordinatesToSyncWithIblt =
|
|
272
|
-
|
|
273
|
-
|
|
408
|
+
allCoordinatesToSyncWithIblt = [];
|
|
409
|
+
for (const entry of properties.entries.values()) {
|
|
410
|
+
allCoordinatesToSyncWithIblt.push(coerceBigInt(entry.hashNumber));
|
|
411
|
+
}
|
|
274
412
|
}
|
|
275
413
|
|
|
276
414
|
if (allCoordinatesToSyncWithIblt.length === 0) {
|
|
277
415
|
return;
|
|
278
416
|
}
|
|
279
417
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
418
|
+
await ribltReady;
|
|
419
|
+
|
|
420
|
+
let sortedEntries: bigint[] | BigUint64Array;
|
|
421
|
+
if (typeof BigUint64Array !== "undefined") {
|
|
422
|
+
const typed = new BigUint64Array(allCoordinatesToSyncWithIblt.length);
|
|
423
|
+
for (let i = 0; i < allCoordinatesToSyncWithIblt.length; i++) {
|
|
424
|
+
typed[i] = allCoordinatesToSyncWithIblt[i];
|
|
287
425
|
}
|
|
288
|
-
|
|
426
|
+
typed.sort();
|
|
427
|
+
sortedEntries = typed;
|
|
428
|
+
} else {
|
|
429
|
+
sortedEntries = allCoordinatesToSyncWithIblt.sort((a, b) => {
|
|
430
|
+
if (a > b) {
|
|
431
|
+
return 1;
|
|
432
|
+
} else if (a < b) {
|
|
433
|
+
return -1;
|
|
434
|
+
} else {
|
|
435
|
+
return 0;
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
289
439
|
|
|
290
440
|
// assume sorted, and find the largest gap
|
|
291
441
|
let largestGap = 0n;
|
|
292
442
|
let largestGapIndex = 0;
|
|
293
|
-
for (let i = 0; i < sortedEntries.length
|
|
443
|
+
for (let i = 0; i < sortedEntries.length; i++) {
|
|
294
444
|
const current = sortedEntries[i];
|
|
295
|
-
const next = sortedEntries[i + 1];
|
|
445
|
+
const next = sortedEntries[(i + 1) % sortedEntries.length];
|
|
296
446
|
const gap =
|
|
297
447
|
next >= current
|
|
298
448
|
? next - current
|
|
@@ -322,8 +472,12 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
322
472
|
|
|
323
473
|
const startSync = new StartSync({ from: start, to: end, symbols: [] });
|
|
324
474
|
const encoder = new EncoderWrapper();
|
|
325
|
-
|
|
326
|
-
encoder.
|
|
475
|
+
if (typeof BigUint64Array !== "undefined" && sortedEntries instanceof BigUint64Array) {
|
|
476
|
+
encoder.add_symbols(sortedEntries);
|
|
477
|
+
} else {
|
|
478
|
+
for (const entry of sortedEntries) {
|
|
479
|
+
encoder.add_symbol(coerceBigInt(entry));
|
|
480
|
+
}
|
|
327
481
|
}
|
|
328
482
|
|
|
329
483
|
let initialSymbols = Math.round(
|
|
@@ -399,16 +553,12 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
399
553
|
this.startedOrCompletedSynchronizations.add(syncId);
|
|
400
554
|
|
|
401
555
|
const wrapped = message.end < message.start;
|
|
402
|
-
const decoder = await
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
},
|
|
409
|
-
this.properties.entryIndex,
|
|
410
|
-
"decoder",
|
|
411
|
-
);
|
|
556
|
+
const decoder = await this.getLocalDecoderForRange({
|
|
557
|
+
start1: message.start,
|
|
558
|
+
end1: wrapped ? this.properties.numbers.maxValue : message.end,
|
|
559
|
+
start2: 0n,
|
|
560
|
+
end2: wrapped ? message.end : 0n,
|
|
561
|
+
});
|
|
412
562
|
|
|
413
563
|
if (!decoder) {
|
|
414
564
|
await this.simple.rpc.send(
|
|
@@ -613,10 +763,12 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
613
763
|
}
|
|
614
764
|
|
|
615
765
|
onEntryAdded(entry: Entry<any>): void {
|
|
766
|
+
this.invalidateLocalRangeEncoderCache();
|
|
616
767
|
return this.simple.onEntryAdded(entry);
|
|
617
768
|
}
|
|
618
769
|
|
|
619
770
|
onEntryRemoved(hash: string) {
|
|
771
|
+
this.invalidateLocalRangeEncoderCache();
|
|
620
772
|
return this.simple.onEntryRemoved(hash);
|
|
621
773
|
}
|
|
622
774
|
|
|
@@ -635,6 +787,7 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
635
787
|
for (const [, obj] of this.outgoingSyncProcesses) {
|
|
636
788
|
obj.free();
|
|
637
789
|
}
|
|
790
|
+
this.clearLocalRangeEncoderCache();
|
|
638
791
|
return this.simple.close();
|
|
639
792
|
}
|
|
640
793
|
|
package/src/sync/simple.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "../exchange-heads.js";
|
|
17
17
|
import { TransportMessage } from "../message.js";
|
|
18
18
|
import type { EntryReplicated } from "../ranges.js";
|
|
19
|
-
import type { SyncableKey, Syncronizer } from "./index.js";
|
|
19
|
+
import type { SyncableKey, SyncOptions, Syncronizer } from "./index.js";
|
|
20
20
|
|
|
21
21
|
@variant([0, 1])
|
|
22
22
|
export class RequestMaybeSync extends TransportMessage {
|
|
@@ -57,7 +57,7 @@ const getHashesFromSymbols = async (
|
|
|
57
57
|
coordinateToHash: Cache<string>,
|
|
58
58
|
) => {
|
|
59
59
|
let queries: IntegerCompare[] = [];
|
|
60
|
-
let batchSize =
|
|
60
|
+
let batchSize = 128; // TODO arg
|
|
61
61
|
let results = new Set<string>();
|
|
62
62
|
const handleBatch = async (end = false) => {
|
|
63
63
|
if (queries.length >= batchSize || (end && queries.length > 0)) {
|
|
@@ -109,6 +109,7 @@ export class SimpleSyncronizer<R extends "u32" | "u64">
|
|
|
109
109
|
log: Log<any>;
|
|
110
110
|
entryIndex: Index<EntryReplicated<R>, any>;
|
|
111
111
|
coordinateToHash: Cache<string>;
|
|
112
|
+
private syncOptions?: SyncOptions<R>;
|
|
112
113
|
|
|
113
114
|
// Syncing and dedeplucation work
|
|
114
115
|
syncMoreInterval?: ReturnType<typeof setTimeout>;
|
|
@@ -120,6 +121,7 @@ export class SimpleSyncronizer<R extends "u32" | "u64">
|
|
|
120
121
|
entryIndex: Index<EntryReplicated<R>, any>;
|
|
121
122
|
log: Log<any>;
|
|
122
123
|
coordinateToHash: Cache<string>;
|
|
124
|
+
sync?: SyncOptions<R>;
|
|
123
125
|
}) {
|
|
124
126
|
this.syncInFlightQueue = new Map();
|
|
125
127
|
this.syncInFlightQueueInverted = new Map();
|
|
@@ -128,14 +130,35 @@ export class SimpleSyncronizer<R extends "u32" | "u64">
|
|
|
128
130
|
this.log = properties.log;
|
|
129
131
|
this.entryIndex = properties.entryIndex;
|
|
130
132
|
this.coordinateToHash = properties.coordinateToHash;
|
|
133
|
+
this.syncOptions = properties.sync;
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
onMaybeMissingEntries(properties: {
|
|
134
137
|
entries: Map<string, EntryReplicated<R>>;
|
|
135
138
|
targets: string[];
|
|
136
139
|
}): Promise<void> {
|
|
140
|
+
let hashes: string[];
|
|
141
|
+
const priorityFn = this.syncOptions?.priority;
|
|
142
|
+
if (priorityFn) {
|
|
143
|
+
let index = 0;
|
|
144
|
+
const scored: { hash: string; index: number; priority: number }[] = [];
|
|
145
|
+
for (const [hash, entry] of properties.entries) {
|
|
146
|
+
const priorityValue = priorityFn(entry);
|
|
147
|
+
scored.push({
|
|
148
|
+
hash,
|
|
149
|
+
index,
|
|
150
|
+
priority: Number.isFinite(priorityValue) ? priorityValue : 0,
|
|
151
|
+
});
|
|
152
|
+
index += 1;
|
|
153
|
+
}
|
|
154
|
+
scored.sort((a, b) => b.priority - a.priority || a.index - b.index);
|
|
155
|
+
hashes = scored.map((x) => x.hash);
|
|
156
|
+
} else {
|
|
157
|
+
hashes = [...properties.entries.keys()];
|
|
158
|
+
}
|
|
159
|
+
|
|
137
160
|
return this.rpc.send(
|
|
138
|
-
new RequestMaybeSync({ hashes
|
|
161
|
+
new RequestMaybeSync({ hashes }),
|
|
139
162
|
{
|
|
140
163
|
priority: 1,
|
|
141
164
|
mode: new SilentDelivery({ to: properties.targets, redundancy: 1 }),
|