@peerbit/shared-log 8.0.7 → 9.0.0-2bc15a6

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 (79) 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.d.ts +2 -0
  6. package/dist/benchmark/index.d.ts.map +1 -0
  7. package/{lib/esm/__benchmark__ → dist/benchmark}/index.js +16 -16
  8. package/dist/benchmark/index.js.map +1 -0
  9. package/dist/benchmark/replication-prune.d.ts +2 -0
  10. package/dist/benchmark/replication-prune.d.ts.map +1 -0
  11. package/dist/benchmark/replication-prune.js +103 -0
  12. package/dist/benchmark/replication-prune.js.map +1 -0
  13. package/dist/benchmark/replication.d.ts +2 -0
  14. package/dist/benchmark/replication.d.ts.map +1 -0
  15. package/dist/benchmark/replication.js +91 -0
  16. package/dist/benchmark/replication.js.map +1 -0
  17. package/{lib/esm → dist/src}/blocks.d.ts +1 -0
  18. package/dist/src/blocks.d.ts.map +1 -0
  19. package/{lib/esm → dist/src}/blocks.js +1 -1
  20. package/dist/src/blocks.js.map +1 -0
  21. package/{lib/esm → dist/src}/cpu.d.ts +2 -1
  22. package/dist/src/cpu.d.ts.map +1 -0
  23. package/{lib/esm → dist/src}/cpu.js +2 -2
  24. package/dist/src/cpu.js.map +1 -0
  25. package/{lib/esm → dist/src}/exchange-heads.d.ts +2 -1
  26. package/dist/src/exchange-heads.d.ts.map +1 -0
  27. package/{lib/esm → dist/src}/exchange-heads.js +9 -7
  28. package/dist/src/exchange-heads.js.map +1 -0
  29. package/{lib/esm → dist/src}/index.d.ts +64 -54
  30. package/dist/src/index.d.ts.map +1 -0
  31. package/{lib/esm → dist/src}/index.js +569 -399
  32. package/dist/src/index.js.map +1 -0
  33. package/{lib/esm → dist/src}/message.d.ts +1 -0
  34. package/dist/src/message.d.ts.map +1 -0
  35. package/{lib/esm → dist/src}/pid.d.ts +1 -0
  36. package/dist/src/pid.d.ts.map +1 -0
  37. package/{lib/esm → dist/src}/pid.js +20 -20
  38. package/dist/src/pid.js.map +1 -0
  39. package/dist/src/ranges.d.ts +10 -0
  40. package/dist/src/ranges.d.ts.map +1 -0
  41. package/dist/src/ranges.js +645 -0
  42. package/dist/src/ranges.js.map +1 -0
  43. package/dist/src/replication.d.ts +112 -0
  44. package/dist/src/replication.d.ts.map +1 -0
  45. package/dist/src/replication.js +348 -0
  46. package/dist/src/replication.js.map +1 -0
  47. package/dist/src/role.d.ts +2 -0
  48. package/dist/src/role.d.ts.map +1 -0
  49. package/dist/src/role.js +106 -0
  50. package/dist/src/role.js.map +1 -0
  51. package/package.json +70 -43
  52. package/src/blocks.ts +1 -1
  53. package/src/cpu.ts +7 -6
  54. package/src/exchange-heads.ts +19 -19
  55. package/src/index.ts +881 -609
  56. package/src/pid.ts +22 -21
  57. package/src/ranges.ts +692 -148
  58. package/src/replication.ts +271 -19
  59. package/src/role.ts +63 -83
  60. package/LICENSE +0 -202
  61. package/lib/esm/__benchmark__/index.d.ts +0 -1
  62. package/lib/esm/__benchmark__/index.js.map +0 -1
  63. package/lib/esm/blocks.js.map +0 -1
  64. package/lib/esm/cpu.js.map +0 -1
  65. package/lib/esm/exchange-heads.js.map +0 -1
  66. package/lib/esm/index.js.map +0 -1
  67. package/lib/esm/pid.js.map +0 -1
  68. package/lib/esm/ranges.d.ts +0 -12
  69. package/lib/esm/ranges.js +0 -247
  70. package/lib/esm/ranges.js.map +0 -1
  71. package/lib/esm/replication.d.ts +0 -53
  72. package/lib/esm/replication.js +0 -105
  73. package/lib/esm/replication.js.map +0 -1
  74. package/lib/esm/role.d.ts +0 -38
  75. package/lib/esm/role.js +0 -130
  76. package/lib/esm/role.js.map +0 -1
  77. package/src/__benchmark__/index.ts +0 -115
  78. /package/{lib/esm → dist/src}/message.js +0 -0
  79. /package/{lib/esm → dist/src}/message.js.map +0 -0
@@ -1,26 +1,255 @@
1
1
  import {
2
- variant,
2
+ BinaryReader,
3
3
  deserialize,
4
- serialize,
5
4
  field,
6
- option,
7
- BinaryReader
5
+ serialize,
6
+ variant,
7
+ vec,
8
8
  } from "@dao-xyz/borsh";
9
+ import { PublicSignKey, equals, randomBytes } from "@peerbit/crypto";
10
+ import { type Index, id } from "@peerbit/indexer-interface";
9
11
  import { TransportMessage } from "./message.js";
10
- import { Observer, Replicator, Role } from "./role.js";
11
- import { PublicSignKey } from "@peerbit/crypto";
12
- import yallist from "yallist";
12
+ import { SEGMENT_COORDINATE_SCALE } from "./role.js";
13
13
 
14
14
  export type ReplicationLimits = { min: MinReplicas; max?: MinReplicas };
15
+ /*
16
+ export class ReplicatorRect {
17
+
18
+ @id({ type: Uint8Array })
19
+ id: Uint8Array;
20
+
21
+ @field({ type: 'string' })
22
+ hash: string;
23
+
24
+ @field({ type: vec(ReplicationSegment) })
25
+ segments: ReplicationSegment[];
26
+
27
+ constructor(properties: { hash: string; segments: ReplicationSegment[] }) {
28
+ this.id = randomBytes(32);
29
+ this.hash = properties.hash;
30
+ this.segments = properties.segments;
31
+ }
32
+ };
33
+ */
15
34
 
16
- export type ReplicatorRect = {
17
- publicKey: PublicSignKey;
18
- role: Replicator;
35
+ export enum ReplicationIntent {
36
+ Explicit = 0,
37
+ Automatic = 1,
38
+ }
39
+
40
+ export const getSegmentsFromOffsetAndRange = (
41
+ offset: number,
42
+ factor: number,
43
+ ): [[number, number], [number, number]] => {
44
+ let start1 = offset;
45
+ let end1Unscaled = offset + factor; // only add factor if it is not 1 to prevent numerical issues (like (0.9 + 1) % 1 => 0.8999999)
46
+ let end1 = Math.min(end1Unscaled, 1);
47
+ return [
48
+ [start1, end1],
49
+ end1Unscaled > 1
50
+ ? [0, (factor !== 1 ? offset + factor : offset) % 1]
51
+ : [start1, end1],
52
+ ];
19
53
  };
20
54
 
55
+ export class ReplicationRange {
56
+ @field({ type: Uint8Array })
57
+ private id: Uint8Array;
58
+
59
+ @field({ type: "u64" })
60
+ timestamp: bigint;
61
+
62
+ @field({ type: "u32" })
63
+ private _offset: number;
64
+
65
+ @field({ type: "u32" })
66
+ private _factor: number;
67
+
68
+ constructor(properties: {
69
+ id: Uint8Array;
70
+ offset: number;
71
+ factor: number;
72
+ timestamp: bigint;
73
+ }) {
74
+ const { id, offset, factor, timestamp } = properties;
75
+ this.id = id;
76
+ this._offset = Math.round(offset * SEGMENT_COORDINATE_SCALE);
77
+ this._factor = Math.round(factor * SEGMENT_COORDINATE_SCALE);
78
+ this.timestamp = timestamp;
79
+ }
80
+
81
+ get factor(): number {
82
+ return this._factor / SEGMENT_COORDINATE_SCALE;
83
+ }
84
+
85
+ get offset(): number {
86
+ return this._offset / SEGMENT_COORDINATE_SCALE;
87
+ }
88
+
89
+ toReplicationRangeIndexable(key: PublicSignKey): ReplicationRangeIndexable {
90
+ return new ReplicationRangeIndexable({
91
+ id: this.id,
92
+ publicKeyHash: key.hashcode(),
93
+ offset: this.offset,
94
+ length: this.factor,
95
+ timestamp: this.timestamp,
96
+ });
97
+ }
98
+ }
99
+
100
+ export class ReplicationRangeIndexable {
101
+ @id({ type: Uint8Array })
102
+ id: Uint8Array;
103
+
104
+ @field({ type: "string" })
105
+ hash: string;
106
+
107
+ @field({ type: "u64" })
108
+ timestamp: bigint;
109
+
110
+ @field({ type: "u32" })
111
+ start1: number;
112
+
113
+ @field({ type: "u32" })
114
+ end1: number;
115
+
116
+ @field({ type: "u32" })
117
+ start2: number;
118
+
119
+ @field({ type: "u32" })
120
+ end2: number;
121
+
122
+ @field({ type: "u32" })
123
+ width: number;
124
+
125
+ @field({ type: "u8" })
126
+ replicationIntent: ReplicationIntent;
127
+
128
+ constructor(
129
+ properties: {
130
+ id?: Uint8Array;
131
+
132
+ offset: number;
133
+ length: number;
134
+ replicationIntent?: ReplicationIntent;
135
+ timestamp?: bigint;
136
+ } & ({ publicKeyHash: string } | { publicKey: PublicSignKey }),
137
+ ) {
138
+ this.id = properties.id ?? randomBytes(32);
139
+ this.hash =
140
+ (properties as { publicKeyHash: string }).publicKeyHash ||
141
+ (properties as { publicKey: PublicSignKey }).publicKey.hashcode();
142
+ this.transform({ length: properties.length, offset: properties.offset });
143
+ this.replicationIntent =
144
+ properties.replicationIntent ?? ReplicationIntent.Explicit;
145
+ this.timestamp = properties.timestamp || BigInt(0);
146
+ }
147
+
148
+ private transform(properties: { offset: number; length: number }) {
149
+ const ranges = getSegmentsFromOffsetAndRange(
150
+ properties.offset,
151
+ properties.length,
152
+ );
153
+ this.start1 = Math.round(ranges[0][0] * SEGMENT_COORDINATE_SCALE);
154
+ this.end1 = Math.round(ranges[0][1] * SEGMENT_COORDINATE_SCALE);
155
+ this.start2 = Math.round(ranges[1][0] * SEGMENT_COORDINATE_SCALE);
156
+ this.end2 = Math.round(ranges[1][1] * SEGMENT_COORDINATE_SCALE);
157
+
158
+ this.width =
159
+ this.end1 -
160
+ this.start1 +
161
+ (this.end2 < this.end1 ? this.end2 - this.start2 : 0);
162
+
163
+ if (
164
+ this.start1 > 0xffffffff ||
165
+ this.end1 > 0xffffffff ||
166
+ this.start2 > 0xffffffff ||
167
+ this.end2 > 0xffffffff ||
168
+ this.width > 0xffffffff
169
+ ) {
170
+ throw new Error("Segment coordinate out of bounds");
171
+ }
172
+ }
173
+
174
+ contains(point: number) {
175
+ return (
176
+ (point >= this.start1 && point < this.end1) ||
177
+ (point >= this.start2 && point < this.end2)
178
+ );
179
+ }
180
+
181
+ overlaps(other: ReplicationRangeIndexable, checkOther = true): boolean {
182
+ if (
183
+ this.contains(other.start1) ||
184
+ this.contains(other.start2) ||
185
+ this.contains(other.end1) ||
186
+ this.contains(other.end2)
187
+ ) {
188
+ return true;
189
+ }
190
+
191
+ if (checkOther) {
192
+ return other.overlaps(this, false);
193
+ }
194
+ return false;
195
+ }
196
+ toReplicationRange() {
197
+ return new ReplicationRange({
198
+ id: this.id,
199
+ offset: this.start1 / SEGMENT_COORDINATE_SCALE,
200
+ factor: this.width / SEGMENT_COORDINATE_SCALE,
201
+ timestamp: this.timestamp,
202
+ });
203
+ }
204
+
205
+ distanceTo(point: number) {
206
+ let wrappedPoint = SEGMENT_COORDINATE_SCALE - point;
207
+ return Math.min(
208
+ Math.abs(this.start1 - point),
209
+ Math.abs(this.end2 - point),
210
+ Math.abs(this.start1 - wrappedPoint),
211
+ Math.abs(this.end2 - wrappedPoint),
212
+ );
213
+ }
214
+ get wrapped() {
215
+ return this.end2 < this.end1;
216
+ }
217
+
218
+ get widthNormalized() {
219
+ return this.width / SEGMENT_COORDINATE_SCALE;
220
+ }
221
+
222
+ equals(other: ReplicationRangeIndexable) {
223
+ if (
224
+ equals(this.id, other.id) &&
225
+ this.hash === other.hash &&
226
+ this.timestamp === other.timestamp &&
227
+ this.replicationIntent === other.replicationIntent &&
228
+ this.start1 === other.start1 &&
229
+ this.end1 === other.end1 &&
230
+ this.start2 === other.start2 &&
231
+ this.end2 === other.end2 &&
232
+ this.width === other.width
233
+ ) {
234
+ return true;
235
+ }
236
+
237
+ return false;
238
+ }
239
+
240
+ toString() {
241
+ let roundToTwoDecimals = (num: number) => Math.round(num * 100) / 100;
242
+
243
+ if (Math.abs(this.start1 - this.start2) < 0.0001) {
244
+ return `([${roundToTwoDecimals(this.start1 / SEGMENT_COORDINATE_SCALE)}, ${roundToTwoDecimals(this.end1 / SEGMENT_COORDINATE_SCALE)}])`;
245
+ }
246
+ return `([${roundToTwoDecimals(this.start1 / SEGMENT_COORDINATE_SCALE)}, ${roundToTwoDecimals(this.end1 / SEGMENT_COORDINATE_SCALE)}] [${roundToTwoDecimals(this.start2 / SEGMENT_COORDINATE_SCALE)}, ${roundToTwoDecimals(this.end2 / SEGMENT_COORDINATE_SCALE)}])`;
247
+ }
248
+ }
249
+
21
250
  interface SharedLog {
22
251
  replicas: Partial<ReplicationLimits>;
23
- getReplicatorsSorted(): yallist<ReplicatorRect> | undefined;
252
+ replicationIndex: Index<ReplicationRangeIndexable> | undefined;
24
253
  }
25
254
 
26
255
  export class MinReplicas {
@@ -38,26 +267,49 @@ export class AbsoluteReplicas extends MinReplicas {
38
267
  super();
39
268
  this._value = value;
40
269
  }
270
+
41
271
  getValue(_log: SharedLog): number {
42
272
  return this._value;
43
273
  }
44
274
  }
45
275
 
46
276
  @variant([1, 0])
47
- export class RequestRoleMessage extends TransportMessage {
277
+ export class RequestReplicationInfoMessage extends TransportMessage {
48
278
  constructor() {
49
279
  super();
50
280
  }
51
281
  }
52
282
 
53
283
  @variant([1, 1])
54
- export class ResponseRoleMessage extends TransportMessage {
55
- @field({ type: option(Role) })
56
- role: Observer | Replicator;
284
+ export class ResponseReplicationInfoMessage extends TransportMessage {
285
+ @field({ type: vec(ReplicationRange) })
286
+ segments: ReplicationRange[];
287
+
288
+ constructor(properties: { segments: ReplicationRange[] }) {
289
+ super();
290
+ this.segments = properties.segments;
291
+ }
292
+ }
293
+
294
+ @variant([1, 2])
295
+ export class StartedReplicating extends TransportMessage {
296
+ @field({ type: vec(ReplicationRange) })
297
+ segments: ReplicationRange[];
298
+
299
+ constructor(properties: { segments: ReplicationRange[] }) {
300
+ super();
301
+ this.segments = properties.segments;
302
+ }
303
+ }
304
+
305
+ @variant([1, 3])
306
+ export class StoppedReplicating extends TransportMessage {
307
+ @field({ type: vec(Uint8Array) })
308
+ segmentIds: Uint8Array[];
57
309
 
58
- constructor(properties: { role: Observer | Replicator }) {
310
+ constructor(properties: { segmentIds: Uint8Array[] }) {
59
311
  super();
60
- this.role = properties.role;
312
+ this.segmentIds = properties.segmentIds;
61
313
  }
62
314
  }
63
315
 
@@ -98,7 +350,7 @@ export const maxReplicas = (
98
350
  log: SharedLog,
99
351
  entries:
100
352
  | { meta: { data?: Uint8Array } }[]
101
- | IterableIterator<{ meta: { data?: Uint8Array } }>
353
+ | IterableIterator<{ meta: { data?: Uint8Array } }>,
102
354
  ) => {
103
355
  let max = 0;
104
356
  for (const entry of entries) {
@@ -112,7 +364,7 @@ export const maxReplicas = (
112
364
 
113
365
  export const hashToUniformNumber = (hash: Uint8Array) => {
114
366
  const seedNumber = new BinaryReader(
115
- hash.subarray(hash.length - 4, hash.length)
367
+ hash.subarray(hash.length - 4, hash.length),
116
368
  ).u32();
117
369
  return seedNumber / 0xffffffff; // bounded between 0 and 1
118
370
  };
package/src/role.ts CHANGED
@@ -1,16 +1,16 @@
1
- import { field, variant, vec } from "@dao-xyz/borsh";
1
+ /* import { field, variant, vec } from "@dao-xyz/borsh"; */
2
2
 
3
- export const overlaps = (x1: number, x2: number, y1: number, y2: number) => {
3
+ /* export const overlaps = (x1: number, x2: number, y1: number, y2: number) => {
4
4
  if (x1 <= y2 && y1 <= x2) {
5
5
  return true;
6
6
  }
7
7
  return false;
8
- };
8
+ }; */
9
9
 
10
- export abstract class Role {
11
- abstract equals(other: Role);
10
+ /* export abstract class Role {
11
+ abstract equals(other: Role): boolean;
12
12
  }
13
-
13
+
14
14
  export const NO_TYPE_VARIANT = new Uint8Array([0]);
15
15
 
16
16
  @variant(0)
@@ -29,103 +29,83 @@ export class Observer extends Role {
29
29
  }
30
30
  }
31
31
 
32
- export const REPLICATOR_TYPE_VARIANT = new Uint8Array([2]);
32
+ export const REPLICATOR_TYPE_VARIANT = new Uint8Array([2]);*/
33
+
34
+ export const SEGMENT_COORDINATE_SCALE = 4294967295;
35
+ /* export class ReplicationSegment {
33
36
 
34
- export class ReplicationSegment {
35
37
  @field({ type: "u64" })
36
38
  timestamp: bigint;
37
39
 
38
40
  @field({ type: "u32" })
39
- private factorNominator: number;
41
+ start: number;
42
+
43
+ @field({ type: 'u32' })
44
+ end: number;
45
+
40
46
 
41
- @field({ type: "u32" })
42
- private offsetNominator: number;
43
47
 
44
48
  constructor(properties: {
45
- factor: number;
46
- offset: number;
47
- timestamp?: bigint;
49
+ start: number;
50
+ end: number;
51
+ timestamp: bigint;
48
52
  }) {
49
- const { factor, timestamp, offset } = properties;
50
- if (factor > 1 || factor < 0) {
51
- throw new Error("Expecting factor to be between 0 and 1, got: " + factor);
52
- }
53
+ const { start, end, timestamp } = properties;
53
54
 
54
- this.timestamp = timestamp ?? BigInt(+new Date());
55
- this.factorNominator = Math.round(4294967295 * factor);
56
-
57
- if (offset > 1 || offset < 0) {
58
- throw new Error("Expecting offset to be between 0 and 1, got: " + offset);
55
+ if (start > end) {
56
+ throw new Error("Range 'start' needs to be lower or equal to 'end'")
59
57
  }
60
- this.offsetNominator = Math.round(4294967295 * offset);
58
+ this.start = Math.round(start * SEGMENT_COORDINATE_SCALE);
59
+ this.end = Math.round(end * SEGMENT_COORDINATE_SCALE);
60
+ this.timestamp = timestamp
61
61
  }
62
62
 
63
- get factor(): number {
64
- return this.factorNominator / 4294967295;
65
- }
66
63
 
67
- get offset(): number {
68
- return this.offsetNominator / 4294967295;
69
- }
70
-
71
- overlaps(other: ReplicationSegment) {
72
- let x1 = this.offset;
73
- let x2 = this.offset + this.factor;
74
- let y1 = other.offset;
75
- let y2 = other.offset + other.factor;
76
- if (overlaps(x1, x2, y1, y2)) {
77
- return true;
78
- }
79
64
 
80
- if (x2 > 1 || y2 > 1) {
81
- if (x2 > 1) {
82
- x1 = 0;
83
- x2 = x2 % 1;
84
- }
85
- if (y2 > 1) {
86
- y1 = 0;
87
- y2 = y2 % 1;
88
- }
89
- if (overlaps(x1, x2, y1, y2)) {
90
- return true;
91
- }
92
- }
93
- return false;
94
- }
95
65
  }
66
+ */
67
+
68
+ /* abstract class Capacity { }
96
69
 
97
70
  @variant(2)
98
71
  export class Replicator extends Role {
99
- @field({ type: vec(ReplicationSegment) })
100
- segments: ReplicationSegment[];
101
72
 
102
- constructor(properties: {
103
- factor: number;
104
- timestamp?: bigint;
105
- offset: number;
106
- }) {
107
- super();
108
- const segment: ReplicationSegment = new ReplicationSegment(properties);
109
- this.segments = [segment];
110
- }
111
-
112
- get factor(): number {
113
- return this.segments[0]!.factor;
114
- }
115
-
116
- get offset(): number {
117
- return this.segments[0]!.offset;
118
- }
73
+ @field({ type: vec(Capacity) })
74
+ capacity: Capacity[];
119
75
 
120
- get timestamp(): bigint {
121
- return this.segments[0]!.timestamp;
122
- }
76
+ constructor(properties?: { capacity: Capacity[] }) {
77
+ super();
78
+ this.capacity = properties?.capacity || [];
79
+ } */
80
+
81
+ /* constructor(properties: {
82
+ timestamp?: bigint;
83
+ factor: number;
84
+ offset: number;
85
+ }) {
86
+ super();
87
+ let timestamp = properties.timestamp || BigInt(+new Date);
88
+ let ranges = getSegmentsFromOffsetAndRange(properties.offset, properties.factor);
89
+ this.segments = ranges.map(x => new ReplicationSegment({ start: x[0], end: x[1], timestamp }));
90
+ }
91
+ */
92
+ /* get factor(): number {
93
+ return this.segments[0]!.factor;
94
+ }
123
95
 
124
- equals(other: Role) {
125
- return (
126
- other instanceof Replicator &&
127
- other.factor === this.factor &&
128
- other.offset === this.offset
129
- );
130
- }
96
+ get offset(): number {
97
+ return this.segments[0]!.offset;
131
98
  }
99
+
100
+ get timestamp(): bigint {
101
+ return this.segments[0]!.timestamp;
102
+ } */
103
+
104
+ /* equals(other: Role) {
105
+ return (
106
+ other instanceof Replicator &&
107
+ other.factor === this.factor &&
108
+ other.offset === this.offset
109
+ );
110
+ } */
111
+ /* } */