@peerbit/shared-log 12.3.5 → 13.0.0-b712c6b
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/sync-batch-sweep.d.ts +2 -0
- package/dist/benchmark/sync-batch-sweep.d.ts.map +1 -0
- package/dist/benchmark/sync-batch-sweep.js +305 -0
- package/dist/benchmark/sync-batch-sweep.js.map +1 -0
- package/dist/src/fanout-envelope.d.ts +18 -0
- package/dist/src/fanout-envelope.d.ts.map +1 -0
- package/dist/src/fanout-envelope.js +85 -0
- package/dist/src/fanout-envelope.js.map +1 -0
- package/dist/src/index.d.ts +55 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1595 -339
- package/dist/src/index.js.map +1 -1
- package/dist/src/pid.d.ts.map +1 -1
- package/dist/src/pid.js +21 -5
- package/dist/src/pid.js.map +1 -1
- package/dist/src/ranges.d.ts +3 -1
- package/dist/src/ranges.d.ts.map +1 -1
- package/dist/src/ranges.js +14 -5
- package/dist/src/ranges.js.map +1 -1
- package/dist/src/sync/index.d.ts +45 -1
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/rateless-iblt.d.ts +13 -2
- package/dist/src/sync/rateless-iblt.d.ts.map +1 -1
- package/dist/src/sync/rateless-iblt.js +194 -3
- package/dist/src/sync/rateless-iblt.js.map +1 -1
- package/dist/src/sync/simple.d.ts +24 -3
- package/dist/src/sync/simple.d.ts.map +1 -1
- package/dist/src/sync/simple.js +330 -32
- package/dist/src/sync/simple.js.map +1 -1
- package/package.json +20 -20
- package/src/fanout-envelope.ts +27 -0
- package/src/index.ts +2162 -691
- package/src/pid.ts +22 -4
- package/src/ranges.ts +14 -4
- package/src/sync/index.ts +53 -1
- package/src/sync/rateless-iblt.ts +237 -4
- package/src/sync/simple.ts +427 -41
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-batch-sweep.d.ts","sourceRoot":"","sources":["../../benchmark/sync-batch-sweep.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// Benchmarks catch-up sync behavior while varying repair sweep batch size.
|
|
2
|
+
//
|
|
3
|
+
// Run with:
|
|
4
|
+
// cd packages/programs/data/shared-log
|
|
5
|
+
// SWEEP_BATCH_SIZES="256,512,1024,4096,16384,65536" SWEEP_ENTRY_COUNT=20000 \
|
|
6
|
+
// SWEEP_RUNS=1 SWEEP_TIMEOUT=120000 node --loader ts-node/esm ./benchmark/sync-batch-sweep.ts
|
|
7
|
+
//
|
|
8
|
+
// CI assertion env vars:
|
|
9
|
+
// - SWEEP_ASSERT_MAX_RATIO: max allowed (slowest_mean / fastest_mean)
|
|
10
|
+
// - SWEEP_ASSERT_REQUIRE_STARTSYNC_FOR_BATCH_GTE: require StartSync traffic for batches >= value
|
|
11
|
+
// - SWEEP_ASSERT_MAX_MEAN_MS: comma list "batch:maxMs,batch:maxMs"
|
|
12
|
+
import { keys } from "@libp2p/crypto";
|
|
13
|
+
import { TestSession } from "@peerbit/test-utils";
|
|
14
|
+
import { waitForResolved } from "@peerbit/time";
|
|
15
|
+
import { expect } from "chai";
|
|
16
|
+
import { performance } from "node:perf_hooks";
|
|
17
|
+
import { createReplicationDomainHash } from "../src/index.js";
|
|
18
|
+
import { MoreSymbols, RatelessIBLTSynchronizer, RequestAll, StartSync, } from "../src/sync/rateless-iblt.js";
|
|
19
|
+
import { RequestMaybeSync, RequestMaybeSyncCoordinate, } from "../src/sync/simple.js";
|
|
20
|
+
import { EventStore } from "../test/utils/stores/event-store.js";
|
|
21
|
+
const parsePositiveInteger = (value, fallback) => {
|
|
22
|
+
if (!value) {
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
const parsed = Number.parseInt(value, 10);
|
|
26
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
27
|
+
throw new Error(`Expected a positive integer, got '${value}'`);
|
|
28
|
+
}
|
|
29
|
+
return parsed;
|
|
30
|
+
};
|
|
31
|
+
const parseNonNegativeInteger = (value, fallback) => {
|
|
32
|
+
if (!value) {
|
|
33
|
+
return fallback;
|
|
34
|
+
}
|
|
35
|
+
const parsed = Number.parseInt(value, 10);
|
|
36
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
37
|
+
throw new Error(`Expected a non-negative integer, got '${value}'`);
|
|
38
|
+
}
|
|
39
|
+
return parsed;
|
|
40
|
+
};
|
|
41
|
+
const parseNumberList = (value, defaults) => {
|
|
42
|
+
if (!value)
|
|
43
|
+
return defaults;
|
|
44
|
+
const parsed = value
|
|
45
|
+
.split(",")
|
|
46
|
+
.map((x) => Number.parseInt(x.trim(), 10))
|
|
47
|
+
.filter((x) => Number.isFinite(x) && x > 0);
|
|
48
|
+
return parsed.length > 0 ? parsed : defaults;
|
|
49
|
+
};
|
|
50
|
+
const parseBatchThresholdMap = (value) => {
|
|
51
|
+
const thresholds = new Map();
|
|
52
|
+
if (!value)
|
|
53
|
+
return thresholds;
|
|
54
|
+
for (const token of value.split(",")) {
|
|
55
|
+
const [batchRaw, thresholdRaw] = token.split(":");
|
|
56
|
+
if (!batchRaw || !thresholdRaw) {
|
|
57
|
+
throw new Error(`Invalid SWEEP_ASSERT_MAX_MEAN_MS token '${token}', expected 'batch:maxMs'`);
|
|
58
|
+
}
|
|
59
|
+
const batch = Number.parseInt(batchRaw.trim(), 10);
|
|
60
|
+
const threshold = Number.parseFloat(thresholdRaw.trim());
|
|
61
|
+
if (!Number.isFinite(batch) || batch <= 0) {
|
|
62
|
+
throw new Error(`Invalid batch '${batchRaw}' in SWEEP_ASSERT_MAX_MEAN_MS token '${token}'`);
|
|
63
|
+
}
|
|
64
|
+
if (!Number.isFinite(threshold) || threshold <= 0) {
|
|
65
|
+
throw new Error(`Invalid threshold '${thresholdRaw}' in SWEEP_ASSERT_MAX_MEAN_MS token '${token}'`);
|
|
66
|
+
}
|
|
67
|
+
thresholds.set(batch, threshold);
|
|
68
|
+
}
|
|
69
|
+
return thresholds;
|
|
70
|
+
};
|
|
71
|
+
const parseOptionalPositiveFloat = (value) => {
|
|
72
|
+
if (!value) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const parsed = Number.parseFloat(value);
|
|
76
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
77
|
+
throw new Error(`Expected a positive number, got '${value}'`);
|
|
78
|
+
}
|
|
79
|
+
return parsed;
|
|
80
|
+
};
|
|
81
|
+
const parseOptionalPositiveInteger = (value) => {
|
|
82
|
+
if (!value) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const parsed = Number.parseInt(value, 10);
|
|
86
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
87
|
+
throw new Error(`Expected a positive integer, got '${value}'`);
|
|
88
|
+
}
|
|
89
|
+
return parsed;
|
|
90
|
+
};
|
|
91
|
+
const createEmptyCounters = () => ({
|
|
92
|
+
startSync: 0,
|
|
93
|
+
moreSymbols: 0,
|
|
94
|
+
requestAll: 0,
|
|
95
|
+
requestMaybeSync: 0,
|
|
96
|
+
requestMaybeSyncCoordinate: 0,
|
|
97
|
+
});
|
|
98
|
+
const mergeCounters = (left, right) => ({
|
|
99
|
+
startSync: left.startSync + right.startSync,
|
|
100
|
+
moreSymbols: left.moreSymbols + right.moreSymbols,
|
|
101
|
+
requestAll: left.requestAll + right.requestAll,
|
|
102
|
+
requestMaybeSync: left.requestMaybeSync + right.requestMaybeSync,
|
|
103
|
+
requestMaybeSyncCoordinate: left.requestMaybeSyncCoordinate + right.requestMaybeSyncCoordinate,
|
|
104
|
+
});
|
|
105
|
+
const attachMessageCounter = (store) => {
|
|
106
|
+
const counters = createEmptyCounters();
|
|
107
|
+
const original = store.log.onMessage.bind(store.log);
|
|
108
|
+
store.log.onMessage = async (msg, context) => {
|
|
109
|
+
if (msg instanceof StartSync)
|
|
110
|
+
counters.startSync += 1;
|
|
111
|
+
else if (msg instanceof MoreSymbols)
|
|
112
|
+
counters.moreSymbols += 1;
|
|
113
|
+
else if (msg instanceof RequestAll)
|
|
114
|
+
counters.requestAll += 1;
|
|
115
|
+
else if (msg instanceof RequestMaybeSync)
|
|
116
|
+
counters.requestMaybeSync += 1;
|
|
117
|
+
else if (msg instanceof RequestMaybeSyncCoordinate)
|
|
118
|
+
counters.requestMaybeSyncCoordinate += 1;
|
|
119
|
+
return original(msg, context);
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
read: () => ({ ...counters }),
|
|
123
|
+
restore: () => {
|
|
124
|
+
store.log.onMessage = original;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const fixedKeys = [
|
|
129
|
+
{
|
|
130
|
+
libp2p: {
|
|
131
|
+
privateKey: keys.privateKeyFromRaw(new Uint8Array([
|
|
132
|
+
204, 234, 187, 172, 226, 232, 70, 175, 62, 211, 147, 91, 229, 157,
|
|
133
|
+
168, 15, 45, 242, 144, 98, 75, 58, 208, 9, 223, 143, 251, 52, 252,
|
|
134
|
+
159, 64, 83, 52, 197, 24, 246, 24, 234, 141, 183, 151, 82, 53, 142,
|
|
135
|
+
57, 25, 148, 150, 26, 209, 223, 22, 212, 40, 201, 6, 191, 72, 148, 82,
|
|
136
|
+
66, 138, 199, 185,
|
|
137
|
+
])),
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
libp2p: {
|
|
142
|
+
privateKey: keys.privateKeyFromRaw(new Uint8Array([
|
|
143
|
+
237, 55, 205, 86, 40, 44, 73, 169, 196, 118, 36, 69, 214, 122, 28,
|
|
144
|
+
157, 208, 163, 15, 215, 104, 193, 151, 177, 62, 231, 253, 120, 122,
|
|
145
|
+
222, 174, 242, 120, 50, 165, 97, 8, 235, 97, 186, 148, 251, 100, 168,
|
|
146
|
+
49, 10, 119, 71, 246, 246, 174, 163, 198, 54, 224, 6, 174, 212, 159,
|
|
147
|
+
187, 2, 137, 47, 192,
|
|
148
|
+
])),
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
const setup = {
|
|
153
|
+
domain: createReplicationDomainHash("u64"),
|
|
154
|
+
type: "u64",
|
|
155
|
+
syncronizer: RatelessIBLTSynchronizer,
|
|
156
|
+
name: "u64-iblt",
|
|
157
|
+
};
|
|
158
|
+
const runCatchup = async (properties) => {
|
|
159
|
+
const session = await TestSession.disconnected(2, fixedKeys);
|
|
160
|
+
const store = new EventStore();
|
|
161
|
+
let db1;
|
|
162
|
+
let db2;
|
|
163
|
+
let counter1;
|
|
164
|
+
let counter2;
|
|
165
|
+
try {
|
|
166
|
+
db1 = await session.peers[0].open(store.clone(), {
|
|
167
|
+
args: {
|
|
168
|
+
replicate: { factor: 2 },
|
|
169
|
+
setup,
|
|
170
|
+
sync: {
|
|
171
|
+
repairSweepTargetBufferSize: properties.batchSize,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
// Preload while only a single replica is active to avoid delivery-timeout
|
|
176
|
+
// artifacts when very large entry counts are written offline.
|
|
177
|
+
for (let i = 0; i < properties.entryCount; i++) {
|
|
178
|
+
await db1.add(`entry-${i}`, { meta: { next: [] } });
|
|
179
|
+
}
|
|
180
|
+
expect(db1.log.log.length).to.equal(properties.entryCount);
|
|
181
|
+
db2 = await session.peers[1].open(store.clone(), {
|
|
182
|
+
args: {
|
|
183
|
+
replicate: { factor: 2 },
|
|
184
|
+
setup,
|
|
185
|
+
sync: {
|
|
186
|
+
repairSweepTargetBufferSize: properties.batchSize,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
expect(db2.log.log.length).to.equal(0);
|
|
191
|
+
counter1 = attachMessageCounter(db1);
|
|
192
|
+
counter2 = attachMessageCounter(db2);
|
|
193
|
+
await waitForResolved(() => session.peers[0].dial(session.peers[1].getMultiaddrs()));
|
|
194
|
+
const t0 = performance.now();
|
|
195
|
+
await waitForResolved(() => expect(db2.log.log.length).to.equal(properties.entryCount), { timeout: properties.timeoutMs, delayInterval: 250 });
|
|
196
|
+
const catchupMs = performance.now() - t0;
|
|
197
|
+
const counters = mergeCounters(counter1.read(), counter2.read());
|
|
198
|
+
return { catchupMs, counters };
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
counter1?.restore();
|
|
202
|
+
counter2?.restore();
|
|
203
|
+
await session.stop();
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const mean = (values) => values.reduce((acc, value) => acc + value, 0) / values.length;
|
|
207
|
+
const batchSizes = parseNumberList(process.env.SWEEP_BATCH_SIZES, [
|
|
208
|
+
256,
|
|
209
|
+
512,
|
|
210
|
+
1024,
|
|
211
|
+
4096,
|
|
212
|
+
16384,
|
|
213
|
+
65536,
|
|
214
|
+
]);
|
|
215
|
+
const entryCount = parsePositiveInteger(process.env.SWEEP_ENTRY_COUNT, 20_000);
|
|
216
|
+
const timeoutMs = parsePositiveInteger(process.env.SWEEP_TIMEOUT, 120_000);
|
|
217
|
+
const warmupRuns = parseNonNegativeInteger(process.env.SWEEP_WARMUP_RUNS, 0);
|
|
218
|
+
const measuredRuns = parsePositiveInteger(process.env.SWEEP_RUNS, 1);
|
|
219
|
+
const assertMaxRatio = parseOptionalPositiveFloat(process.env.SWEEP_ASSERT_MAX_RATIO);
|
|
220
|
+
const assertStartSyncForBatchGte = parseOptionalPositiveInteger(process.env.SWEEP_ASSERT_REQUIRE_STARTSYNC_FOR_BATCH_GTE);
|
|
221
|
+
const assertMaxMeanByBatch = parseBatchThresholdMap(process.env.SWEEP_ASSERT_MAX_MEAN_MS);
|
|
222
|
+
const tasks = [];
|
|
223
|
+
for (const batchSize of batchSizes) {
|
|
224
|
+
let counterTotals = createEmptyCounters();
|
|
225
|
+
const samples = [];
|
|
226
|
+
const totalRuns = warmupRuns + measuredRuns;
|
|
227
|
+
for (let run = 0; run < totalRuns; run++) {
|
|
228
|
+
const result = await runCatchup({ batchSize, entryCount, timeoutMs });
|
|
229
|
+
if (run < warmupRuns) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
samples.push(result.catchupMs);
|
|
233
|
+
counterTotals = mergeCounters(counterTotals, result.counters);
|
|
234
|
+
}
|
|
235
|
+
const meanMs = mean(samples);
|
|
236
|
+
tasks.push({
|
|
237
|
+
name: `repairSweepTargetBufferSize=${batchSize}`,
|
|
238
|
+
batchSize,
|
|
239
|
+
mean_ms: meanMs,
|
|
240
|
+
hz: meanMs > 0 ? 1000 / meanMs : 0,
|
|
241
|
+
rme: null,
|
|
242
|
+
samples: samples.length,
|
|
243
|
+
startSyncTotal: counterTotals.startSync,
|
|
244
|
+
moreSymbolsTotal: counterTotals.moreSymbols,
|
|
245
|
+
requestAllTotal: counterTotals.requestAll,
|
|
246
|
+
requestMaybeSyncTotal: counterTotals.requestMaybeSync,
|
|
247
|
+
requestMaybeSyncCoordinateTotal: counterTotals.requestMaybeSyncCoordinate,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const failures = [];
|
|
251
|
+
if (assertMaxRatio != null && tasks.length > 1) {
|
|
252
|
+
const means = tasks.map((task) => task.mean_ms);
|
|
253
|
+
const ratio = Math.max(...means) / Math.min(...means);
|
|
254
|
+
if (ratio > assertMaxRatio) {
|
|
255
|
+
failures.push(`max mean ratio ${ratio.toFixed(3)} exceeded threshold ${assertMaxRatio.toFixed(3)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (assertStartSyncForBatchGte != null) {
|
|
259
|
+
for (const task of tasks) {
|
|
260
|
+
if (task.batchSize >= assertStartSyncForBatchGte &&
|
|
261
|
+
task.startSyncTotal === 0) {
|
|
262
|
+
failures.push(`batch ${task.batchSize} produced zero StartSync messages (expected rateless path)`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
for (const [batchSize, maxMeanMs] of assertMaxMeanByBatch) {
|
|
267
|
+
const task = tasks.find((x) => x.batchSize === batchSize);
|
|
268
|
+
if (!task) {
|
|
269
|
+
failures.push(`missing configured batch size ${batchSize} for max mean assertion`);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (task.mean_ms > maxMeanMs) {
|
|
273
|
+
failures.push(`batch ${batchSize} mean ${task.mean_ms.toFixed(3)}ms exceeded max ${maxMeanMs.toFixed(3)}ms`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const output = {
|
|
277
|
+
name: "shared-log-sync-batch-sweep",
|
|
278
|
+
tasks,
|
|
279
|
+
meta: {
|
|
280
|
+
entryCount,
|
|
281
|
+
timeoutMs,
|
|
282
|
+
warmupRuns,
|
|
283
|
+
measuredRuns,
|
|
284
|
+
batchSizes,
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
if (process.env.BENCH_JSON === "1") {
|
|
288
|
+
process.stdout.write(JSON.stringify(output, null, 2));
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
console.table(tasks.map((task) => ({
|
|
292
|
+
batch: task.batchSize,
|
|
293
|
+
mean_ms: task.mean_ms.toFixed(2),
|
|
294
|
+
hz: task.hz.toFixed(2),
|
|
295
|
+
startSync: task.startSyncTotal,
|
|
296
|
+
moreSymbols: task.moreSymbolsTotal,
|
|
297
|
+
requestAll: task.requestAllTotal,
|
|
298
|
+
requestMaybeSync: task.requestMaybeSyncTotal,
|
|
299
|
+
requestMaybeSyncCoordinate: task.requestMaybeSyncCoordinateTotal,
|
|
300
|
+
})));
|
|
301
|
+
}
|
|
302
|
+
if (failures.length > 0) {
|
|
303
|
+
throw new Error(`sync-batch-sweep assertions failed:\n- ${failures.join("\n- ")}`);
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=sync-batch-sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-batch-sweep.js","sourceRoot":"","sources":["../../benchmark/sync-batch-sweep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application-level envelope for fanout-delivered shared-log messages.
|
|
3
|
+
*
|
|
4
|
+
* FanoutTree's data-plane forwarding makes the root the transport-level origin
|
|
5
|
+
* when proxy-publishing. Shared-log needs a stable publisher identity and
|
|
6
|
+
* timestamp regardless of which overlay hop forwarded the bytes.
|
|
7
|
+
*/
|
|
8
|
+
export declare class FanoutEnvelope {
|
|
9
|
+
from: string;
|
|
10
|
+
timestamp: bigint;
|
|
11
|
+
payload: Uint8Array;
|
|
12
|
+
constructor(props: {
|
|
13
|
+
from: string;
|
|
14
|
+
timestamp: bigint;
|
|
15
|
+
payload: Uint8Array;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=fanout-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout-envelope.d.ts","sourceRoot":"","sources":["../../src/fanout-envelope.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,qBACa,cAAc;IAE1B,IAAI,EAAE,MAAM,CAAC;IAGb,SAAS,EAAE,MAAM,CAAC;IAGlB,OAAO,EAAE,UAAU,CAAC;gBAER,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,UAAU,CAAA;KAAE;CAK3E"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import { field, variant } from "@dao-xyz/borsh";
|
|
36
|
+
/**
|
|
37
|
+
* Application-level envelope for fanout-delivered shared-log messages.
|
|
38
|
+
*
|
|
39
|
+
* FanoutTree's data-plane forwarding makes the root the transport-level origin
|
|
40
|
+
* when proxy-publishing. Shared-log needs a stable publisher identity and
|
|
41
|
+
* timestamp regardless of which overlay hop forwarded the bytes.
|
|
42
|
+
*/
|
|
43
|
+
let FanoutEnvelope = (() => {
|
|
44
|
+
let _classDecorators = [variant(0)];
|
|
45
|
+
let _classDescriptor;
|
|
46
|
+
let _classExtraInitializers = [];
|
|
47
|
+
let _classThis;
|
|
48
|
+
let _from_decorators;
|
|
49
|
+
let _from_initializers = [];
|
|
50
|
+
let _from_extraInitializers = [];
|
|
51
|
+
let _timestamp_decorators;
|
|
52
|
+
let _timestamp_initializers = [];
|
|
53
|
+
let _timestamp_extraInitializers = [];
|
|
54
|
+
let _payload_decorators;
|
|
55
|
+
let _payload_initializers = [];
|
|
56
|
+
let _payload_extraInitializers = [];
|
|
57
|
+
var FanoutEnvelope = class {
|
|
58
|
+
static { _classThis = this; }
|
|
59
|
+
static {
|
|
60
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
61
|
+
_from_decorators = [field({ type: "string" })];
|
|
62
|
+
_timestamp_decorators = [field({ type: "u64" })];
|
|
63
|
+
_payload_decorators = [field({ type: Uint8Array })];
|
|
64
|
+
__esDecorate(null, null, _from_decorators, { kind: "field", name: "from", static: false, private: false, access: { has: obj => "from" in obj, get: obj => obj.from, set: (obj, value) => { obj.from = value; } }, metadata: _metadata }, _from_initializers, _from_extraInitializers);
|
|
65
|
+
__esDecorate(null, null, _timestamp_decorators, { kind: "field", name: "timestamp", static: false, private: false, access: { has: obj => "timestamp" in obj, get: obj => obj.timestamp, set: (obj, value) => { obj.timestamp = value; } }, metadata: _metadata }, _timestamp_initializers, _timestamp_extraInitializers);
|
|
66
|
+
__esDecorate(null, null, _payload_decorators, { kind: "field", name: "payload", static: false, private: false, access: { has: obj => "payload" in obj, get: obj => obj.payload, set: (obj, value) => { obj.payload = value; } }, metadata: _metadata }, _payload_initializers, _payload_extraInitializers);
|
|
67
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
68
|
+
FanoutEnvelope = _classThis = _classDescriptor.value;
|
|
69
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
70
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
71
|
+
}
|
|
72
|
+
from = __runInitializers(this, _from_initializers, void 0); // publisher publicKey hash
|
|
73
|
+
timestamp = (__runInitializers(this, _from_extraInitializers), __runInitializers(this, _timestamp_initializers, void 0)); // publisher-supplied timestamp
|
|
74
|
+
payload = (__runInitializers(this, _timestamp_extraInitializers), __runInitializers(this, _payload_initializers, void 0)); // serialized TransportMessage
|
|
75
|
+
constructor(props) {
|
|
76
|
+
__runInitializers(this, _payload_extraInitializers);
|
|
77
|
+
this.from = props.from;
|
|
78
|
+
this.timestamp = props.timestamp;
|
|
79
|
+
this.payload = props.payload;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return FanoutEnvelope = _classThis;
|
|
83
|
+
})();
|
|
84
|
+
export { FanoutEnvelope };
|
|
85
|
+
//# sourceMappingURL=fanout-envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout-envelope.js","sourceRoot":"","sources":["../../src/fanout-envelope.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;GAMG;IAEU,cAAc;4BAD1B,OAAO,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;gCAET,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;qCAGzB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;mCAGtB,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;YAL5B,8JAAA,IAAI,6BAAJ,IAAI,mFAAS;YAGb,6KAAA,SAAS,6BAAT,SAAS,6FAAS;YAGlB,uKAAA,OAAO,6BAAP,OAAO,yFAAa;YARrB,6KAeC;;;YAfY,uDAAc;;QAE1B,IAAI,uDAAS,CAAC,2BAA2B;QAGzC,SAAS,gHAAS,CAAC,+BAA+B;QAGlD,OAAO,mHAAa,CAAC,8BAA8B;QAEnD,YAAY,KAA+D;;YAC1E,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YACjC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;SAC7B;;;;SAdW,cAAc"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { PublicSignKey } from "@peerbit/crypto";
|
|
|
2
2
|
import { type Index } from "@peerbit/indexer-interface";
|
|
3
3
|
import { type AppendOptions, type Change, Entry, Log, type LogEvents, type LogProperties, Meta, ShallowEntry, type ShallowOrFullEntry } from "@peerbit/log";
|
|
4
4
|
import { Program, type ProgramEvents } from "@peerbit/program";
|
|
5
|
+
import { type FanoutTreeChannelOptions, type FanoutTreeJoinOptions } from "@peerbit/pubsub";
|
|
5
6
|
import { SubscriptionEvent, UnsubcriptionEvent } from "@peerbit/pubsub-interface";
|
|
6
7
|
import { RPC, type RequestContext } from "@peerbit/rpc";
|
|
7
8
|
import { BlocksMessage } from "./blocks.js";
|
|
@@ -101,6 +102,7 @@ export type SharedLogOptions<T, D extends ReplicationDomain<any, T, R>, R extend
|
|
|
101
102
|
eagerBlocks?: boolean | {
|
|
102
103
|
cacheSize?: number;
|
|
103
104
|
};
|
|
105
|
+
fanout?: SharedLogFanoutOptions;
|
|
104
106
|
};
|
|
105
107
|
export declare const DEFAULT_MIN_REPLICAS = 2;
|
|
106
108
|
export declare const WAIT_FOR_REPLICATOR_TIMEOUT = 20000;
|
|
@@ -109,20 +111,30 @@ export declare const WAIT_FOR_REPLICATOR_REQUEST_INTERVAL = 1000;
|
|
|
109
111
|
export declare const WAIT_FOR_REPLICATOR_REQUEST_MIN_ATTEMPTS = 3;
|
|
110
112
|
export declare const WAIT_FOR_PRUNE_DELAY = 0;
|
|
111
113
|
export type Args<T, D extends ReplicationDomain<any, T, R>, R extends "u32" | "u64" = D extends ReplicationDomain<any, T, infer I> ? I : "u32"> = LogProperties<T> & LogEvents<T> & SharedLogOptions<T, D, R>;
|
|
114
|
+
export type DeliveryReliability = "ack" | "best-effort";
|
|
112
115
|
export type DeliveryOptions = {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
};
|
|
116
|
+
reliability?: DeliveryReliability;
|
|
117
|
+
minAcks?: number;
|
|
116
118
|
requireRecipients?: boolean;
|
|
117
119
|
timeout?: number;
|
|
118
120
|
signal?: AbortSignal;
|
|
119
121
|
};
|
|
120
|
-
export type
|
|
122
|
+
export type SharedLogFanoutOptions = {
|
|
123
|
+
root?: string;
|
|
124
|
+
channel?: Partial<Omit<FanoutTreeChannelOptions, "role">>;
|
|
125
|
+
join?: FanoutTreeJoinOptions;
|
|
126
|
+
};
|
|
127
|
+
type SharedAppendBaseOptions<T> = AppendOptions<T> & {
|
|
121
128
|
replicas?: AbsoluteReplicas | number;
|
|
122
129
|
replicate?: boolean;
|
|
123
|
-
target?: "all" | "replicators" | "none";
|
|
124
|
-
delivery?: false | true | DeliveryOptions;
|
|
125
130
|
};
|
|
131
|
+
export type SharedAppendOptions<T> = (SharedAppendBaseOptions<T> & {
|
|
132
|
+
target?: "replicators" | "none";
|
|
133
|
+
delivery?: false | true | DeliveryOptions;
|
|
134
|
+
}) | (SharedAppendBaseOptions<T> & {
|
|
135
|
+
target: "all";
|
|
136
|
+
delivery?: false | undefined;
|
|
137
|
+
});
|
|
126
138
|
export type ReplicatorJoinEvent = {
|
|
127
139
|
publicKey: PublicSignKey;
|
|
128
140
|
};
|
|
@@ -151,10 +163,15 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
151
163
|
private coordinateToHash;
|
|
152
164
|
private recentlyRebalanced;
|
|
153
165
|
uniqueReplicators: Set<string>;
|
|
166
|
+
private _replicatorJoinEmitted;
|
|
154
167
|
private _replicatorsReconciled;
|
|
155
168
|
_gidPeersHistory: Map<string, Set<string>>;
|
|
156
169
|
private _onSubscriptionFn;
|
|
157
170
|
private _onUnsubscriptionFn;
|
|
171
|
+
private _onFanoutDataFn?;
|
|
172
|
+
private _onFanoutUnicastFn?;
|
|
173
|
+
private _fanoutChannel?;
|
|
174
|
+
private _providerHandle?;
|
|
158
175
|
private _isTrustedReplicator?;
|
|
159
176
|
private _logProperties?;
|
|
160
177
|
private _closeController;
|
|
@@ -166,6 +183,9 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
166
183
|
timeout: ReturnType<typeof setTimeout>;
|
|
167
184
|
}>>;
|
|
168
185
|
private latestReplicationInfoMessage;
|
|
186
|
+
private _replicationInfoBlockedPeers;
|
|
187
|
+
private _replicationInfoRequestByPeer;
|
|
188
|
+
private _replicationInfoApplyQueueByPeer;
|
|
169
189
|
private remoteBlocks;
|
|
170
190
|
private openTime;
|
|
171
191
|
private oldestOpenTime;
|
|
@@ -178,7 +198,13 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
178
198
|
private responseToPruneDebouncedFn;
|
|
179
199
|
private _requestIPruneSent;
|
|
180
200
|
private _requestIPruneResponseReplicatorSet;
|
|
201
|
+
private _checkedPruneRetries;
|
|
181
202
|
private replicationChangeDebounceFn;
|
|
203
|
+
private _repairRetryTimers;
|
|
204
|
+
private _recentRepairDispatch;
|
|
205
|
+
private _repairSweepRunning;
|
|
206
|
+
private _repairSweepForceFreshPending;
|
|
207
|
+
private _repairSweepAddedPeersPending;
|
|
182
208
|
private distributeQueue?;
|
|
183
209
|
syncronizer: Syncronizer<R>;
|
|
184
210
|
replicas: ReplicationLimits;
|
|
@@ -189,6 +215,7 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
189
215
|
waitForReplicatorRequestMaxAttempts?: number;
|
|
190
216
|
waitForPruneDelay: number;
|
|
191
217
|
distributionDebounceTime: number;
|
|
218
|
+
repairSweepTargetBufferSize: number;
|
|
192
219
|
replicationController: PIDReplicationController;
|
|
193
220
|
history: {
|
|
194
221
|
usedMemory: number;
|
|
@@ -203,6 +230,20 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
203
230
|
get compatibility(): number | undefined;
|
|
204
231
|
get isAdaptiveReplicating(): boolean;
|
|
205
232
|
private get v8Behaviour();
|
|
233
|
+
private getFanoutChannelOptions;
|
|
234
|
+
private _openFanoutChannel;
|
|
235
|
+
private _closeFanoutChannel;
|
|
236
|
+
private _onFanoutData;
|
|
237
|
+
private _onFanoutUnicast;
|
|
238
|
+
private _publishExchangeHeadsViaFanout;
|
|
239
|
+
private _parseDeliveryOptions;
|
|
240
|
+
private _getSortedRouteHints;
|
|
241
|
+
private _sendAckWithUnifiedHints;
|
|
242
|
+
private _appendDeliverToReplicators;
|
|
243
|
+
private _mergeLeadersFromGidReferences;
|
|
244
|
+
private _appendDeliverToAllFanout;
|
|
245
|
+
private _resolvePublicKeyFromHash;
|
|
246
|
+
private _getTopicSubscribers;
|
|
206
247
|
private getRole;
|
|
207
248
|
isReplicating(): Promise<boolean>;
|
|
208
249
|
private setupRebalanceDebounceFunction;
|
|
@@ -231,7 +272,12 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
231
272
|
}): Promise<void>;
|
|
232
273
|
private removePeerFromGidPeerHistory;
|
|
233
274
|
addPeersToGidPeerHistory(gid: string, publicKeys: Iterable<string>, reset?: boolean): Set<string>;
|
|
275
|
+
private dispatchMaybeMissingEntries;
|
|
276
|
+
private scheduleRepairSweep;
|
|
277
|
+
private runRepairSweep;
|
|
234
278
|
private pruneDebouncedFnAddIfNotKeeping;
|
|
279
|
+
private clearCheckedPruneRetry;
|
|
280
|
+
private scheduleCheckedPruneRetry;
|
|
235
281
|
append(data: T, options?: SharedAppendOptions<T> | undefined): Promise<{
|
|
236
282
|
entry: Entry<T>;
|
|
237
283
|
removed: ShallowOrFullEntry<T>[];
|
|
@@ -345,6 +391,9 @@ export declare class SharedLog<T, D extends ReplicationDomain<any, T, R> = any,
|
|
|
345
391
|
candidates?: string[];
|
|
346
392
|
roleAge?: number;
|
|
347
393
|
}): Promise<boolean>;
|
|
394
|
+
private withReplicationInfoApplyQueue;
|
|
395
|
+
private cancelReplicationInfoRequests;
|
|
396
|
+
private scheduleReplicationInfoRequests;
|
|
348
397
|
handleSubscriptionChange(publicKey: PublicSignKey, topics: string[], subscribed: boolean): Promise<void>;
|
|
349
398
|
private getClampedReplicas;
|
|
350
399
|
private removePruneRequestSent;
|