@peerbit/shared-log 10.3.8 → 10.3.9-17e5d15

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/package.json CHANGED
@@ -1,72 +1,72 @@
1
1
  {
2
- "name": "@peerbit/shared-log",
3
- "version": "10.3.8",
4
- "description": "Shared log",
5
- "sideEffects": false,
6
- "type": "module",
7
- "types": "./dist/src/index.d.ts",
8
- "typesVersions": {
9
- "*": {
10
- "*": [
11
- "*",
12
- "dist/*",
13
- "dist/src/*",
14
- "dist/src/*/index"
15
- ],
16
- "src/*": [
17
- "*",
18
- "dist/*",
19
- "dist/src/*",
20
- "dist/src/*/index"
21
- ]
22
- }
23
- },
24
- "files": [
25
- "src",
26
- "dist",
27
- "!dist/e2e",
28
- "!dist/test",
29
- "!**/*.tsbuildinfo"
30
- ],
31
- "exports": {
32
- ".": {
33
- "types": "./dist/src/index.d.ts",
34
- "import": "./dist/src/index.js"
35
- }
36
- },
37
- "eslintConfig": {
38
- "extends": "peerbit",
39
- "parserOptions": {
40
- "project": true,
41
- "sourceType": "module"
42
- },
43
- "ignorePatterns": [
44
- "!.aegir.js",
45
- "test/ts-use",
46
- "*.d.ts"
47
- ]
48
- },
49
- "publishConfig": {
50
- "access": "public"
51
- },
52
- "scripts": {
53
- "clean": "aegir clean",
54
- "build": "aegir build --no-bundle",
55
- "test": "aegir test --target node",
56
- "lint": "aegir lint"
57
- },
58
- "author": "dao.xyz",
59
- "license": "MIT",
60
- "dependencies": {
61
- "@dao-xyz/borsh": "^5.2.3",
62
- "@peerbit/logger": "1.0.3",
63
- "@peerbit/program": "5.1.2",
64
- "@peerbit/log": "4.0.30",
65
- "@peerbit/rpc": "5.0.28",
66
- "@peerbit/time": "2.0.7",
67
- "@peerbit/riblt": "1.0.4"
68
- },
69
- "devDependencies": {
70
- "@peerbit/test-utils": "^2.1.18"
71
- }
2
+ "name": "@peerbit/shared-log",
3
+ "version": "10.3.9-17e5d15",
4
+ "description": "Shared log",
5
+ "sideEffects": false,
6
+ "type": "module",
7
+ "types": "./dist/src/index.d.ts",
8
+ "typesVersions": {
9
+ "*": {
10
+ "*": [
11
+ "*",
12
+ "dist/*",
13
+ "dist/src/*",
14
+ "dist/src/*/index"
15
+ ],
16
+ "src/*": [
17
+ "*",
18
+ "dist/*",
19
+ "dist/src/*",
20
+ "dist/src/*/index"
21
+ ]
22
+ }
23
+ },
24
+ "files": [
25
+ "src",
26
+ "dist",
27
+ "!dist/e2e",
28
+ "!dist/test",
29
+ "!**/*.tsbuildinfo"
30
+ ],
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/src/index.d.ts",
34
+ "import": "./dist/src/index.js"
35
+ }
36
+ },
37
+ "eslintConfig": {
38
+ "extends": "peerbit",
39
+ "parserOptions": {
40
+ "project": true,
41
+ "sourceType": "module"
42
+ },
43
+ "ignorePatterns": [
44
+ "!.aegir.js",
45
+ "test/ts-use",
46
+ "*.d.ts"
47
+ ]
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "scripts": {
53
+ "clean": "aegir clean",
54
+ "build": "aegir build --no-bundle",
55
+ "test": "aegir test --target node",
56
+ "lint": "aegir lint"
57
+ },
58
+ "author": "dao.xyz",
59
+ "license": "MIT",
60
+ "dependencies": {
61
+ "@dao-xyz/borsh": "^5.2.3",
62
+ "@peerbit/logger": "1.0.3-17e5d15",
63
+ "@peerbit/program": "5.1.2-17e5d15",
64
+ "@peerbit/log": "4.0.30-17e5d15",
65
+ "@peerbit/rpc": "5.0.28-17e5d15",
66
+ "@peerbit/time": "2.0.7-17e5d15",
67
+ "@peerbit/riblt": "1.0.4-17e5d15"
68
+ },
69
+ "devDependencies": {
70
+ "@peerbit/test-utils": "2.1.18-17e5d15"
71
+ }
72
72
  }
package/src/index.ts CHANGED
@@ -87,6 +87,7 @@ import {
87
87
  ReplicationRangeIndexableU64,
88
88
  ReplicationRangeMessage,
89
89
  appromixateCoverage,
90
+ calculateCoverage,
90
91
  countCoveringRangesSameOwner,
91
92
  debounceAggregationChanges,
92
93
  getAllMergeCandiates,
@@ -2589,6 +2590,13 @@ export class SharedLog<
2589
2590
  });
2590
2591
  }
2591
2592
 
2593
+ async calculateCoverage() {
2594
+ return calculateCoverage({
2595
+ numbers: this.indexableDomain.numbers,
2596
+ peers: this.replicationIndex,
2597
+ });
2598
+ }
2599
+
2592
2600
  /* async calculateTotalParticipation() {
2593
2601
  const sum = await this.replicationIndex.sum({ key: "width" });
2594
2602
  return Number(sum) / MAX_U32;
package/src/integers.ts CHANGED
@@ -48,6 +48,7 @@ export interface Numbers<T extends "u32" | "u64"> {
48
48
  divRound: (a: NumberFromType<T>, b: number | bigint) => NumberFromType<T>;
49
49
  abs: (a: NumberFromType<T>) => NumberFromType<T>;
50
50
  min: (a: NumberFromType<T>, b: NumberFromType<T>) => NumberFromType<T>;
51
+ max: (a: NumberFromType<T>, b: NumberFromType<T>) => NumberFromType<T>;
51
52
  denormalize: (value: number) => NumberFromType<T>;
52
53
  bytesToNumber: (bytes: Uint8Array) => NumberFromType<T>;
53
54
  }
@@ -81,6 +82,7 @@ export const createNumbers = <N extends "u32" | "u64">(
81
82
  divRound: (a, b) => Math.round(a / Number(b)) as any,
82
83
  abs: (a) => Math.abs(a as number),
83
84
  min: (a, b) => Math.min(a as number, b as number),
85
+ max: (a, b) => Math.max(a as number, b as number),
84
86
  denormalize: denormalizerFn,
85
87
  bytesToNumber: bytesToNumber(resolution),
86
88
  } as Numbers<N>;
@@ -93,6 +95,7 @@ export const createNumbers = <N extends "u32" | "u64">(
93
95
  divRound: (a, b) => (a as bigint) / BigInt(b),
94
96
  abs: (a) => (a < 0n ? -a : a),
95
97
  min: (a, b) => (a < b ? a : b),
98
+ max: (a, b) => (a > b ? a : b),
96
99
  denormalize: denormalizerFn,
97
100
  bytesToNumber: bytesToNumber(resolution),
98
101
  } as Numbers<N>;
package/src/ranges.ts CHANGED
@@ -1355,6 +1355,66 @@ export const appromixateCoverage = async <R extends "u32" | "u64">(properties: {
1355
1355
  return hits / properties.samples;
1356
1356
  };
1357
1357
 
1358
+ export const calculateCoverage = async <R extends "u32" | "u64">(properties: {
1359
+ peers: Index<ReplicationRangeIndexable<R>>;
1360
+ numbers: Numbers<R>;
1361
+ }): Promise<number> => {
1362
+ const contentStart = properties.numbers.zero;
1363
+ const contentEnd = properties.numbers.maxValue;
1364
+ const endpoints: { point: NumberFromType<R>; delta: -1 | 1 }[] = [];
1365
+ let lastPoint = contentStart;
1366
+
1367
+ // For each range, record its start and end as events.
1368
+ for (const r of await properties.peers.iterate().all()) {
1369
+ endpoints.push({ point: r.value.start1, delta: +1 });
1370
+ endpoints.push({ point: r.value.end1, delta: -1 });
1371
+
1372
+ if (r.value.start1 !== r.value.start2) {
1373
+ endpoints.push({ point: r.value.start2, delta: +1 });
1374
+ endpoints.push({ point: r.value.end2, delta: -1 });
1375
+ }
1376
+ }
1377
+
1378
+ // Sort endpoints.
1379
+ // When points are equal, process a start (delta +1) before an end (delta -1)
1380
+ endpoints.sort((a, b) => {
1381
+ if (a.point === b.point) return b.delta - a.delta;
1382
+ return Number(a.point - b.point);
1383
+ });
1384
+
1385
+ let currentCoverage = 0;
1386
+ let minCoverage = Infinity;
1387
+
1388
+ // If the very start of the content space isn’t covered, return 0.
1389
+ if (endpoints.length === 0 || endpoints[0].point > contentStart) {
1390
+ return 0;
1391
+ }
1392
+
1393
+ // Process each endpoint, updating the current coverage.
1394
+ for (const e of endpoints) {
1395
+ // If there is an interval from lastPoint to this endpoint,
1396
+ // then the coverage in that entire segment was currentCoverage.
1397
+ if (e.point > lastPoint) {
1398
+ // Restrict to our content space.
1399
+ const segStart = properties.numbers.max(lastPoint, contentStart);
1400
+ const segEnd = properties.numbers.min(e.point, contentEnd);
1401
+ if (segStart < segEnd) {
1402
+ minCoverage = Math.min(minCoverage, currentCoverage);
1403
+ }
1404
+ lastPoint = e.point;
1405
+ }
1406
+ currentCoverage += e.delta;
1407
+ }
1408
+
1409
+ // Check if the last endpoint left a tail inside the content space.
1410
+ if (lastPoint < contentEnd) {
1411
+ minCoverage = Math.min(minCoverage, currentCoverage);
1412
+ }
1413
+
1414
+ // If any segment has zero coverage or nothing was covered, return 0.
1415
+ return minCoverage === Infinity || minCoverage <= 0 ? 0 : minCoverage;
1416
+ };
1417
+
1358
1418
  const getClosest = <S extends Shape | undefined, R extends "u32" | "u64">(
1359
1419
  direction: "above" | "below",
1360
1420
  rects: Index<ReplicationRangeIndexable<R>>,
@@ -476,7 +476,11 @@ export class RatelessIBLTSynchronizer<
476
476
  try {
477
477
  decoder.try_decode();
478
478
  } catch (error: any) {
479
- if (error?.message === "Invalid degree") {
479
+ if (
480
+ error?.message === "Invalid degree" ||
481
+ error === "Invalid degree"
482
+ ) {
483
+ // TODO in some way test this code path
480
484
  logger.error(error?.message);
481
485
  return false;
482
486
  } else {