@peerbit/shared-log 8.0.7-a9206a8 → 8.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 (49) hide show
  1. package/dist/benchmark/get-samples.d.ts +2 -0
  2. package/dist/benchmark/get-samples.d.ts.map +1 -0
  3. package/dist/benchmark/get-samples.js +69 -0
  4. package/dist/benchmark/get-samples.js.map +1 -0
  5. package/dist/benchmark/index.js +15 -16
  6. package/dist/benchmark/index.js.map +1 -1
  7. package/dist/benchmark/replication-prune.d.ts +2 -0
  8. package/dist/benchmark/replication-prune.d.ts.map +1 -0
  9. package/dist/benchmark/replication-prune.js +103 -0
  10. package/dist/benchmark/replication-prune.js.map +1 -0
  11. package/dist/benchmark/replication.d.ts +2 -0
  12. package/dist/benchmark/replication.d.ts.map +1 -0
  13. package/dist/benchmark/replication.js +91 -0
  14. package/dist/benchmark/replication.js.map +1 -0
  15. package/dist/src/blocks.js +1 -1
  16. package/dist/src/blocks.js.map +1 -1
  17. package/dist/src/cpu.js.map +1 -1
  18. package/dist/src/exchange-heads.d.ts +1 -1
  19. package/dist/src/exchange-heads.d.ts.map +1 -1
  20. package/dist/src/exchange-heads.js +8 -8
  21. package/dist/src/exchange-heads.js.map +1 -1
  22. package/dist/src/index.d.ts +53 -47
  23. package/dist/src/index.d.ts.map +1 -1
  24. package/dist/src/index.js +513 -365
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/pid.d.ts.map +1 -1
  27. package/dist/src/pid.js +20 -20
  28. package/dist/src/pid.js.map +1 -1
  29. package/dist/src/ranges.d.ts +9 -12
  30. package/dist/src/ranges.d.ts.map +1 -1
  31. package/dist/src/ranges.js +528 -133
  32. package/dist/src/ranges.js.map +1 -1
  33. package/dist/src/replication.d.ts +70 -12
  34. package/dist/src/replication.d.ts.map +1 -1
  35. package/dist/src/replication.js +258 -17
  36. package/dist/src/replication.js.map +1 -1
  37. package/dist/src/role.d.ts +1 -38
  38. package/dist/src/role.d.ts.map +1 -1
  39. package/dist/src/role.js +92 -116
  40. package/dist/src/role.js.map +1 -1
  41. package/package.json +11 -10
  42. package/src/blocks.ts +1 -1
  43. package/src/cpu.ts +4 -4
  44. package/src/exchange-heads.ts +18 -18
  45. package/src/index.ts +797 -550
  46. package/src/pid.ts +23 -22
  47. package/src/ranges.ts +693 -147
  48. package/src/replication.ts +271 -19
  49. package/src/role.ts +63 -83
@@ -1,8 +1,12 @@
1
- import yallist from "yallist";
1
+ import { equals } from "@peerbit/crypto";
2
+ import { And, Compare, IntegerCompare, Or, SearchRequest, Sort, SortDirection, StringMatch, iterate, iteratorInSeries, } from "@peerbit/indexer-interface";
2
3
  import {} from "./replication.js";
3
- import { Replicator } from "./role.js";
4
- import { PublicSignKey } from "@peerbit/crypto";
5
- export const containsPoint = (rect, point, eps = 0.00001 // we do this to handle numerical errors
4
+ import { SEGMENT_COORDINATE_SCALE } from "./role.js";
5
+ /*
6
+ export const containsPoint = (
7
+ rect: { offset: number; length: number },
8
+ point: number,
9
+ eps = 0.00001 // we do this to handle numerical errors
6
10
  ) => {
7
11
  if (rect.factor === 0) {
8
12
  return false;
@@ -16,235 +20,626 @@ export const containsPoint = (rect, point, eps = 0.00001 // we do this to handle
16
20
  end = endUnwrapped % 1;
17
21
  wrapped = true;
18
22
  }
23
+
19
24
  const inFirstInterval = point >= start && point < Math.min(endUnwrapped, 1);
20
- const inSecondInterval = !inFirstInterval && wrapped && point >= 0 && point < end;
25
+ const inSecondInterval =
26
+ !inFirstInterval && wrapped && point >= 0 && point < end;
27
+
21
28
  return inFirstInterval || inSecondInterval;
29
+ }; */
30
+ /* const resolveRectsThatContainPoint = async (
31
+ rects: Index<ReplicationRangeIndexable>,
32
+ point: number,
33
+ roleAgeLimit: number,
34
+ matured: boolean
35
+ ): Promise<ReplicationRangeIndexable[]> => {
36
+ // point is between 0 and 1, and the range can start at any offset between 0 and 1 and have length between 0 and 1
37
+ // so we need to query for all ranges that contain the point
38
+ const scaledPoint = Math.round(point * SEGMENT_COORDINATE_SCALE)
39
+ let queries = [
40
+ new IntegerCompare({ key: 'start', compare: Compare.LessOrEqual, value: scaledPoint }),
41
+ new IntegerCompare({ key: 'end', compare: Compare.Greater, value: scaledPoint }),
42
+ new IntegerCompare({ key: 'timestamp', compare: matured ? Compare.LessOrEqual : Compare.Greater, value: Date.now() - roleAgeLimit })
43
+ ]
44
+
45
+ const results = await rects.query(new SearchRequest({
46
+ query: [
47
+ new Nested({
48
+ path: 'segments',
49
+ query: queries
50
+ })
51
+ ]
52
+ }))
53
+ return results.results.map(x => x.value)
54
+ } */
55
+ /* const resolveRectsInRange = async (rects: Index<ReplicationRangeIndexable>,
56
+ start: number,
57
+ end: number,
58
+ roleAgeLimit: number,
59
+ matured: boolean
60
+ ): Promise<ReplicationRangeIndexable[]> => {
61
+ // point is between 0 and 1, and the range can start at any offset between 0 and 1 and have length between 0 and 1
62
+ // so we need to query for all ranges that contain the point
63
+ let endScaled = Math.round(end * SEGMENT_COORDINATE_SCALE);
64
+ let startScaled = Math.round(start * SEGMENT_COORDINATE_SCALE);
65
+ let queries = [
66
+ new Or([
67
+ new And([
68
+ new IntegerCompare({ key: 'start1', compare: Compare.Less, value: endScaled }),
69
+ new IntegerCompare({ key: 'end1', compare: Compare.GreaterOrEqual, value: startScaled }),
70
+ ]),
71
+ new And([
72
+ new IntegerCompare({ key: 'start2', compare: Compare.Less, value: endScaled }),
73
+ new IntegerCompare({ key: 'end2', compare: Compare.GreaterOrEqual, value: startScaled }),
74
+ ])
75
+ ]),
76
+ new IntegerCompare({ key: 'timestamp', compare: matured ? Compare.LessOrEqual : Compare.Greater, value: BigInt(+new Date - roleAgeLimit) })
77
+ ]
78
+
79
+ const results = await rects.query(new SearchRequest({
80
+ query: queries,
81
+ sort: [new Sort({ key: "start1" }), new Sort({ key: "start2" })],
82
+ fetch: 0xffffffff
83
+ }))
84
+ return results.results.map(x => x.value)
85
+ } */
86
+ const containingPoint = (rects, point, roleAgeLimit, matured, now, options) => {
87
+ // point is between 0 and 1, and the range can start at any offset between 0 and 1 and have length between 0 and 1
88
+ // so we need to query for all ranges that contain the point
89
+ let pointScaled = Math.round(point * (options?.scaled ? 1 : SEGMENT_COORDINATE_SCALE));
90
+ let queries = [
91
+ new Or([
92
+ new And([
93
+ new IntegerCompare({
94
+ key: "start1",
95
+ compare: Compare.LessOrEqual,
96
+ value: pointScaled,
97
+ }),
98
+ new IntegerCompare({
99
+ key: "end1",
100
+ compare: Compare.Greater,
101
+ value: pointScaled,
102
+ }),
103
+ ]),
104
+ new And([
105
+ new IntegerCompare({
106
+ key: "start2",
107
+ compare: Compare.LessOrEqual,
108
+ value: pointScaled,
109
+ }),
110
+ new IntegerCompare({
111
+ key: "end2",
112
+ compare: Compare.Greater,
113
+ value: pointScaled,
114
+ }),
115
+ ]),
116
+ ]),
117
+ new IntegerCompare({
118
+ key: "timestamp",
119
+ compare: matured ? Compare.LessOrEqual : Compare.Greater,
120
+ value: BigInt(now - roleAgeLimit),
121
+ }),
122
+ ];
123
+ return iterate(rects, new SearchRequest({
124
+ query: queries,
125
+ sort: options?.sort,
126
+ fetch: 0xffffffff,
127
+ }));
128
+ /* const results = await rects.query(new SearchRequest({
129
+ query: queries,
130
+ sort: options?.sort,
131
+ fetch: 0xffffffff
132
+ }))
133
+ return results.results.map(x => x.value) */
22
134
  };
23
- const collectNodesAroundPoint = (time, roleAge, peers, currentNode, collector, point, done = () => true) => {
24
- /* let uniqueMatured = 0;
25
- */ const maybeIncrementMatured = (rect) => {
26
- const isMature = isMatured(rect.role, time, roleAge);
27
- collector(rect, isMature);
135
+ const getClosest = (direction, rects, point, roleAgeLimit, matured, now, scaled = false) => {
136
+ const scaledPoint = Math.round(point * (scaled ? 1 : SEGMENT_COORDINATE_SCALE));
137
+ const createQueries = (p, equality) => {
138
+ let queries;
139
+ if (direction === "below") {
140
+ queries = [
141
+ new IntegerCompare({
142
+ key: "end2",
143
+ compare: equality ? Compare.LessOrEqual : Compare.Less,
144
+ value: p,
145
+ }),
146
+ new IntegerCompare({
147
+ key: "timestamp",
148
+ compare: matured ? Compare.LessOrEqual : Compare.GreaterOrEqual,
149
+ value: BigInt(now - roleAgeLimit),
150
+ }),
151
+ ];
152
+ }
153
+ else {
154
+ queries = [
155
+ new IntegerCompare({
156
+ key: "start1",
157
+ compare: equality ? Compare.GreaterOrEqual : Compare.Greater,
158
+ value: p,
159
+ }),
160
+ new IntegerCompare({
161
+ key: "timestamp",
162
+ compare: matured ? Compare.LessOrEqual : Compare.GreaterOrEqual,
163
+ value: BigInt(now - roleAgeLimit),
164
+ }),
165
+ ];
166
+ }
167
+ queries.push(new IntegerCompare({ key: "width", compare: Compare.Greater, value: 0 }));
168
+ return queries;
28
169
  };
29
- // Assume peers does not mutate during this loop
30
- const startNode = currentNode;
31
- const diffs = [];
32
- while (currentNode) {
33
- if (containsPoint(currentNode.value.role, point)) {
34
- maybeIncrementMatured(currentNode.value);
35
- if (done(false)) {
36
- return;
170
+ const iterator = iterate(rects, new SearchRequest({
171
+ query: createQueries(scaledPoint, false),
172
+ sort: direction === "below"
173
+ ? new Sort({ key: ["end2"], direction: "desc" })
174
+ : new Sort({ key: ["start1"], direction: "asc" }),
175
+ }));
176
+ const iteratorWrapped = iterate(rects, new SearchRequest({
177
+ query: createQueries(direction === "below" ? SEGMENT_COORDINATE_SCALE : 0, true),
178
+ sort: direction === "below"
179
+ ? new Sort({ key: ["end2"], direction: "desc" })
180
+ : new Sort({ key: ["start1"], direction: "asc" }),
181
+ }));
182
+ return joinIterator([iterator, iteratorWrapped], scaledPoint, true, direction);
183
+ };
184
+ export const getDistance = (from, to, direction, end = SEGMENT_COORDINATE_SCALE) => {
185
+ // if direction is 'above' only measure distance from 'from to 'to' from above.
186
+ // i.e if from < to, then from needs to wrap around 0 to 1 and then to to
187
+ // if direction is 'below' and from > to, then from needs to wrap around 1 to 0 and then to to
188
+ // if direction is 'closest' then the shortest distance is the distance
189
+ // also from is 0.1 and to is 0.9, then distance should be 0.2 not 0.8
190
+ // same as for if from is 0.9 and to is 0.1, then distance should be 0.2 not 0.8
191
+ if (direction === "closest") {
192
+ if (from === to) {
193
+ return 0;
194
+ }
195
+ return Math.min(Math.abs(from - to), Math.abs(end - Math.abs(from - to)));
196
+ }
197
+ if (direction === "above") {
198
+ if (from <= to) {
199
+ return Math.abs(end - to) + from;
200
+ }
201
+ return from - to;
202
+ }
203
+ if (direction === "below") {
204
+ if (from >= to) {
205
+ return Math.abs(end - from) + to;
206
+ }
207
+ return to - from;
208
+ }
209
+ throw new Error("Invalid direction");
210
+ };
211
+ const joinIterator = (iterators, point, scaled, direction) => {
212
+ const scaledPoint = Math.round(point * (scaled ? 1 : SEGMENT_COORDINATE_SCALE));
213
+ let queues = [];
214
+ return {
215
+ next: async (count) => {
216
+ let results = {
217
+ kept: 0, // TODO
218
+ results: [],
219
+ };
220
+ for (let i = 0; i < iterators.length; i++) {
221
+ let queue = queues[i];
222
+ if (!queue) {
223
+ queue = { elements: [], kept: 0 };
224
+ queues[i] = queue;
225
+ }
226
+ let iterator = iterators[i];
227
+ if (queue.elements.length < count && iterator.done() === false) {
228
+ let res = await iterator.next(count);
229
+ queue.kept = res.kept;
230
+ for (const el of res.results) {
231
+ const closest = el.value;
232
+ let dist;
233
+ if (direction === "closest") {
234
+ dist = Math.min(getDistance(closest.start1, scaledPoint, direction), getDistance(closest.end2, scaledPoint, direction));
235
+ }
236
+ else if (direction === "above") {
237
+ dist = getDistance(closest.start1, scaledPoint, direction);
238
+ }
239
+ else if (direction === "below") {
240
+ dist = getDistance(closest.end2, scaledPoint, direction);
241
+ }
242
+ else {
243
+ throw new Error("Invalid direction");
244
+ }
245
+ queue.elements.push({ result: el, dist });
246
+ }
247
+ }
37
248
  }
38
- } /* if (matured === 0) */
39
- else {
40
- const start = currentNode.value.role.offset;
41
- const end = (currentNode.value.role.offset + currentNode.value.role.factor) % 1;
42
- const absDelta = Math.min(Math.abs(start - point), Math.abs(end - point));
43
- const diff = Math.min(absDelta, 1 - absDelta);
44
- diffs.push({
45
- diff: currentNode.value.role.factor > 0
46
- ? diff / currentNode.value.role.factor
47
- : Number.MAX_SAFE_INTEGER,
48
- rect: currentNode.value
49
- });
50
- }
51
- currentNode = currentNode.next || peers.head;
52
- if (currentNode?.value.publicKey &&
53
- startNode?.value.publicKey.equals(currentNode?.value.publicKey)) {
54
- break; // TODO throw error for failing to fetch ffull width
55
- }
56
- }
57
- if (done(true) == false) {
58
- diffs.sort((x, y) => x.diff - y.diff);
59
- for (const node of diffs) {
60
- maybeIncrementMatured(node.rect);
61
- if (done(true)) {
62
- break;
249
+ // pull the 'count' the closest element from one of the queue
250
+ for (let i = 0; i < count; i++) {
251
+ let closestQueue = -1;
252
+ let closestDist = Number.MAX_SAFE_INTEGER;
253
+ for (let j = 0; j < queues.length; j++) {
254
+ let queue = queues[j];
255
+ if (queue && queue.elements.length > 0) {
256
+ let closest = queue.elements[0];
257
+ if (closest.dist < closestDist) {
258
+ closestDist = closest.dist;
259
+ closestQueue = j;
260
+ }
261
+ }
262
+ }
263
+ if (closestQueue === -1) {
264
+ break;
265
+ }
266
+ let closest = queues[closestQueue]?.elements.shift();
267
+ if (closest) {
268
+ results.results.push(closest.result);
269
+ }
270
+ }
271
+ for (let i = 0; i < queues.length; i++) {
272
+ results.kept += queues[i].elements.length + queues[i].kept;
273
+ }
274
+ return results;
275
+ },
276
+ done: () => iterators.every((x) => x.done()),
277
+ close: async () => {
278
+ for (const iterator of iterators) {
279
+ await iterator.close();
280
+ }
281
+ },
282
+ all: async () => {
283
+ let results = [];
284
+ for (const iterator of iterators) {
285
+ let res = await iterator.all();
286
+ results.push(...res);
287
+ }
288
+ return results;
289
+ },
290
+ };
291
+ };
292
+ const getClosestAround = (peers, point, roleAge, now, scaled) => {
293
+ const closestBelow = getClosest("below", peers, point, roleAge, true, now, scaled);
294
+ const closestAbove = getClosest("above", peers, point, roleAge, true, now, scaled);
295
+ const containing = containingPoint(peers, point, roleAge, true, now, {
296
+ scaled: scaled,
297
+ });
298
+ return iteratorInSeries(containing, joinIterator([closestBelow, closestAbove], point, scaled, "closest"));
299
+ };
300
+ const collectNodesAroundPoint = async (roleAge, peers, collector, point, now, done = () => true) => {
301
+ const containing = containingPoint(peers, point, 0, true, now, {
302
+ scaled: false,
303
+ });
304
+ const allContaining = await containing.next(0xffffffff);
305
+ for (const rect of allContaining.results) {
306
+ collector(rect.value, isMatured(rect.value, now, roleAge));
307
+ }
308
+ if (done()) {
309
+ return;
310
+ }
311
+ const closestBelow = getClosest("below", peers, point, 0, true, now, false);
312
+ const closestAbove = getClosest("above", peers, point, 0, true, now, false);
313
+ const aroundIterator = joinIterator([closestBelow, closestAbove], point, false, "closest");
314
+ while (aroundIterator.done() === false && done() === false) {
315
+ const res = await aroundIterator.next(1);
316
+ for (const rect of res.results) {
317
+ collector(rect.value, isMatured(rect.value, now, roleAge));
318
+ if (done()) {
319
+ return;
63
320
  }
64
321
  }
65
322
  }
66
323
  };
67
- export const isMatured = (role, now, minAge) => {
68
- return now - Number(role.timestamp) >= minAge;
324
+ export const isMatured = (segment, now, minAge) => {
325
+ return now - Number(segment.timestamp) >= minAge;
69
326
  };
70
- export const getSamples = (cursor, peers, amount, roleAge) => {
327
+ export const getSamples = async (cursor, peers, amount, roleAge) => {
71
328
  const leaders = new Set();
72
329
  const width = 1;
73
- if (!peers || peers?.length === 0) {
330
+ if (!peers) {
74
331
  return [];
75
332
  }
76
- amount = Math.min(amount, peers.length);
77
- const t = +new Date();
333
+ const size = await peers.getSize();
334
+ amount = Math.min(amount, size);
335
+ if (amount === 0) {
336
+ return [];
337
+ }
338
+ const now = +new Date();
78
339
  const maturedLeaders = new Set();
79
340
  for (let i = 0; i < amount; i++) {
80
341
  // evenly distributed
81
342
  const point = ((cursor + i / amount) % 1) * width;
82
- const currentNode = peers.head;
83
343
  // aquire at least one unique node for each point
84
- // but if previous point yielded more than one node
85
- collectNodesAroundPoint(t, roleAge, peers, currentNode, (rect, m) => {
344
+ await collectNodesAroundPoint(roleAge, peers, (rect, m) => {
345
+ // console.log(m, rect.start1 / SEGMENT_COORDINATE_SCALE, rect.width / SEGMENT_COORDINATE_SCALE)
86
346
  if (m) {
87
- maturedLeaders.add(rect.publicKey.hashcode());
347
+ maturedLeaders.add(rect.hash);
88
348
  }
89
- leaders.add(rect.publicKey.hashcode());
90
- }, point, (postProcess) => {
91
- if (postProcess) {
92
- if (maturedLeaders.size > i) {
93
- return true;
94
- }
349
+ leaders.add(rect.hash);
350
+ }, point, now, () => {
351
+ if (maturedLeaders.size > i) {
352
+ return true;
95
353
  }
96
- return false; // collect all intersecting points
354
+ return false;
97
355
  });
98
356
  }
99
357
  return [...leaders];
100
358
  };
101
- export const getCover = (coveringWidth, peers, roleAge, startNodeIdentity) => {
102
- return [...getCoverSet(coveringWidth, peers, roleAge, startNodeIdentity)];
359
+ const fetchOne = async (iterator) => {
360
+ const value = await iterator.next(1);
361
+ await iterator.close();
362
+ return value.results[0]?.value;
103
363
  };
104
- export const getCoverSet = (coveringWidth, peers, roleAge, startNodeIdentity) => {
364
+ export const getCoverSet = async (coveringWidth, peers, roleAge, startNodeIdentity) => {
365
+ let now = +new Date();
105
366
  // find a good starting point
106
- let walker = peers.head;
367
+ let startNode = undefined;
107
368
  if (startNodeIdentity) {
108
369
  // start at our node (local first)
109
- while (walker) {
110
- if (walker.value.publicKey.equals(startNodeIdentity)) {
111
- break;
370
+ let result = await peers.query(new SearchRequest({
371
+ query: [
372
+ new StringMatch({ key: "hash", value: startNodeIdentity.hashcode() }),
373
+ ],
374
+ fetch: 1,
375
+ }));
376
+ startNode = result.results[0]?.value;
377
+ if (startNode) {
378
+ if (!isMatured(startNode, now, roleAge)) {
379
+ const matured = await fetchOne(getClosestAround(peers, startNode.start1, roleAge, now, true));
380
+ if (matured) {
381
+ startNode = matured;
382
+ }
112
383
  }
113
- walker = walker.next;
114
- }
115
- if (!walker) {
116
- walker = peers.head;
117
384
  }
118
385
  }
386
+ let startLocation;
387
+ if (!startNode) {
388
+ startLocation = Math.random() * SEGMENT_COORDINATE_SCALE;
389
+ startNode = await fetchOne(getClosestAround(peers, startLocation, roleAge, now, true));
390
+ }
119
391
  else {
120
- const seed = Math.round(peers.length * Math.random()); // start at a random point
121
- for (let i = 0; i < seed - 1; i++) {
122
- if (walker?.next == null) {
123
- break;
124
- }
125
- walker = walker.next;
126
- }
392
+ // TODO choose start location as the point with the longest range?
393
+ startLocation =
394
+ startNode.start1 ?? Math.random() * SEGMENT_COORDINATE_SCALE;
127
395
  }
128
- const startNode = walker;
396
+ /* const startNode = walker; */
129
397
  if (!startNode) {
130
398
  return new Set();
131
399
  }
400
+ let results = [];
401
+ let widthToCoverScaled = coveringWidth * SEGMENT_COORDINATE_SCALE;
402
+ const endLocation = (startLocation + widthToCoverScaled) % SEGMENT_COORDINATE_SCALE;
403
+ const endIsWrapped = endLocation <= startLocation;
404
+ const endRect = (await fetchOne(getClosestAround(peers, endLocation, roleAge, now, true))) || (await fetchOne(getClosestAround(peers, endLocation, 0, now, true))); // (await getClosest('above', peers, nextLocation, roleAge, true, 1, true))[0]
405
+ if (!endRect) {
406
+ return new Set();
407
+ }
408
+ let current =
409
+ /* (await getClosestAround(peers, startLocation, roleAge, 1, true))[0] */ startNode ||
410
+ (await fetchOne(getClosestAround(peers, startLocation, 0, now, true))); //(await getClosest('above', peers, startLocation, roleAge, true, 1, true))[0]
411
+ let coveredLength = current.width;
412
+ let nextLocation = current.end2;
413
+ // push edges
414
+ results.push(endRect);
415
+ results.push(current);
416
+ /* const endIsSameAsStart = equals(endRect.id, current.id); */
417
+ const resolveNextContaining = async (nextLocation, roleAge) => {
418
+ let next = await fetchOne(containingPoint(peers, nextLocation, roleAge, true, now, {
419
+ scaled: true,
420
+ sort: [new Sort({ key: "end2", direction: SortDirection.DESC })],
421
+ })); // get entersecting sort by largest end2
422
+ return next;
423
+ };
424
+ const resolveNextAbove = async (nextLocation, roleAge) => {
425
+ // if not get closest from above
426
+ let next = await fetchOne(getClosest("above", peers, nextLocation, roleAge, true, now, true));
427
+ return next;
428
+ };
429
+ const resolveNext = async (nextLocation, roleAge) => {
430
+ const containing = await resolveNextContaining(nextLocation, roleAge);
431
+ if (containing) {
432
+ return [containing, true];
433
+ }
434
+ return [await resolveNextAbove(nextLocation, roleAge), false];
435
+ };
436
+ // fill the middle
437
+ let wrappedOnce = current.end2 < current.end1;
438
+ let maturedCoveredLength = coveredLength;
439
+ /* let lastMatured = isMatured(startNode, now, roleAge) ? startNode : undefined;
440
+ */
441
+ while (maturedCoveredLength < widthToCoverScaled &&
442
+ coveredLength <= SEGMENT_COORDINATE_SCALE) {
443
+ let nextCandidate = await resolveNext(nextLocation, roleAge);
444
+ /* let fromAbove = false; */
445
+ let matured = true;
446
+ if (!nextCandidate[0]) {
447
+ matured = false;
448
+ nextCandidate = await resolveNext(nextLocation, 0);
449
+ /* fromAbove = true; */
450
+ }
451
+ if (!nextCandidate[0]) {
452
+ break;
453
+ }
454
+ current = nextCandidate[0];
455
+ let distanceBefore = coveredLength;
456
+ if (current.end2 < nextLocation) {
457
+ wrappedOnce = true;
458
+ coveredLength += SEGMENT_COORDINATE_SCALE - nextLocation;
459
+ coveredLength += current.end2;
460
+ }
461
+ else {
462
+ coveredLength += current.end1 - nextLocation;
463
+ }
464
+ let isLast = distanceBefore < widthToCoverScaled &&
465
+ coveredLength >= widthToCoverScaled;
466
+ if ((isLast &&
467
+ !nextCandidate[1]) /* || Math.min(current.start1, current.start2) > Math.min(endRect.start1, endRect.start2) */ /* (Math.min(current.start1, current.start2) > endLocation) */ ||
468
+ equals(endRect.id, current.id)) {
469
+ /* if ((isLast && ((endIsWrapped && wrappedOnce) || (!endIsWrapped))) && (current.start1 > endLocation || equals(current.id, endRect.id))) { */
470
+ // this is the end!
471
+ /* if (lastMatured && lastMatured.distanceTo(endLocation) < current.distanceTo(endLocation)) {
472
+ breaks;
473
+ } */
474
+ break;
475
+ }
476
+ /* if (fromAbove && next && next.start1 > endRect.start1 && (endIsWrapped === false || wrappedOnce)) {
477
+ break;
478
+ } */
479
+ // this is a skip condition to not include too many rects
480
+ if (matured) {
481
+ maturedCoveredLength = coveredLength;
482
+ /* lastMatured = current; */
483
+ }
484
+ results.push(current);
485
+ /*
486
+
487
+ if (current.start1 > endLocation && (wrappedOnce || !endIsWrapped)) {
488
+ break;
489
+ }
490
+
491
+ */
492
+ nextLocation = endIsWrapped
493
+ ? wrappedOnce
494
+ ? Math.min(current.end2, endLocation)
495
+ : current.end2
496
+ : Math.min(current.end2, endLocation);
497
+ }
498
+ const res = new Set(results.map((x) => x.hash));
499
+ startNodeIdentity && res.add(startNodeIdentity.hashcode());
500
+ return res;
132
501
  //
133
- const set = new Set();
502
+ /* const set: Set<string> = new Set();
134
503
  let currentNode = startNode;
135
504
  const t = +new Date();
505
+
136
506
  let wrappedOnce = false;
137
- const startPoint = startNode.value.role.offset;
138
- const getNextPoint = () => {
139
- let nextPoint = currentNode.value.role.offset + currentNode.value.role.factor;
507
+ const startPoint = startNode.segment.offset;
508
+
509
+ const getNextPoint = (): [number, number, number, boolean] => {
510
+ let nextPoint =
511
+ currentNode.segment.offset + currentNode.segment.factor;
512
+
140
513
  if (nextPoint > 1 || nextPoint < startPoint) {
141
514
  wrappedOnce = true;
142
515
  }
516
+
143
517
  nextPoint = nextPoint % 1;
144
- let distanceStart;
518
+ let distanceStart: number;
519
+
145
520
  if (wrappedOnce) {
146
- distanceStart = (1 - startPoint + currentNode.value.role.offset) % 1;
147
- }
148
- else {
149
- distanceStart = (currentNode.value.role.offset - startPoint) % 1;
521
+ distanceStart = (1 - startPoint + currentNode.segment.offset) % 1;
522
+ } else {
523
+ distanceStart = (currentNode.segment.offset - startPoint) % 1;
150
524
  }
151
- const distanceEnd = distanceStart + currentNode.value.role.factor;
525
+
526
+ const distanceEnd = distanceStart + currentNode.segment.factor;
527
+
152
528
  return [nextPoint, distanceStart, distanceEnd, wrappedOnce];
153
529
  };
154
- const getNextMatured = (from) => {
155
- let next = (from.next || peers.head);
156
- while (!next.value.publicKey.equals(from.value.publicKey) &&
157
- !next.value.publicKey.equals(startNode.value.publicKey)) {
158
- if (isMatured(next.value.role, t, roleAge)) {
530
+
531
+ const getNextMatured = async (from: ReplicatorRect) => {
532
+ let next = (await peers.query(new SearchRequest({ query: [new IntegerCompare({ key: ['segment', 'offset'], compare: Compare.Greater, value: from.segment.offset })], fetch: 1 })))?.results[0]?.value // (from.next || peers.head)!;
533
+ while (
534
+ next.hash !== from.hash &&
535
+ next.hash !== startNode.hash
536
+ ) {
537
+ if (isMatured(next.segment, t, roleAge)) {
159
538
  return next;
160
539
  }
161
- next = (next.next || peers.head);
540
+ next = (next.next || peers.head)!;
162
541
  }
163
542
  return undefined;
164
- };
543
+ }; */
165
544
  /**
166
545
  * The purpose of this loop is to cover at least coveringWidth
167
546
  * so that if we query all nodes in this range, we know we will
168
547
  * "query" all data in that range
169
548
  */
170
- let isPastThePoint = false;
549
+ /* let isPastThePoint = false;
171
550
  outer: while (currentNode) {
172
- if (set.has(currentNode.value.publicKey.hashcode()))
173
- break;
551
+ if (set.has(currentNode.hash)) break;
552
+
174
553
  const [nextPoint, distanceStart, distanceEnd, wrapped] = getNextPoint();
554
+
175
555
  if (distanceStart <= coveringWidth) {
176
- set.add(currentNode.value.publicKey.hashcode());
556
+ set.add(currentNode.hash);
177
557
  }
558
+
178
559
  if (distanceEnd >= coveringWidth) {
179
560
  break;
180
561
  }
562
+
181
563
  let next = currentNode.next || peers.head;
182
564
  while (next) {
183
565
  if (next.value.publicKey.equals(startNode.value.publicKey)) {
184
566
  break outer;
185
567
  }
186
- const prevOffset = (next.prev || peers.tail).value.role.offset;
568
+
569
+ const prevOffset = (next.prev || peers.tail)!.value.role.offset;
187
570
  const nextOffset = next.value.role.offset;
188
571
  const nextHasWrapped = nextOffset < prevOffset;
189
- if ((!wrapped && nextOffset > nextPoint) ||
572
+
573
+ if (
574
+ (!wrapped && nextOffset > nextPoint) ||
190
575
  (nextHasWrapped &&
191
576
  (wrapped ? nextOffset > nextPoint : prevOffset < nextPoint)) ||
192
- (!nextHasWrapped && prevOffset < nextPoint && nextPoint <= nextOffset)) {
577
+ (!nextHasWrapped && prevOffset < nextPoint && nextPoint <= nextOffset)
578
+ ) {
193
579
  isPastThePoint = true;
194
580
  }
581
+
195
582
  if (isPastThePoint) {
196
583
  break; // include this next in the set;
197
584
  }
585
+
198
586
  const overlapsRange = containsPoint(next.value.role, nextPoint);
587
+
199
588
  if (overlapsRange) {
200
589
  // Find out if there is a better choice ahead of us
201
- const nextNext = getNextMatured(next);
202
- if (nextNext &&
203
- !nextNext.value.publicKey.equals(currentNode.value.publicKey) &&
204
- nextNext.value.role.offset < nextPoint &&
205
- nextNext.value.role.offset + nextNext.value.role.factor > nextPoint) {
590
+ const nextNext = await getNextMatured(next);
591
+ if (
592
+ nextNext &&
593
+ nextNext.hash === currentNode.hash &&
594
+ nextNext.segment.offset < nextPoint &&
595
+ nextNext.segment.offset + nextNext.segment.factor > nextPoint
596
+ ) {
206
597
  // nextNext is better (continue to iterate)
207
- }
208
- else {
598
+ } else {
209
599
  // done
210
600
  break;
211
601
  }
212
- }
213
- else {
602
+ } else {
214
603
  // (continue to iterate)
215
604
  }
605
+
216
606
  next = next.next || peers.head;
217
607
  }
218
- currentNode = next;
219
- }
608
+ currentNode = next!;
609
+ } */
220
610
  // collect 1 point around the boundary of the start and one at the end,
221
611
  // preferrd matured and that we already have it
222
- for (const point of [
223
- startNode.value.role.offset,
224
- (startNode.value.role.offset + coveringWidth) % 1
612
+ /* for (const point of [
613
+ startNode.segment.offset,
614
+ (startNode.segment.offset + coveringWidth) % 1
225
615
  ]) {
226
616
  let done = false;
227
- const unmatured = [];
228
- collectNodesAroundPoint(t, roleAge, peers, isMatured(startNode.value.role, t, roleAge) ? startNode : peers.head, // start at startNode is matured, else start at head (we only seek to find one matured node at the point)
229
- (rect, matured) => {
230
- if (matured) {
231
- if (set.has(rect.publicKey.hashcode())) {
232
- // great!
233
- }
234
- else {
235
- set.add(rect.publicKey.hashcode());
617
+ const unmatured: string[] = [];
618
+ collectNodesAroundPoint(
619
+ t,
620
+ roleAge,
621
+ peers,
622
+ isMatured(startNode.segment, t, roleAge) ? startNode : peers.head, // start at startNode is matured, else start at head (we only seek to find one matured node at the point)
623
+ (rect, matured) => {
624
+ if (matured) {
625
+ if (set.has(rect.hash)) {
626
+ // great!
627
+ } else {
628
+ set.add(rect.hash);
629
+ }
630
+ done = true;
631
+ } else {
632
+ unmatured.push(rect.hash);
236
633
  }
237
- done = true;
238
- }
239
- else {
240
- unmatured.push(rect.publicKey.hashcode());
241
- }
242
- }, point, () => done);
634
+ },
635
+ point,
636
+ () => done
637
+ );
243
638
  if (!done && unmatured.length > 0) {
244
639
  set.add(unmatured[0]);
245
640
  // TODO add more elements?
246
641
  }
247
642
  }
248
- return set;
643
+ return set; */
249
644
  };
250
645
  //# sourceMappingURL=ranges.js.map