cojson 0.20.17 → 0.20.18
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +9 -0
- package/dist/ClockOffset.d.ts +21 -0
- package/dist/ClockOffset.d.ts.map +1 -0
- package/dist/ClockOffset.js +55 -0
- package/dist/ClockOffset.js.map +1 -0
- package/dist/coValueCore/coValueCore.js +2 -2
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/localNode.d.ts +16 -3
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +36 -5
- package/dist/localNode.js.map +1 -1
- package/dist/tests/ClockOffset.test.d.ts +2 -0
- package/dist/tests/ClockOffset.test.d.ts.map +1 -0
- package/dist/tests/ClockOffset.test.js +146 -0
- package/dist/tests/ClockOffset.test.js.map +1 -0
- package/dist/tests/clockDrift.integration.test.d.ts +2 -0
- package/dist/tests/clockDrift.integration.test.d.ts.map +1 -0
- package/dist/tests/clockDrift.integration.test.js +177 -0
- package/dist/tests/clockDrift.integration.test.js.map +1 -0
- package/dist/tests/localNode.clockOffset.test.d.ts +2 -0
- package/dist/tests/localNode.clockOffset.test.d.ts.map +1 -0
- package/dist/tests/localNode.clockOffset.test.js +70 -0
- package/dist/tests/localNode.clockOffset.test.js.map +1 -0
- package/dist/tests/testUtils.d.ts +2 -0
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +9 -2
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +4 -4
- package/src/ClockOffset.ts +83 -0
- package/src/coValueCore/coValueCore.ts +2 -2
- package/src/localNode.ts +31 -0
- package/src/tests/ClockOffset.test.ts +177 -0
- package/src/tests/clockDrift.integration.test.ts +261 -0
- package/src/tests/localNode.clockOffset.test.ts +92 -0
- package/src/tests/testUtils.ts +16 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClockOffset.test.d.ts","sourceRoot":"","sources":["../../src/tests/ClockOffset.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { ClockOffset } from "../ClockOffset.js";
|
|
3
|
+
function makeRng(seed) {
|
|
4
|
+
let state = seed >>> 0;
|
|
5
|
+
return () => {
|
|
6
|
+
state ^= state << 13;
|
|
7
|
+
state ^= state >>> 17;
|
|
8
|
+
state ^= state << 5;
|
|
9
|
+
return ((state >>> 0) / 0xffffffff) * 2 - 1;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
describe("ClockOffset", () => {
|
|
13
|
+
test("currentOffset() returns 0 before any samples are ingested", () => {
|
|
14
|
+
const clockOffset = new ClockOffset();
|
|
15
|
+
expect(clockOffset.currentOffset()).toBe(0);
|
|
16
|
+
});
|
|
17
|
+
test("sampleCount() reports sliding window size capped at windowSize", () => {
|
|
18
|
+
const windowSize = 4;
|
|
19
|
+
const clockOffset = new ClockOffset({
|
|
20
|
+
windowSize,
|
|
21
|
+
// Keep the outlier gate wide enough to accept the spread of samples
|
|
22
|
+
// we feed below; the point of this test is the window count, not
|
|
23
|
+
// outlier rejection.
|
|
24
|
+
outlierThresholdMs: 10000,
|
|
25
|
+
});
|
|
26
|
+
expect(clockOffset.sampleCount()).toBe(0);
|
|
27
|
+
for (let i = 0; i < 3; i++) {
|
|
28
|
+
clockOffset.addSample({
|
|
29
|
+
serverTime: 1000 + i,
|
|
30
|
+
localReceiveTime: 1000,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
expect(clockOffset.sampleCount()).toBe(3);
|
|
34
|
+
for (let i = 0; i < windowSize + 2; i++) {
|
|
35
|
+
clockOffset.addSample({
|
|
36
|
+
serverTime: 2000 + i,
|
|
37
|
+
localReceiveTime: 2000,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
expect(clockOffset.sampleCount()).toBe(windowSize);
|
|
41
|
+
});
|
|
42
|
+
test("after a single sample, currentOffset() reflects serverTime - localReceiveTime", () => {
|
|
43
|
+
const clockOffset = new ClockOffset();
|
|
44
|
+
clockOffset.addSample({ serverTime: 10500, localReceiveTime: 10000 });
|
|
45
|
+
expect(clockOffset.currentOffset()).toBe(500);
|
|
46
|
+
});
|
|
47
|
+
test("converges to within a small tolerance of the true offset under bounded jitter", () => {
|
|
48
|
+
// True offset is 1000 ms; each sample has jitter of +/- 50 ms. The tolerance
|
|
49
|
+
// of 60 ms is chosen to be slightly larger than the jitter amplitude so the
|
|
50
|
+
// test does not assume a specific estimator (mean / median / trimmed mean
|
|
51
|
+
// would all satisfy it), but is tight enough to prove convergence is real.
|
|
52
|
+
const clockOffset = new ClockOffset();
|
|
53
|
+
const rng = makeRng(42);
|
|
54
|
+
const trueOffset = 1000;
|
|
55
|
+
for (let i = 0; i < 64; i++) {
|
|
56
|
+
const jitter = rng() * 50;
|
|
57
|
+
const localReceiveTime = 1000000 + i * 100;
|
|
58
|
+
const serverTime = localReceiveTime + trueOffset + jitter;
|
|
59
|
+
clockOffset.addSample({ serverTime, localReceiveTime });
|
|
60
|
+
}
|
|
61
|
+
expect(clockOffset.currentOffset()).toBeGreaterThan(trueOffset - 60);
|
|
62
|
+
expect(clockOffset.currentOffset()).toBeLessThan(trueOffset + 60);
|
|
63
|
+
});
|
|
64
|
+
test("a single huge outlier does not meaningfully move the estimate", () => {
|
|
65
|
+
const clockOffset = new ClockOffset();
|
|
66
|
+
const trueOffset = 1000;
|
|
67
|
+
// Fill the window with clean samples near offset=1000.
|
|
68
|
+
for (let i = 0; i < 32; i++) {
|
|
69
|
+
const localReceiveTime = 2000000 + i * 100;
|
|
70
|
+
clockOffset.addSample({
|
|
71
|
+
serverTime: localReceiveTime + trueOffset,
|
|
72
|
+
localReceiveTime,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const before = clockOffset.currentOffset();
|
|
76
|
+
// One extreme sample — offset would be ~100_000 if taken at face value.
|
|
77
|
+
clockOffset.addSample({
|
|
78
|
+
serverTime: 2000000 + 32 * 100 + 100000,
|
|
79
|
+
localReceiveTime: 2000000 + 32 * 100,
|
|
80
|
+
});
|
|
81
|
+
const after = clockOffset.currentOffset();
|
|
82
|
+
expect(Math.abs(after - trueOffset)).toBeLessThan(50);
|
|
83
|
+
expect(Math.abs(after - before)).toBeLessThan(50);
|
|
84
|
+
});
|
|
85
|
+
test("samples beyond maxAbsOffsetMs are ignored entirely", () => {
|
|
86
|
+
const clockOffset = new ClockOffset({ maxAbsOffsetMs: 5000 });
|
|
87
|
+
clockOffset.addSample({ serverTime: 10200, localReceiveTime: 10000 });
|
|
88
|
+
const before = clockOffset.currentOffset();
|
|
89
|
+
// Implied offset is 10_000_000 ms — well beyond the 5000 ms cap.
|
|
90
|
+
clockOffset.addSample({
|
|
91
|
+
serverTime: 20000000,
|
|
92
|
+
localReceiveTime: 10000000,
|
|
93
|
+
});
|
|
94
|
+
expect(clockOffset.currentOffset()).toBe(before);
|
|
95
|
+
});
|
|
96
|
+
test("sliding window drops old samples once newer ones fill it", () => {
|
|
97
|
+
const clockOffset = new ClockOffset({ windowSize: 10 });
|
|
98
|
+
// Ten samples establishing offset ~500.
|
|
99
|
+
for (let i = 0; i < 10; i++) {
|
|
100
|
+
const localReceiveTime = 3000000 + i * 100;
|
|
101
|
+
clockOffset.addSample({
|
|
102
|
+
serverTime: localReceiveTime + 500,
|
|
103
|
+
localReceiveTime,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Twenty samples at offset ~2000 — more than the window, so the old
|
|
107
|
+
// offset=500 samples should be fully evicted.
|
|
108
|
+
for (let i = 0; i < 20; i++) {
|
|
109
|
+
const localReceiveTime = 3100000 + i * 100;
|
|
110
|
+
clockOffset.addSample({
|
|
111
|
+
serverTime: localReceiveTime + 2000,
|
|
112
|
+
localReceiveTime,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
expect(clockOffset.currentOffset()).toBeGreaterThan(1950);
|
|
116
|
+
expect(clockOffset.currentOffset()).toBeLessThan(2050);
|
|
117
|
+
});
|
|
118
|
+
test("a hostile peer's single bad sample does not poison later estimates", () => {
|
|
119
|
+
const clockOffset = new ClockOffset();
|
|
120
|
+
const trueOffset = 1000;
|
|
121
|
+
// Warm-up with good samples.
|
|
122
|
+
for (let i = 0; i < 16; i++) {
|
|
123
|
+
const localReceiveTime = 4000000 + i * 100;
|
|
124
|
+
clockOffset.addSample({
|
|
125
|
+
serverTime: localReceiveTime + trueOffset,
|
|
126
|
+
localReceiveTime,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Hostile sample — way off.
|
|
130
|
+
clockOffset.addSample({
|
|
131
|
+
serverTime: 4000000 + 16 * 100 + 500000,
|
|
132
|
+
localReceiveTime: 4000000 + 16 * 100,
|
|
133
|
+
});
|
|
134
|
+
// More good samples after the attack.
|
|
135
|
+
for (let i = 17; i < 48; i++) {
|
|
136
|
+
const localReceiveTime = 4000000 + i * 100;
|
|
137
|
+
clockOffset.addSample({
|
|
138
|
+
serverTime: localReceiveTime + trueOffset,
|
|
139
|
+
localReceiveTime,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
expect(clockOffset.currentOffset()).toBeGreaterThan(trueOffset - 25);
|
|
143
|
+
expect(clockOffset.currentOffset()).toBeLessThan(trueOffset + 25);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=ClockOffset.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClockOffset.test.js","sourceRoot":"","sources":["../../src/tests/ClockOffset.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clockDrift.integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/clockDrift.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
import { loadCoValueOrFail, setupTestAccount, setupTestNode, waitFor, } from "./testUtils.js";
|
|
4
|
+
const CLIENT_SKEW_MS = 20000;
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
});
|
|
8
|
+
describe("clock drift across peers with clock sync enabled", () => {
|
|
9
|
+
test("worker can publish and self-remove after a skewed client with clock sync creates group, grant and chat", async () => {
|
|
10
|
+
const errorSpy = vi.spyOn(logger, "error");
|
|
11
|
+
const realNow = Math.floor(performance.timeOrigin + performance.now());
|
|
12
|
+
vi.spyOn(Date, "now").mockImplementation(() => {
|
|
13
|
+
const real = performance.timeOrigin + performance.now();
|
|
14
|
+
return Math.floor(real) + CLIENT_SKEW_MS;
|
|
15
|
+
});
|
|
16
|
+
const worker = await setupTestAccount({
|
|
17
|
+
isSyncServer: true,
|
|
18
|
+
});
|
|
19
|
+
const client = await setupTestAccount({
|
|
20
|
+
connected: true,
|
|
21
|
+
experimental_clockSyncFromServerPings: true,
|
|
22
|
+
});
|
|
23
|
+
const skewedNow = Date.now();
|
|
24
|
+
client.node.clockOffset.addSample({
|
|
25
|
+
serverTime: skewedNow - CLIENT_SKEW_MS,
|
|
26
|
+
localReceiveTime: skewedNow,
|
|
27
|
+
});
|
|
28
|
+
const group = client.node.createGroup();
|
|
29
|
+
const workerAccountOnClient = await loadCoValueOrFail(client.node, worker.accountID);
|
|
30
|
+
group.addMember(workerAccountOnClient, "admin");
|
|
31
|
+
const oneToOneChat = group.createMap();
|
|
32
|
+
oneToOneChat.set("kind", "OneToOneChat", "trusting");
|
|
33
|
+
oneToOneChat.set("published", false, "trusting");
|
|
34
|
+
await oneToOneChat.core.waitForSync();
|
|
35
|
+
await group.core.waitForSync();
|
|
36
|
+
const clientGroupTxs = group.core.getValidSortedTransactions();
|
|
37
|
+
const maxClientGroupMadeAt = Math.max(...clientGroupTxs.map((tx) => tx.madeAt));
|
|
38
|
+
expect(maxClientGroupMadeAt).toBeLessThan(realNow + CLIENT_SKEW_MS - 5000);
|
|
39
|
+
vi.restoreAllMocks();
|
|
40
|
+
const errorSpyAfter = vi.spyOn(logger, "error");
|
|
41
|
+
const chatOnWorker = await loadCoValueOrFail(worker.node, oneToOneChat.id);
|
|
42
|
+
const groupOnWorker = await loadCoValueOrFail(worker.node, group.id);
|
|
43
|
+
const workerAccountOnWorker = await loadCoValueOrFail(worker.node, worker.accountID);
|
|
44
|
+
await waitFor(() => {
|
|
45
|
+
expect(chatOnWorker.get("kind")).toBe("OneToOneChat");
|
|
46
|
+
expect(groupOnWorker.roleOf(worker.accountID)).toBe("admin");
|
|
47
|
+
});
|
|
48
|
+
chatOnWorker.set("published", true, "trusting");
|
|
49
|
+
groupOnWorker.removeMember(workerAccountOnWorker);
|
|
50
|
+
await chatOnWorker.core.waitForSync();
|
|
51
|
+
await groupOnWorker.core.waitForSync();
|
|
52
|
+
await waitFor(() => {
|
|
53
|
+
expect(oneToOneChat.get("published")).toBe(true);
|
|
54
|
+
expect(group.roleOf(worker.accountID)).not.toBe("admin");
|
|
55
|
+
expect(chatOnWorker.get("published")).toBe(true);
|
|
56
|
+
expect(groupOnWorker.roleOf(worker.accountID)).not.toBe("admin");
|
|
57
|
+
});
|
|
58
|
+
expect(oneToOneChat.get("published")).toBe(true);
|
|
59
|
+
expect(chatOnWorker.get("published")).toBe(true);
|
|
60
|
+
expect(group.roleOf(worker.accountID)).not.toBe("admin");
|
|
61
|
+
expect(groupOnWorker.roleOf(worker.accountID)).not.toBe("admin");
|
|
62
|
+
const forbiddenFragments = [
|
|
63
|
+
"invalid transaction",
|
|
64
|
+
"permission",
|
|
65
|
+
"rejected",
|
|
66
|
+
"not authorized",
|
|
67
|
+
"not authorised",
|
|
68
|
+
];
|
|
69
|
+
const offendingCalls = [...errorSpy.mock.calls, ...errorSpyAfter.mock.calls]
|
|
70
|
+
.map((call) => call.map((arg) => String(arg)).join(" "))
|
|
71
|
+
.filter((line) => forbiddenFragments.some((f) => line.toLowerCase().includes(f)));
|
|
72
|
+
expect(offendingCalls).toEqual([]);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe("experimental_clockSyncFromServerPings flag wiring", () => {
|
|
76
|
+
function seedOffset(clockOffset, offsetMs) {
|
|
77
|
+
const localReceiveTime = Date.now();
|
|
78
|
+
clockOffset.addSample({
|
|
79
|
+
serverTime: localReceiveTime + offsetMs,
|
|
80
|
+
localReceiveTime,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
test("with the flag on, a seeded +10_000 ms offset pulls locally-stamped madeAt forward", () => {
|
|
84
|
+
const { node } = setupTestNode({
|
|
85
|
+
experimental_clockSyncFromServerPings: true,
|
|
86
|
+
});
|
|
87
|
+
seedOffset(node.clockOffset, 10000);
|
|
88
|
+
const group = node.createGroup();
|
|
89
|
+
const map = group.createMap();
|
|
90
|
+
const before = Date.now();
|
|
91
|
+
map.set("k", "v", "trusting");
|
|
92
|
+
const after = Date.now();
|
|
93
|
+
const txs = map.core.getValidSortedTransactions();
|
|
94
|
+
const lastTx = txs.at(-1);
|
|
95
|
+
expect(lastTx).toBeDefined();
|
|
96
|
+
expect(lastTx.madeAt).toBeGreaterThanOrEqual(before + 9900);
|
|
97
|
+
expect(lastTx.madeAt).toBeLessThanOrEqual(after + 10100);
|
|
98
|
+
});
|
|
99
|
+
test("without the flag, a seeded +10_000 ms offset does NOT shift locally-stamped madeAt", () => {
|
|
100
|
+
const { node } = setupTestNode({
|
|
101
|
+
experimental_clockSyncFromServerPings: false,
|
|
102
|
+
});
|
|
103
|
+
seedOffset(node.clockOffset, 10000);
|
|
104
|
+
const group = node.createGroup();
|
|
105
|
+
const map = group.createMap();
|
|
106
|
+
const before = Date.now();
|
|
107
|
+
map.set("k", "v", "trusting");
|
|
108
|
+
const after = Date.now();
|
|
109
|
+
const txs = map.core.getValidSortedTransactions();
|
|
110
|
+
const lastTx = txs.at(-1);
|
|
111
|
+
expect(lastTx).toBeDefined();
|
|
112
|
+
expect(lastTx.madeAt).toBeGreaterThanOrEqual(before);
|
|
113
|
+
expect(lastTx.madeAt).toBeLessThanOrEqual(after + 100);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe("clock sync pulls skewed client stamps toward server time", () => {
|
|
117
|
+
test("with both nodes flag-on, a client whose wall clock is 20s ahead authors transactions that land near real time on the worker", async () => {
|
|
118
|
+
const errorSpy = vi.spyOn(logger, "error");
|
|
119
|
+
const worker = await setupTestAccount({
|
|
120
|
+
isSyncServer: true,
|
|
121
|
+
experimental_clockSyncFromServerPings: true,
|
|
122
|
+
});
|
|
123
|
+
const realNowBeforeClient = Date.now();
|
|
124
|
+
const SKEW_MS = 20000;
|
|
125
|
+
vi.spyOn(Date, "now").mockImplementation(() => {
|
|
126
|
+
const real = Math.floor(performance.timeOrigin + performance.now());
|
|
127
|
+
return real + SKEW_MS;
|
|
128
|
+
});
|
|
129
|
+
const client = await setupTestAccount({
|
|
130
|
+
connected: true,
|
|
131
|
+
experimental_clockSyncFromServerPings: true,
|
|
132
|
+
});
|
|
133
|
+
const localReceiveTime = Date.now();
|
|
134
|
+
client.node.clockOffset.addSample({
|
|
135
|
+
serverTime: localReceiveTime - SKEW_MS,
|
|
136
|
+
localReceiveTime,
|
|
137
|
+
});
|
|
138
|
+
expect(client.node.clockOffset.currentOffset()).toBeLessThanOrEqual(-SKEW_MS + 100);
|
|
139
|
+
expect(client.node.clockOffset.currentOffset()).toBeGreaterThanOrEqual(-SKEW_MS - 100);
|
|
140
|
+
const group = client.node.createGroup();
|
|
141
|
+
group.addMember("everyone", "writer");
|
|
142
|
+
const map = group.createMap();
|
|
143
|
+
map.set("from", "skewed-client", "trusting");
|
|
144
|
+
await map.core.waitForSync();
|
|
145
|
+
await group.core.waitForSync();
|
|
146
|
+
vi.restoreAllMocks();
|
|
147
|
+
const errorSpyAfter = vi.spyOn(logger, "error");
|
|
148
|
+
const realNowAfter = Date.now();
|
|
149
|
+
const mapOnWorker = await loadCoValueOrFail(worker.node, map.id);
|
|
150
|
+
await waitFor(() => {
|
|
151
|
+
expect(mapOnWorker.get("from")).toBe("skewed-client");
|
|
152
|
+
});
|
|
153
|
+
const clientTxsOnWorker = mapOnWorker.core.getValidSortedTransactions();
|
|
154
|
+
const setTx = clientTxsOnWorker.find((tx) => {
|
|
155
|
+
const changes = tx.changes;
|
|
156
|
+
return (changes?.[0]?.key === "from" && changes[0]?.value === "skewed-client");
|
|
157
|
+
});
|
|
158
|
+
expect(setTx).toBeDefined();
|
|
159
|
+
const TOLERANCE_MS = 2000;
|
|
160
|
+
expect(setTx.madeAt).toBeGreaterThanOrEqual(realNowBeforeClient - TOLERANCE_MS);
|
|
161
|
+
expect(setTx.madeAt).toBeLessThanOrEqual(realNowAfter + TOLERANCE_MS);
|
|
162
|
+
expect(setTx.madeAt).toBeLessThan(realNowAfter + SKEW_MS - 5000);
|
|
163
|
+
const forbiddenFragments = [
|
|
164
|
+
"invalid transaction",
|
|
165
|
+
"permission",
|
|
166
|
+
"rejected",
|
|
167
|
+
"not authorized",
|
|
168
|
+
"not authorised",
|
|
169
|
+
"out of order",
|
|
170
|
+
];
|
|
171
|
+
const offendingCalls = [...errorSpy.mock.calls, ...errorSpyAfter.mock.calls]
|
|
172
|
+
.map((call) => call.map((arg) => String(arg)).join(" "))
|
|
173
|
+
.filter((line) => forbiddenFragments.some((f) => line.toLowerCase().includes(f)));
|
|
174
|
+
expect(offendingCalls).toEqual([]);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=clockDrift.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clockDrift.integration.test.js","sourceRoot":"","sources":["../../src/tests/clockDrift.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localNode.clockOffset.test.d.ts","sourceRoot":"","sources":["../../src/tests/localNode.clockOffset.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { ClockOffset } from "../ClockOffset.js";
|
|
3
|
+
import { LocalNode } from "../localNode.js";
|
|
4
|
+
import { randomAgentAndSessionID } from "./testUtils.js";
|
|
5
|
+
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
6
|
+
const Crypto = await WasmCrypto.create();
|
|
7
|
+
function makeNode(opts) {
|
|
8
|
+
const [admin, session] = randomAgentAndSessionID();
|
|
9
|
+
return new LocalNode(admin.agentSecret, session, Crypto, undefined, undefined, opts);
|
|
10
|
+
}
|
|
11
|
+
describe("LocalNode clock offset wiring", () => {
|
|
12
|
+
test("clockOffset is always present on the node, regardless of flag state", () => {
|
|
13
|
+
const withFlag = makeNode({ experimental_clockSyncFromServerPings: true });
|
|
14
|
+
const withoutFlag = makeNode({
|
|
15
|
+
experimental_clockSyncFromServerPings: false,
|
|
16
|
+
});
|
|
17
|
+
expect(withFlag.clockOffset).toBeInstanceOf(ClockOffset);
|
|
18
|
+
expect(withoutFlag.clockOffset).toBeInstanceOf(ClockOffset);
|
|
19
|
+
});
|
|
20
|
+
test("with the flag enabled, seeding clockOffset with a +10_000 ms sample pulls stampNow() forward by ~10_000 ms", () => {
|
|
21
|
+
const flagged = makeNode({ experimental_clockSyncFromServerPings: true });
|
|
22
|
+
const control = makeNode({
|
|
23
|
+
experimental_clockSyncFromServerPings: false,
|
|
24
|
+
});
|
|
25
|
+
const localReceiveTime = Date.now();
|
|
26
|
+
flagged.clockOffset.addSample({
|
|
27
|
+
serverTime: localReceiveTime + 10000,
|
|
28
|
+
localReceiveTime,
|
|
29
|
+
});
|
|
30
|
+
const controlStamp = control.stampNow();
|
|
31
|
+
const flaggedStamp = flagged.stampNow();
|
|
32
|
+
const delta = flaggedStamp - controlStamp;
|
|
33
|
+
expect(delta).toBeGreaterThanOrEqual(9900);
|
|
34
|
+
expect(delta).toBeLessThanOrEqual(10100);
|
|
35
|
+
});
|
|
36
|
+
test("getClockOffsetDiagnostics() reflects current offset and sample count", () => {
|
|
37
|
+
const node = makeNode({ experimental_clockSyncFromServerPings: true });
|
|
38
|
+
expect(node.getClockOffsetDiagnostics()).toEqual({
|
|
39
|
+
currentOffset: 0,
|
|
40
|
+
sampleCount: 0,
|
|
41
|
+
});
|
|
42
|
+
const base = Date.now();
|
|
43
|
+
node.clockOffset.addSample({
|
|
44
|
+
serverTime: base + 400,
|
|
45
|
+
localReceiveTime: base,
|
|
46
|
+
});
|
|
47
|
+
node.clockOffset.addSample({
|
|
48
|
+
serverTime: base + 600,
|
|
49
|
+
localReceiveTime: base,
|
|
50
|
+
});
|
|
51
|
+
expect(node.getClockOffsetDiagnostics()).toEqual({
|
|
52
|
+
currentOffset: 500,
|
|
53
|
+
sampleCount: 2,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
test("without the flag, seeding clockOffset with a +10_000 ms sample does NOT affect stampNow()", () => {
|
|
57
|
+
const node = makeNode({ experimental_clockSyncFromServerPings: false });
|
|
58
|
+
const localReceiveTime = Date.now();
|
|
59
|
+
node.clockOffset.addSample({
|
|
60
|
+
serverTime: localReceiveTime + 10000,
|
|
61
|
+
localReceiveTime,
|
|
62
|
+
});
|
|
63
|
+
const before = Date.now();
|
|
64
|
+
const stamp = node.stampNow();
|
|
65
|
+
const after = Date.now();
|
|
66
|
+
expect(stamp).toBeGreaterThanOrEqual(before);
|
|
67
|
+
expect(stamp).toBeLessThanOrEqual(after + 100);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=localNode.clockOffset.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localNode.clockOffset.test.js","sourceRoot":"","sources":["../../src/tests/localNode.clockOffset.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -139,6 +139,7 @@ export declare function setupTestNode(opts?: {
|
|
|
139
139
|
secret?: AgentSecret;
|
|
140
140
|
syncWhen?: SyncWhen;
|
|
141
141
|
enableFullStorageReconciliation?: boolean;
|
|
142
|
+
experimental_clockSyncFromServerPings?: boolean;
|
|
142
143
|
}): {
|
|
143
144
|
node: LocalNode;
|
|
144
145
|
connectToSyncServer: (opts?: {
|
|
@@ -176,6 +177,7 @@ export declare function setupTestAccount(opts?: {
|
|
|
176
177
|
storage?: StorageAPI;
|
|
177
178
|
accountID?: RawAccountID;
|
|
178
179
|
accountSecret?: AgentSecret;
|
|
180
|
+
experimental_clockSyncFromServerPings?: boolean;
|
|
179
181
|
}): Promise<{
|
|
180
182
|
node: LocalNode;
|
|
181
183
|
accountID: RawAccountID;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../src/tests/testUtils.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../src/tests/testUtils.ts"],"names":[],"mappings":"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"}
|
package/dist/tests/testUtils.js
CHANGED
|
@@ -289,7 +289,9 @@ export function setupTestNode(opts = {}) {
|
|
|
289
289
|
const [admin, session] = opts.secret
|
|
290
290
|
? agentAndSessionIDFromSecret(opts.secret)
|
|
291
291
|
: randomAgentAndSessionID();
|
|
292
|
-
let node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation
|
|
292
|
+
let node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation, {
|
|
293
|
+
experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
|
|
294
|
+
});
|
|
293
295
|
if (opts.isSyncServer) {
|
|
294
296
|
syncServer.current = node;
|
|
295
297
|
}
|
|
@@ -340,7 +342,9 @@ export function setupTestNode(opts = {}) {
|
|
|
340
342
|
addAsyncStorage,
|
|
341
343
|
restart: async () => {
|
|
342
344
|
await node.gracefulShutdown();
|
|
343
|
-
ctx.node = node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation
|
|
345
|
+
ctx.node = node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation, {
|
|
346
|
+
experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
|
|
347
|
+
});
|
|
344
348
|
if (opts.isSyncServer) {
|
|
345
349
|
syncServer.current = node;
|
|
346
350
|
}
|
|
@@ -352,6 +356,7 @@ export function setupTestNode(opts = {}) {
|
|
|
352
356
|
connected: opts.connected,
|
|
353
357
|
isSyncServer: opts.isSyncServer,
|
|
354
358
|
enableFullStorageReconciliation: opts.enableFullStorageReconciliation,
|
|
359
|
+
experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
|
|
355
360
|
});
|
|
356
361
|
},
|
|
357
362
|
disconnect: () => {
|
|
@@ -378,6 +383,7 @@ export async function setupTestAccount(opts = {}) {
|
|
|
378
383
|
accountID: opts.accountID,
|
|
379
384
|
accountSecret: opts.accountSecret,
|
|
380
385
|
sessionID: Crypto.newRandomSessionID(opts.accountID),
|
|
386
|
+
experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
|
|
381
387
|
}),
|
|
382
388
|
accountID: opts.accountID,
|
|
383
389
|
accountSecret: opts.accountSecret,
|
|
@@ -387,6 +393,7 @@ export async function setupTestAccount(opts = {}) {
|
|
|
387
393
|
crypto: Crypto,
|
|
388
394
|
creationProps: { name: "Client" },
|
|
389
395
|
storage: opts.storage,
|
|
396
|
+
experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
|
|
390
397
|
});
|
|
391
398
|
if (opts.isSyncServer) {
|
|
392
399
|
syncServer.current = ctx.node;
|