@peerbit/shared-log 3.1.10 → 4.0.1
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/lib/esm/__benchmark__/index.js +12 -3
- package/lib/esm/__benchmark__/index.js.map +1 -1
- package/lib/esm/blocks.d.ts +6 -0
- package/lib/esm/blocks.js +29 -0
- package/lib/esm/blocks.js.map +1 -0
- package/lib/esm/exchange-heads.d.ts +0 -1
- package/lib/esm/exchange-heads.js +0 -1
- package/lib/esm/exchange-heads.js.map +1 -1
- package/lib/esm/index.d.ts +101 -42
- package/lib/esm/index.js +753 -249
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/replication.d.ts +28 -5
- package/lib/esm/replication.js +37 -2
- package/lib/esm/replication.js.map +1 -1
- package/lib/esm/role.d.ts +22 -2
- package/lib/esm/role.js +57 -9
- package/lib/esm/role.js.map +1 -1
- package/package.json +9 -8
- package/src/__benchmark__/index.ts +13 -4
- package/src/blocks.ts +19 -0
- package/src/exchange-heads.ts +1 -2
- package/src/index.ts +1097 -342
- package/src/replication.ts +49 -4
- package/src/role.ts +67 -6
package/src/replication.ts
CHANGED
|
@@ -3,11 +3,25 @@ import {
|
|
|
3
3
|
deserialize,
|
|
4
4
|
serialize,
|
|
5
5
|
field,
|
|
6
|
-
|
|
6
|
+
option,
|
|
7
|
+
BinaryReader
|
|
7
8
|
} from "@dao-xyz/borsh";
|
|
9
|
+
import { TransportMessage } from "./message.js";
|
|
10
|
+
import { Observer, Replicator, Role } from "./role.js";
|
|
11
|
+
import { PublicSignKey } from "@peerbit/crypto";
|
|
12
|
+
import yallist from "yallist";
|
|
13
|
+
|
|
14
|
+
export type ReplicationLimits = { min: MinReplicas; max?: MinReplicas };
|
|
15
|
+
|
|
16
|
+
export type ReplicatorRect = {
|
|
17
|
+
publicKey: PublicSignKey;
|
|
18
|
+
offset: number;
|
|
19
|
+
role: Replicator;
|
|
20
|
+
};
|
|
8
21
|
|
|
9
22
|
interface SharedLog {
|
|
10
|
-
|
|
23
|
+
replicas: Partial<ReplicationLimits>;
|
|
24
|
+
getReplicatorsSorted(): yallist<ReplicatorRect> | undefined;
|
|
11
25
|
}
|
|
12
26
|
|
|
13
27
|
export class MinReplicas {
|
|
@@ -30,6 +44,25 @@ export class AbsoluteReplicas extends MinReplicas {
|
|
|
30
44
|
}
|
|
31
45
|
}
|
|
32
46
|
|
|
47
|
+
@variant([1, 0])
|
|
48
|
+
export class RequestRoleMessage extends TransportMessage {
|
|
49
|
+
constructor() {
|
|
50
|
+
super();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@variant([1, 1])
|
|
55
|
+
export class ResponseRoleMessage extends TransportMessage {
|
|
56
|
+
@field({ type: option(Role) })
|
|
57
|
+
role: Observer | Replicator;
|
|
58
|
+
|
|
59
|
+
constructor(role: Observer | Replicator) {
|
|
60
|
+
super();
|
|
61
|
+
|
|
62
|
+
this.role = role;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
33
66
|
/*
|
|
34
67
|
@variant(1)
|
|
35
68
|
export class RelativeMinReplicas extends MinReplicas {
|
|
@@ -65,11 +98,23 @@ export const decodeReplicas = (entry: {
|
|
|
65
98
|
|
|
66
99
|
export const maxReplicas = (
|
|
67
100
|
log: SharedLog,
|
|
68
|
-
entries:
|
|
101
|
+
entries:
|
|
102
|
+
| { meta: { data?: Uint8Array } }[]
|
|
103
|
+
| IterableIterator<{ meta: { data?: Uint8Array } }>
|
|
69
104
|
) => {
|
|
70
105
|
let max = 0;
|
|
71
106
|
for (const entry of entries) {
|
|
72
107
|
max = Math.max(decodeReplicas(entry).getValue(log), max);
|
|
73
108
|
}
|
|
74
|
-
|
|
109
|
+
const lower = log.replicas.min?.getValue(log) || 1;
|
|
110
|
+
const higher = log.replicas.max?.getValue(log) ?? Number.MAX_SAFE_INTEGER;
|
|
111
|
+
const numberOfLeaders = Math.max(Math.min(higher, max), lower);
|
|
112
|
+
return numberOfLeaders;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const hashToUniformNumber = (hash: Uint8Array) => {
|
|
116
|
+
const seedNumber = new BinaryReader(
|
|
117
|
+
hash.subarray(hash.length - 4, hash.length)
|
|
118
|
+
).u32();
|
|
119
|
+
return seedNumber / 0xffffffff; // bounded between 0 and 1
|
|
75
120
|
};
|
package/src/role.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { field, variant } from "@dao-xyz/borsh";
|
|
1
|
+
import { field, option, variant, vec } from "@dao-xyz/borsh";
|
|
2
2
|
|
|
3
3
|
export abstract class Role {}
|
|
4
4
|
|
|
@@ -8,19 +8,80 @@ export const NO_TYPE_VARIANT = new Uint8Array([0]);
|
|
|
8
8
|
export class NoType extends Role {}
|
|
9
9
|
|
|
10
10
|
export const OBSERVER_TYPE_VARIANT = new Uint8Array([1]);
|
|
11
|
+
|
|
11
12
|
@variant(1)
|
|
12
13
|
export class Observer extends Role {}
|
|
13
14
|
|
|
14
15
|
export const REPLICATOR_TYPE_VARIANT = new Uint8Array([2]);
|
|
15
16
|
|
|
17
|
+
class ReplicationSegment {
|
|
18
|
+
@field({ type: "u64" })
|
|
19
|
+
timestamp: bigint;
|
|
20
|
+
|
|
21
|
+
@field({ type: "u32" })
|
|
22
|
+
private factorNominator: number;
|
|
23
|
+
|
|
24
|
+
@field({ type: option("u32") })
|
|
25
|
+
private offsetNominator?: number;
|
|
26
|
+
|
|
27
|
+
constructor(properties: {
|
|
28
|
+
factor: number;
|
|
29
|
+
timestamp?: bigint;
|
|
30
|
+
offset?: number;
|
|
31
|
+
}) {
|
|
32
|
+
const { factor, timestamp, offset } = properties;
|
|
33
|
+
if (factor > 1 || factor < 0) {
|
|
34
|
+
throw new Error("Expecting factor to be between 0 and 1, got: " + factor);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.timestamp = timestamp ?? BigInt(+new Date());
|
|
38
|
+
this.factorNominator = Math.round(4294967295 * factor);
|
|
39
|
+
|
|
40
|
+
if (offset != null) {
|
|
41
|
+
if (offset > 1 || offset < 0) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
"Expecting offset to be between 0 and 1, got: " + offset
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
this.offsetNominator = Math.round(4294967295 * offset);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get factor(): number {
|
|
51
|
+
return this.factorNominator / 4294967295;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get offset(): number | undefined {
|
|
55
|
+
return this.offsetNominator != null
|
|
56
|
+
? this.offsetNominator / 4294967295
|
|
57
|
+
: undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
16
61
|
@variant(2)
|
|
17
62
|
export class Replicator extends Role {
|
|
18
|
-
@field({ type:
|
|
19
|
-
|
|
63
|
+
@field({ type: vec(ReplicationSegment) })
|
|
64
|
+
segments: ReplicationSegment[];
|
|
20
65
|
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
66
|
+
constructor(properties: {
|
|
67
|
+
factor: number;
|
|
68
|
+
timestamp?: bigint;
|
|
69
|
+
offset?: number;
|
|
70
|
+
}) {
|
|
23
71
|
super();
|
|
24
|
-
|
|
72
|
+
const segment: ReplicationSegment = new ReplicationSegment(properties);
|
|
73
|
+
this.segments = [segment];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get factor(): number {
|
|
77
|
+
return this.segments[0]!.factor;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get offset(): number | undefined {
|
|
81
|
+
return this.segments[0]!.offset;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get timestamp(): bigint {
|
|
85
|
+
return this.segments[0]!.timestamp;
|
|
25
86
|
}
|
|
26
87
|
}
|