@peerbit/shared-log 9.2.13 → 10.0.0-05f4bef
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/get-samples.js +190 -64
- package/dist/benchmark/get-samples.js.map +1 -1
- package/dist/benchmark/index.js +16 -38
- package/dist/benchmark/index.js.map +1 -1
- package/dist/benchmark/memory/child.js.map +1 -1
- package/dist/benchmark/partial-sync.d.ts +3 -0
- package/dist/benchmark/partial-sync.d.ts.map +1 -0
- package/dist/benchmark/partial-sync.js +121 -0
- package/dist/benchmark/partial-sync.js.map +1 -0
- package/dist/benchmark/replication-prune.js.map +1 -1
- package/dist/benchmark/replication.js.map +1 -1
- package/dist/benchmark/to-rebalance.d.ts +2 -0
- package/dist/benchmark/to-rebalance.d.ts.map +1 -0
- package/dist/benchmark/to-rebalance.js +117 -0
- package/dist/benchmark/to-rebalance.js.map +1 -0
- package/dist/benchmark/utils.d.ts +24 -0
- package/dist/benchmark/utils.d.ts.map +1 -0
- package/dist/benchmark/utils.js +47 -0
- package/dist/benchmark/utils.js.map +1 -0
- package/dist/src/debounce.d.ts +2 -2
- package/dist/src/debounce.d.ts.map +1 -1
- package/dist/src/debounce.js +17 -47
- package/dist/src/debounce.js.map +1 -1
- package/dist/src/exchange-heads.d.ts +1 -13
- package/dist/src/exchange-heads.d.ts.map +1 -1
- package/dist/src/exchange-heads.js +0 -32
- package/dist/src/exchange-heads.js.map +1 -1
- package/dist/src/index.d.ts +119 -60
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1116 -762
- package/dist/src/index.js.map +1 -1
- package/dist/src/integers.d.ts +22 -0
- package/dist/src/integers.d.ts.map +1 -0
- package/dist/src/integers.js +76 -0
- package/dist/src/integers.js.map +1 -0
- package/dist/src/pid.d.ts.map +1 -1
- package/dist/src/pid.js +22 -22
- package/dist/src/pid.js.map +1 -1
- package/dist/src/ranges.d.ts +168 -38
- package/dist/src/ranges.d.ts.map +1 -1
- package/dist/src/ranges.js +869 -272
- package/dist/src/ranges.js.map +1 -1
- package/dist/src/replication-domain-hash.d.ts +2 -3
- package/dist/src/replication-domain-hash.d.ts.map +1 -1
- package/dist/src/replication-domain-hash.js +40 -15
- package/dist/src/replication-domain-hash.js.map +1 -1
- package/dist/src/replication-domain-time.d.ts +5 -5
- package/dist/src/replication-domain-time.d.ts.map +1 -1
- package/dist/src/replication-domain-time.js +2 -0
- package/dist/src/replication-domain-time.js.map +1 -1
- package/dist/src/replication-domain.d.ts +17 -19
- package/dist/src/replication-domain.d.ts.map +1 -1
- package/dist/src/replication-domain.js +2 -6
- package/dist/src/replication-domain.js.map +1 -1
- package/dist/src/replication.d.ts +6 -6
- package/dist/src/replication.d.ts.map +1 -1
- package/dist/src/replication.js +4 -4
- package/dist/src/replication.js.map +1 -1
- package/dist/src/role.d.ts +3 -6
- package/dist/src/role.d.ts.map +1 -1
- package/dist/src/role.js +4 -5
- package/dist/src/role.js.map +1 -1
- package/dist/src/sync/index.d.ts +40 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +2 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/sync/rateless-iblt.d.ts +124 -0
- package/dist/src/sync/rateless-iblt.d.ts.map +1 -0
- package/dist/src/sync/rateless-iblt.js +495 -0
- package/dist/src/sync/rateless-iblt.js.map +1 -0
- package/dist/src/sync/simple.d.ts +69 -0
- package/dist/src/sync/simple.d.ts.map +1 -0
- package/dist/src/sync/simple.js +338 -0
- package/dist/src/sync/simple.js.map +1 -0
- package/dist/src/sync/wasm-init.browser.d.ts +1 -0
- package/dist/src/sync/wasm-init.browser.d.ts.map +1 -0
- package/dist/src/sync/wasm-init.browser.js +3 -0
- package/dist/src/sync/wasm-init.browser.js.map +1 -0
- package/dist/src/sync/wasm-init.d.ts +2 -0
- package/dist/src/sync/wasm-init.d.ts.map +1 -0
- package/dist/src/sync/wasm-init.js +13 -0
- package/dist/src/sync/wasm-init.js.map +1 -0
- package/dist/src/utils.d.ts +3 -3
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +2 -2
- package/dist/src/utils.js.map +1 -1
- package/package.json +73 -69
- package/src/debounce.ts +16 -51
- package/src/exchange-heads.ts +1 -23
- package/src/index.ts +1532 -1038
- package/src/integers.ts +102 -0
- package/src/pid.ts +23 -22
- package/src/ranges.ts +1204 -413
- package/src/replication-domain-hash.ts +43 -18
- package/src/replication-domain-time.ts +9 -9
- package/src/replication-domain.ts +21 -31
- package/src/replication.ts +10 -9
- package/src/role.ts +4 -6
- package/src/sync/index.ts +51 -0
- package/src/sync/rateless-iblt.ts +617 -0
- package/src/sync/simple.ts +403 -0
- package/src/sync/wasm-init.browser.ts +1 -0
- package/src/sync/wasm-init.ts +14 -0
- package/src/utils.ts +10 -4
|
@@ -1,41 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BinaryWriter } from "@dao-xyz/borsh";
|
|
2
2
|
import { sha256 } from "@peerbit/crypto";
|
|
3
3
|
import type { ShallowOrFullEntry } from "@peerbit/log";
|
|
4
|
-
import
|
|
4
|
+
import { bytesToNumber } from "./integers.js";
|
|
5
|
+
import { type EntryReplicated } from "./ranges.js";
|
|
5
6
|
import {
|
|
6
7
|
type Log,
|
|
7
8
|
type ReplicationDomain,
|
|
8
9
|
type ReplicationDomainMapper,
|
|
9
10
|
} from "./replication-domain.js";
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
/* const hashToU32 = (hash: Uint8Array) => {
|
|
12
13
|
const seedNumber = new BinaryReader(
|
|
13
14
|
hash.subarray(hash.length - 4, hash.length),
|
|
14
15
|
).u32();
|
|
15
16
|
return seedNumber;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
const hashTransformer: ReplicationDomainMapper<any> = async (
|
|
19
|
-
entry: ShallowOrFullEntry<any> | EntryReplicated,
|
|
20
|
-
) => {
|
|
21
|
-
// For a fixed set or members, the choosen leaders will always be the same (address invariant)
|
|
22
|
-
// This allows for that same content is always chosen to be distributed to same peers, to remove unecessary copies
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
const hashToU64 = (hash: Uint8Array): bigint => {
|
|
21
|
+
const seedNumber = new BinaryReader(
|
|
22
|
+
hash.subarray(hash.length - 4, hash.length), //
|
|
23
|
+
).u64();
|
|
24
|
+
return seedNumber;
|
|
25
|
+
};
|
|
26
|
+
*/
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const hashTransformer = <R extends "u32" | "u64">(
|
|
29
|
+
resolution: R,
|
|
30
|
+
): ReplicationDomainMapper<any, R> => {
|
|
31
|
+
const numberConverter = bytesToNumber(resolution);
|
|
32
|
+
if (resolution === "u32") {
|
|
33
|
+
return (async (entry: ShallowOrFullEntry<any> | EntryReplicated<R>) => {
|
|
34
|
+
const utf8writer = new BinaryWriter();
|
|
35
|
+
utf8writer.string(entry.meta.gid);
|
|
36
|
+
const seed = await sha256(utf8writer.finalize());
|
|
37
|
+
return numberConverter(seed);
|
|
38
|
+
}) as ReplicationDomainMapper<any, R>;
|
|
39
|
+
} else if (resolution === "u64") {
|
|
40
|
+
return (async (entry: ShallowOrFullEntry<any> | EntryReplicated<R>) => {
|
|
41
|
+
const utf8writer = new BinaryWriter();
|
|
42
|
+
utf8writer.string(entry.meta.gid);
|
|
43
|
+
const seed = await sha256(utf8writer.finalize());
|
|
44
|
+
return numberConverter(seed);
|
|
45
|
+
}) as ReplicationDomainMapper<any, R>;
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error("Unsupported resolution");
|
|
48
|
+
}
|
|
32
49
|
};
|
|
33
50
|
|
|
34
|
-
export type ReplicationDomainHash = ReplicationDomain<
|
|
35
|
-
|
|
51
|
+
export type ReplicationDomainHash<R extends "u32" | "u64"> = ReplicationDomain<
|
|
52
|
+
undefined,
|
|
53
|
+
any,
|
|
54
|
+
R
|
|
55
|
+
>;
|
|
56
|
+
|
|
57
|
+
export const createReplicationDomainHash = <R extends "u32" | "u64">(
|
|
58
|
+
resolution: R,
|
|
59
|
+
): ReplicationDomainHash<R> => {
|
|
36
60
|
return {
|
|
61
|
+
resolution,
|
|
37
62
|
type: "hash",
|
|
38
|
-
fromEntry: hashTransformer,
|
|
63
|
+
fromEntry: hashTransformer<R>(resolution),
|
|
39
64
|
fromArgs: async (args: undefined, log: Log) => {
|
|
40
65
|
return {
|
|
41
66
|
offset: log.node.identity.publicKey,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { ShallowOrFullEntry } from "@peerbit/log";
|
|
2
|
-
import type
|
|
2
|
+
import { type EntryReplicated } from "./ranges.js";
|
|
3
3
|
import {
|
|
4
4
|
type ReplicationDomain,
|
|
5
5
|
type ReplicationDomainMapper,
|
|
6
|
-
type u32,
|
|
7
6
|
} from "./replication-domain.js";
|
|
8
7
|
|
|
9
8
|
type TimeUnit = "seconds" | "milliseconds" | "microseconds" | "nanoseconds";
|
|
@@ -24,11 +23,11 @@ const scalarMilliToUnit = {
|
|
|
24
23
|
export const fromEntry = (
|
|
25
24
|
origin: Date,
|
|
26
25
|
unit: TimeUnit = "milliseconds",
|
|
27
|
-
): ReplicationDomainMapper<any> => {
|
|
26
|
+
): ReplicationDomainMapper<any, "u32"> => {
|
|
28
27
|
const scalar = scalarNanoToUnit[unit];
|
|
29
28
|
const originTime = +origin / scalarMilliToUnit[unit];
|
|
30
29
|
|
|
31
|
-
const fn = (entry: ShallowOrFullEntry<any> | EntryReplicated) => {
|
|
30
|
+
const fn = (entry: ShallowOrFullEntry<any> | EntryReplicated<"u32">) => {
|
|
32
31
|
const cursor = entry.meta.clock.timestamp.wallTime / scalar;
|
|
33
32
|
return Math.round(Number(cursor) - originTime);
|
|
34
33
|
};
|
|
@@ -37,9 +36,9 @@ export const fromEntry = (
|
|
|
37
36
|
|
|
38
37
|
type TimeRange = { from: number; to: number };
|
|
39
38
|
|
|
40
|
-
export type ReplicationDomainTime = ReplicationDomain<TimeRange, any> & {
|
|
41
|
-
fromTime: (time: number | Date) =>
|
|
42
|
-
fromDuration: (duration: number) =>
|
|
39
|
+
export type ReplicationDomainTime = ReplicationDomain<TimeRange, any, "u32"> & {
|
|
40
|
+
fromTime: (time: number | Date) => number;
|
|
41
|
+
fromDuration: (duration: number) => number;
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
export const createReplicationDomainTime = (
|
|
@@ -48,16 +47,17 @@ export const createReplicationDomainTime = (
|
|
|
48
47
|
): ReplicationDomainTime => {
|
|
49
48
|
const originScaled = +origin * scalarMilliToUnit[unit];
|
|
50
49
|
const fromMilliToUnit = scalarMilliToUnit[unit];
|
|
51
|
-
const fromTime = (time: number | Date):
|
|
50
|
+
const fromTime = (time: number | Date): number => {
|
|
52
51
|
return (
|
|
53
52
|
(typeof time === "number" ? time : +time * fromMilliToUnit) - originScaled
|
|
54
53
|
);
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
const fromDuration = (duration: number):
|
|
56
|
+
const fromDuration = (duration: number): number => {
|
|
58
57
|
return duration;
|
|
59
58
|
};
|
|
60
59
|
return {
|
|
60
|
+
resolution: "u32",
|
|
61
61
|
type: "time",
|
|
62
62
|
fromTime,
|
|
63
63
|
fromDuration,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { PublicSignKey } from "@peerbit/crypto";
|
|
2
2
|
import { type Index } from "@peerbit/indexer-interface";
|
|
3
3
|
import type { Entry, ShallowEntry } from "@peerbit/log";
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
4
|
+
import { debounceAccumulator } from "./debounce.js";
|
|
5
|
+
import type { ReplicationRangeIndexable } from "./index.js";
|
|
6
|
+
import type { NumberFromType } from "./integers.js";
|
|
7
|
+
import type { EntryReplicated } from "./ranges.js";
|
|
6
8
|
import type { ReplicationLimits } from "./replication.js";
|
|
7
|
-
import { MAX_U32 } from "./role.js";
|
|
8
9
|
|
|
9
|
-
export type u32 =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
) => Promise<u32> | u32;
|
|
10
|
+
export type ReplicationDomainMapper<T, R extends "u32" | "u64"> = (
|
|
11
|
+
entry: Entry<T> | ShallowEntry | EntryReplicated<R>,
|
|
12
|
+
) => Promise<NumberFromType<R>> | NumberFromType<R>;
|
|
13
13
|
|
|
14
14
|
export type Log = {
|
|
15
15
|
replicas: ReplicationLimits;
|
|
@@ -18,8 +18,7 @@ export type Log = {
|
|
|
18
18
|
publicKey: PublicSignKey;
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
|
-
|
|
22
|
-
replicationIndex: Index<ReplicationRangeIndexable>;
|
|
21
|
+
replicationIndex: Index<ReplicationRangeIndexable<any>>;
|
|
23
22
|
getDefaultMinRoleAge: () => Promise<number>;
|
|
24
23
|
};
|
|
25
24
|
export type ReplicationDomainCoverSet<Args> = (
|
|
@@ -28,24 +27,24 @@ export type ReplicationDomainCoverSet<Args> = (
|
|
|
28
27
|
args: Args,
|
|
29
28
|
) => Promise<string[]> | string[]; // minimum set of peers that covers all the data
|
|
30
29
|
|
|
31
|
-
type CoverRange = {
|
|
32
|
-
offset:
|
|
33
|
-
length?:
|
|
30
|
+
type CoverRange<T extends number | bigint> = {
|
|
31
|
+
offset: T | PublicSignKey;
|
|
32
|
+
length?: T;
|
|
34
33
|
};
|
|
35
34
|
export type ReplicationChanges = ReplicationChange[];
|
|
36
35
|
export type ReplicationChange =
|
|
37
36
|
| {
|
|
38
37
|
type: "added";
|
|
39
|
-
range: ReplicationRangeIndexable
|
|
38
|
+
range: ReplicationRangeIndexable<any>;
|
|
40
39
|
}
|
|
41
40
|
| {
|
|
42
41
|
type: "removed";
|
|
43
|
-
range: ReplicationRangeIndexable
|
|
42
|
+
range: ReplicationRangeIndexable<any>;
|
|
44
43
|
}
|
|
45
44
|
| {
|
|
46
45
|
type: "updated";
|
|
47
|
-
range: ReplicationRangeIndexable
|
|
48
|
-
prev: ReplicationRangeIndexable
|
|
46
|
+
range: ReplicationRangeIndexable<any>;
|
|
47
|
+
prev: ReplicationRangeIndexable<any>;
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
export const mergeReplicationChanges = (
|
|
@@ -62,7 +61,7 @@ export const debounceAggregationChanges = (
|
|
|
62
61
|
fn: (changeOrChanges: ReplicationChange[]) => void,
|
|
63
62
|
delay: number,
|
|
64
63
|
) => {
|
|
65
|
-
return
|
|
64
|
+
return debounceAccumulator(
|
|
66
65
|
(result) => {
|
|
67
66
|
return fn([...result.values()]);
|
|
68
67
|
},
|
|
@@ -90,24 +89,15 @@ export const debounceAggregationChanges = (
|
|
|
90
89
|
);
|
|
91
90
|
};
|
|
92
91
|
|
|
93
|
-
export type ReplicationDomain<Args, T> = {
|
|
92
|
+
export type ReplicationDomain<Args, T, R extends "u32" | "u64"> = {
|
|
93
|
+
resolution: R;
|
|
94
94
|
type: string;
|
|
95
|
-
fromEntry: ReplicationDomainMapper<T>;
|
|
95
|
+
fromEntry: ReplicationDomainMapper<T, R>;
|
|
96
96
|
fromArgs: (
|
|
97
97
|
args: Args | undefined,
|
|
98
98
|
log: Log,
|
|
99
|
-
) => Promise<CoverRange
|
|
100
|
-
|
|
101
|
-
// to rebalance will return an async iterator of objects that will be added to the log
|
|
102
|
-
/* toRebalance(
|
|
103
|
-
change: ReplicationChange,
|
|
104
|
-
index: Index<EntryWithCoordinate>
|
|
105
|
-
): AsyncIterable<{ gid: string, entries: { coordinate: number, hash: string }[] }> | Promise<AsyncIterable<{ gid: string, entries: EntryWithCoordinate[] }>>; */
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export const uniformToU32 = (cursor: number) => {
|
|
109
|
-
return cursor * MAX_U32;
|
|
99
|
+
) => Promise<CoverRange<NumberFromType<R>>> | CoverRange<NumberFromType<R>>;
|
|
110
100
|
};
|
|
111
101
|
|
|
112
102
|
export type ExtractDomainArgs<T> =
|
|
113
|
-
T extends ReplicationDomain<infer Args, any> ? Args : never;
|
|
103
|
+
T extends ReplicationDomain<infer Args, any, any> ? Args : never;
|
package/src/replication.ts
CHANGED
|
@@ -11,8 +11,9 @@ import { type Index } from "@peerbit/indexer-interface";
|
|
|
11
11
|
import { TransportMessage } from "./message.js";
|
|
12
12
|
import {
|
|
13
13
|
ReplicationIntent,
|
|
14
|
-
ReplicationRange,
|
|
15
14
|
type ReplicationRangeIndexable,
|
|
15
|
+
ReplicationRangeMessage,
|
|
16
|
+
ReplicationRangeMessageU32,
|
|
16
17
|
} from "./ranges.js";
|
|
17
18
|
import { Observer, Replicator, Role } from "./role.js";
|
|
18
19
|
|
|
@@ -20,7 +21,7 @@ export type ReplicationLimits = { min: MinReplicas; max?: MinReplicas };
|
|
|
20
21
|
|
|
21
22
|
interface SharedLog {
|
|
22
23
|
replicas: Partial<ReplicationLimits>;
|
|
23
|
-
replicationIndex: Index<ReplicationRangeIndexable
|
|
24
|
+
replicationIndex: Index<ReplicationRangeIndexable<any>> | undefined;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export class MinReplicas {
|
|
@@ -67,7 +68,7 @@ export class ResponseRoleMessage extends TransportMessage {
|
|
|
67
68
|
segments:
|
|
68
69
|
this.role instanceof Replicator
|
|
69
70
|
? this.role.segments.map((x) => {
|
|
70
|
-
return new
|
|
71
|
+
return new ReplicationRangeMessageU32({
|
|
71
72
|
id: randomBytes(32),
|
|
72
73
|
offset: x.offset,
|
|
73
74
|
factor: x.factor,
|
|
@@ -82,10 +83,10 @@ export class ResponseRoleMessage extends TransportMessage {
|
|
|
82
83
|
|
|
83
84
|
@variant([1, 2])
|
|
84
85
|
export class AllReplicatingSegmentsMessage extends TransportMessage {
|
|
85
|
-
@field({ type: vec(
|
|
86
|
-
segments:
|
|
86
|
+
@field({ type: vec(ReplicationRangeMessage) })
|
|
87
|
+
segments: ReplicationRangeMessage<any>[];
|
|
87
88
|
|
|
88
|
-
constructor(properties: { segments:
|
|
89
|
+
constructor(properties: { segments: ReplicationRangeMessage<any>[] }) {
|
|
89
90
|
super();
|
|
90
91
|
this.segments = properties.segments;
|
|
91
92
|
}
|
|
@@ -93,10 +94,10 @@ export class AllReplicatingSegmentsMessage extends TransportMessage {
|
|
|
93
94
|
|
|
94
95
|
@variant([1, 3])
|
|
95
96
|
export class AddedReplicationSegmentMessage extends TransportMessage {
|
|
96
|
-
@field({ type: vec(
|
|
97
|
-
segments:
|
|
97
|
+
@field({ type: vec(ReplicationRangeMessage) })
|
|
98
|
+
segments: ReplicationRangeMessage<any>[];
|
|
98
99
|
|
|
99
|
-
constructor(properties: { segments:
|
|
100
|
+
constructor(properties: { segments: ReplicationRangeMessage<any>[] }) {
|
|
100
101
|
super();
|
|
101
102
|
this.segments = properties.segments;
|
|
102
103
|
}
|
package/src/role.ts
CHANGED
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
* Roles have been replaces with just replication segments.
|
|
5
5
|
*/
|
|
6
6
|
import { field, variant, vec } from "@dao-xyz/borsh";
|
|
7
|
-
|
|
8
|
-
export const MAX_U32 = 4294967295;
|
|
9
|
-
export const HALF_MAX_U32 = 2147483647; // rounded down
|
|
10
|
-
export const scaleToU32 = (value: number) => Math.round(MAX_U32 * value);
|
|
7
|
+
import { MAX_U32, denormalizer } from "./integers.js";
|
|
11
8
|
|
|
12
9
|
export const overlaps = (x1: number, x2: number, y1: number, y2: number) => {
|
|
13
10
|
if (x1 <= y2 && y1 <= x2) {
|
|
@@ -40,6 +37,7 @@ export class Observer extends Role {
|
|
|
40
37
|
|
|
41
38
|
export const REPLICATOR_TYPE_VARIANT = new Uint8Array([2]);
|
|
42
39
|
|
|
40
|
+
const denormalizeru32 = denormalizer("u32");
|
|
43
41
|
export class RoleReplicationSegment {
|
|
44
42
|
@field({ type: "u64" })
|
|
45
43
|
timestamp: bigint;
|
|
@@ -61,12 +59,12 @@ export class RoleReplicationSegment {
|
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
this.timestamp = timestamp ?? BigInt(+new Date());
|
|
64
|
-
this.factorNominator =
|
|
62
|
+
this.factorNominator = denormalizeru32(factor);
|
|
65
63
|
|
|
66
64
|
if (offset > 1 || offset < 0) {
|
|
67
65
|
throw new Error("Expecting offset to be between 0 and 1, got: " + offset);
|
|
68
66
|
}
|
|
69
|
-
this.offsetNominator =
|
|
67
|
+
this.offsetNominator = denormalizeru32(factor);
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
get factor(): number {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Cache } from "@peerbit/cache";
|
|
2
|
+
import type { PublicSignKey } from "@peerbit/crypto";
|
|
3
|
+
import type { Index } from "@peerbit/indexer-interface";
|
|
4
|
+
import type { Entry, Log } from "@peerbit/log";
|
|
5
|
+
import type { RPC, RequestContext } from "@peerbit/rpc";
|
|
6
|
+
import type { EntryWithRefs } from "../exchange-heads.js";
|
|
7
|
+
import type { Numbers } from "../integers.js";
|
|
8
|
+
import type { TransportMessage } from "../message.js";
|
|
9
|
+
import type { EntryReplicated, ReplicationRangeIndexable } from "../ranges.js";
|
|
10
|
+
|
|
11
|
+
export type SynchronizerComponents<R extends "u32" | "u64"> = {
|
|
12
|
+
rpc: RPC<TransportMessage, TransportMessage>;
|
|
13
|
+
rangeIndex: Index<ReplicationRangeIndexable<R>, any>;
|
|
14
|
+
entryIndex: Index<EntryReplicated<R>, any>;
|
|
15
|
+
log: Log<any>;
|
|
16
|
+
coordinateToHash: Cache<string>;
|
|
17
|
+
numbers: Numbers<R>;
|
|
18
|
+
};
|
|
19
|
+
export type SynchronizerConstructor<R extends "u32" | "u64"> = new (
|
|
20
|
+
properties: SynchronizerComponents<R>,
|
|
21
|
+
) => Syncronizer<R>;
|
|
22
|
+
|
|
23
|
+
export type SyncableKey = string | bigint; // hash or coordinate
|
|
24
|
+
|
|
25
|
+
export interface Syncronizer<R extends "u32" | "u64"> {
|
|
26
|
+
onMaybeMissingEntries(properties: {
|
|
27
|
+
entries: Map<string, EntryReplicated<R>>;
|
|
28
|
+
targets: string[];
|
|
29
|
+
}): Promise<void> | void;
|
|
30
|
+
|
|
31
|
+
onMessage(
|
|
32
|
+
message: TransportMessage,
|
|
33
|
+
context: RequestContext,
|
|
34
|
+
): Promise<boolean> | boolean;
|
|
35
|
+
|
|
36
|
+
onReceivedEntries(properties: {
|
|
37
|
+
entries: EntryWithRefs<any>[];
|
|
38
|
+
from: PublicSignKey;
|
|
39
|
+
}): Promise<void> | void;
|
|
40
|
+
|
|
41
|
+
onEntryAdded(entry: Entry<any>): void;
|
|
42
|
+
onEntryRemoved(hash: string): void;
|
|
43
|
+
onPeerDisconnected(key: PublicSignKey): void;
|
|
44
|
+
|
|
45
|
+
open(): Promise<void> | void;
|
|
46
|
+
close(): Promise<void> | void;
|
|
47
|
+
|
|
48
|
+
get pending(): number;
|
|
49
|
+
|
|
50
|
+
get syncInFlight(): Map<string, Map<SyncableKey, { timestamp: number }>>;
|
|
51
|
+
}
|