cojson-transport-ws 0.15.8 → 0.15.10
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 +14 -0
- package/dist/BatchedOutgoingMessages.d.ts +17 -6
- package/dist/BatchedOutgoingMessages.d.ts.map +1 -1
- package/dist/BatchedOutgoingMessages.js +77 -14
- package/dist/BatchedOutgoingMessages.js.map +1 -1
- package/dist/createWebSocketPeer.d.ts +0 -2
- package/dist/createWebSocketPeer.d.ts.map +1 -1
- package/dist/createWebSocketPeer.js +27 -84
- package/dist/createWebSocketPeer.js.map +1 -1
- package/dist/tests/createWebSocketPeer.test.js +64 -22
- package/dist/tests/createWebSocketPeer.test.js.map +1 -1
- package/dist/tests/syncServer.d.ts +1 -0
- package/dist/tests/syncServer.d.ts.map +1 -1
- package/dist/tests/syncServer.js +1 -0
- package/dist/tests/syncServer.js.map +1 -1
- package/dist/tests/webSocket.integration.test.d.ts +2 -0
- package/dist/tests/webSocket.integration.test.d.ts.map +1 -0
- package/dist/tests/{integration.test.js → webSocket.integration.test.js} +28 -2
- package/dist/tests/webSocket.integration.test.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +24 -0
- package/dist/utils.js.map +1 -0
- package/package.json +2 -2
- package/src/BatchedOutgoingMessages.ts +124 -16
- package/src/createWebSocketPeer.ts +33 -118
- package/src/tests/createWebSocketPeer.test.ts +87 -37
- package/src/tests/syncServer.ts +1 -0
- package/src/tests/{integration.test.ts → webSocket.integration.test.ts} +37 -2
- package/src/utils.ts +30 -0
- package/dist/tests/BatchedOutgoingMessages.test.d.ts +0 -2
- package/dist/tests/BatchedOutgoingMessages.test.d.ts.map +0 -1
- package/dist/tests/BatchedOutgoingMessages.test.js +0 -112
- package/dist/tests/BatchedOutgoingMessages.test.js.map +0 -1
- package/dist/tests/integration.test.d.ts +0 -2
- package/dist/tests/integration.test.d.ts.map +0 -1
- package/dist/tests/integration.test.js.map +0 -1
- package/src/tests/BatchedOutgoingMessages.test.ts +0 -146
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type { SyncMessage } from "cojson";
|
|
2
|
-
import
|
|
1
|
+
import type { CojsonInternalTypes, SyncMessage } from "cojson";
|
|
2
|
+
import { cojsonInternals } from "cojson";
|
|
3
3
|
import { type Mocked, describe, expect, test, vi } from "vitest";
|
|
4
4
|
import { MAX_OUTGOING_MESSAGES_CHUNK_BYTES } from "../BatchedOutgoingMessages.js";
|
|
5
5
|
import {
|
|
6
|
-
BUFFER_LIMIT,
|
|
7
|
-
BUFFER_LIMIT_POLLING_INTERVAL,
|
|
8
6
|
type CreateWebSocketPeerOpts,
|
|
9
7
|
createWebSocketPeer,
|
|
10
8
|
} from "../createWebSocketPeer.js";
|
|
11
9
|
import type { AnyWebSocket } from "../types.js";
|
|
10
|
+
import { BUFFER_LIMIT, BUFFER_LIMIT_POLLING_INTERVAL } from "../utils.js";
|
|
11
|
+
|
|
12
|
+
const { CO_VALUE_PRIORITY } = cojsonInternals;
|
|
12
13
|
|
|
13
14
|
function setup(opts: Partial<CreateWebSocketPeerOpts> = {}) {
|
|
14
15
|
const listeners = new Map<string, (event: MessageEvent) => void>();
|
|
@@ -48,34 +49,28 @@ describe("createWebSocketPeer", () => {
|
|
|
48
49
|
expect(peer).toHaveProperty("incoming");
|
|
49
50
|
expect(peer).toHaveProperty("outgoing");
|
|
50
51
|
expect(peer).toHaveProperty("role", "client");
|
|
51
|
-
expect(peer).toHaveProperty("crashOnClose", false);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
test("should handle disconnection", async () => {
|
|
55
|
-
expect.assertions(1);
|
|
56
|
-
|
|
57
55
|
const { listeners, peer } = setup();
|
|
58
56
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
>;
|
|
62
|
-
const pushSpy = vi.spyOn(incoming, "push");
|
|
57
|
+
const onMessageSpy = vi.fn();
|
|
58
|
+
peer.incoming.onMessage(onMessageSpy);
|
|
63
59
|
|
|
64
60
|
const closeHandler = listeners.get("close");
|
|
65
61
|
|
|
66
62
|
closeHandler?.(new MessageEvent("close"));
|
|
67
63
|
|
|
68
|
-
expect(
|
|
64
|
+
expect(onMessageSpy).toHaveBeenCalledWith("Disconnected");
|
|
69
65
|
});
|
|
70
66
|
|
|
71
67
|
test("should handle ping timeout", async () => {
|
|
72
68
|
vi.useFakeTimers();
|
|
73
69
|
const { listeners, peer } = setup();
|
|
74
70
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const pushSpy = vi.spyOn(incoming, "push");
|
|
71
|
+
const onMessageSpy = vi.fn();
|
|
72
|
+
|
|
73
|
+
peer.incoming.onMessage(onMessageSpy);
|
|
79
74
|
|
|
80
75
|
const messageHandler = listeners.get("message");
|
|
81
76
|
|
|
@@ -83,7 +78,7 @@ describe("createWebSocketPeer", () => {
|
|
|
83
78
|
|
|
84
79
|
await vi.advanceTimersByTimeAsync(10_000);
|
|
85
80
|
|
|
86
|
-
expect(
|
|
81
|
+
expect(onMessageSpy).toHaveBeenCalledWith("Disconnected");
|
|
87
82
|
|
|
88
83
|
vi.useRealTimers();
|
|
89
84
|
});
|
|
@@ -97,15 +92,14 @@ describe("createWebSocketPeer", () => {
|
|
|
97
92
|
header: false,
|
|
98
93
|
sessions: {},
|
|
99
94
|
};
|
|
100
|
-
|
|
95
|
+
|
|
96
|
+
peer.outgoing.push(testMessage);
|
|
101
97
|
|
|
102
98
|
await waitFor(() => {
|
|
103
99
|
expect(mockWebSocket.send).toHaveBeenCalledWith(
|
|
104
100
|
JSON.stringify(testMessage),
|
|
105
101
|
);
|
|
106
102
|
});
|
|
107
|
-
|
|
108
|
-
await expect(promise).resolves.toBeUndefined();
|
|
109
103
|
});
|
|
110
104
|
|
|
111
105
|
test("should stop sending messages when the websocket is closed", async () => {
|
|
@@ -153,23 +147,6 @@ describe("createWebSocketPeer", () => {
|
|
|
153
147
|
expect(mockWebSocket.close).toHaveBeenCalled();
|
|
154
148
|
});
|
|
155
149
|
|
|
156
|
-
test("should return a rejection if a message is sent after the peer is closed", async () => {
|
|
157
|
-
const { peer } = setup();
|
|
158
|
-
|
|
159
|
-
peer.outgoing.close();
|
|
160
|
-
|
|
161
|
-
const message: SyncMessage = {
|
|
162
|
-
action: "known",
|
|
163
|
-
id: "co_ztest",
|
|
164
|
-
header: false,
|
|
165
|
-
sessions: {},
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
await expect(peer.outgoing.push(message)).rejects.toThrow(
|
|
169
|
-
"WebSocket closed",
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
150
|
test("should call onSuccess handler after receiving first message", () => {
|
|
174
151
|
const onSuccess = vi.fn();
|
|
175
152
|
const { listeners } = setup({ onSuccess });
|
|
@@ -229,6 +206,42 @@ describe("createWebSocketPeer", () => {
|
|
|
229
206
|
);
|
|
230
207
|
});
|
|
231
208
|
|
|
209
|
+
test("should sort outgoing messages by priority", async () => {
|
|
210
|
+
const { peer, mockWebSocket } = setup();
|
|
211
|
+
|
|
212
|
+
mockWebSocket.send.mockImplementation(() => {
|
|
213
|
+
mockWebSocket.readyState = 0;
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const message1: SyncMessage = {
|
|
217
|
+
action: "content",
|
|
218
|
+
id: "co_zlow",
|
|
219
|
+
new: {},
|
|
220
|
+
priority: CO_VALUE_PRIORITY.LOW,
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const message2: SyncMessage = {
|
|
224
|
+
action: "content",
|
|
225
|
+
id: "co_zhigh",
|
|
226
|
+
new: {},
|
|
227
|
+
priority: CO_VALUE_PRIORITY.HIGH,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
void peer.outgoing.push(message1);
|
|
231
|
+
void peer.outgoing.push(message2);
|
|
232
|
+
void peer.outgoing.push(message2);
|
|
233
|
+
|
|
234
|
+
await waitFor(() => {
|
|
235
|
+
expect(mockWebSocket.send).toHaveBeenCalled();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
expect(mockWebSocket.send).toHaveBeenCalledWith(
|
|
239
|
+
[message2, message2, message1]
|
|
240
|
+
.map((msg) => JSON.stringify(msg))
|
|
241
|
+
.join("\n"),
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
232
245
|
test("should send all the pending messages when the websocket is closed", async () => {
|
|
233
246
|
const { peer, mockWebSocket } = setup();
|
|
234
247
|
|
|
@@ -298,6 +311,43 @@ describe("createWebSocketPeer", () => {
|
|
|
298
311
|
);
|
|
299
312
|
});
|
|
300
313
|
|
|
314
|
+
test("should send accumulated messages before a large message", async () => {
|
|
315
|
+
const { peer, mockWebSocket } = setup();
|
|
316
|
+
|
|
317
|
+
const smallMessage: SyncMessage = {
|
|
318
|
+
action: "known",
|
|
319
|
+
id: "co_z_small",
|
|
320
|
+
header: false,
|
|
321
|
+
sessions: {},
|
|
322
|
+
};
|
|
323
|
+
const largeMessage: SyncMessage = {
|
|
324
|
+
action: "known",
|
|
325
|
+
id: "co_z_large",
|
|
326
|
+
header: false,
|
|
327
|
+
sessions: {
|
|
328
|
+
// Add a large payload to exceed MAX_OUTGOING_MESSAGES_CHUNK_BYTES
|
|
329
|
+
payload: "x".repeat(MAX_OUTGOING_MESSAGES_CHUNK_BYTES),
|
|
330
|
+
} as CojsonInternalTypes.CoValueKnownState["sessions"],
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
void peer.outgoing.push(smallMessage);
|
|
334
|
+
void peer.outgoing.push(largeMessage);
|
|
335
|
+
|
|
336
|
+
await waitFor(() => {
|
|
337
|
+
expect(mockWebSocket.send).toHaveBeenCalledTimes(2);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
expect(mockWebSocket.send).toHaveBeenCalledTimes(2);
|
|
341
|
+
expect(mockWebSocket.send).toHaveBeenNthCalledWith(
|
|
342
|
+
1,
|
|
343
|
+
JSON.stringify(smallMessage),
|
|
344
|
+
);
|
|
345
|
+
expect(mockWebSocket.send).toHaveBeenNthCalledWith(
|
|
346
|
+
2,
|
|
347
|
+
JSON.stringify(largeMessage),
|
|
348
|
+
);
|
|
349
|
+
});
|
|
350
|
+
|
|
301
351
|
test("should wait for the buffer to be under BUFFER_LIMIT before sending more messages", async () => {
|
|
302
352
|
vi.useFakeTimers();
|
|
303
353
|
const { peer, mockWebSocket } = setup();
|
package/src/tests/syncServer.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assert } from "node:console";
|
|
1
2
|
import { ControlledAgent, type CryptoProvider, LocalNode } from "cojson";
|
|
2
3
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
|
3
4
|
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
@@ -7,7 +8,7 @@ import { startSyncServer } from "./syncServer";
|
|
|
7
8
|
import { waitFor } from "./utils";
|
|
8
9
|
|
|
9
10
|
describe("WebSocket Peer Integration", () => {
|
|
10
|
-
let server:
|
|
11
|
+
let server: Awaited<ReturnType<typeof startSyncServer>>;
|
|
11
12
|
let syncServerUrl: string;
|
|
12
13
|
let crypto: CryptoProvider;
|
|
13
14
|
|
|
@@ -93,7 +94,11 @@ describe("WebSocket Peer Integration", () => {
|
|
|
93
94
|
const serverNode = server.localNode;
|
|
94
95
|
const serverMap = await serverNode.load(map.id);
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
if (serverMap === "unavailable") {
|
|
98
|
+
throw new Error("Server map is unavailable");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
expect(serverMap.get("testKey")?.toString()).toBe("testValue");
|
|
97
102
|
});
|
|
98
103
|
|
|
99
104
|
test("should handle disconnection and cleanup", async () => {
|
|
@@ -161,4 +166,34 @@ describe("WebSocket Peer Integration", () => {
|
|
|
161
166
|
|
|
162
167
|
expect(ws.readyState).toBe(WebSocket.CLOSED);
|
|
163
168
|
});
|
|
169
|
+
|
|
170
|
+
test("calling terminate on the server should close the connection", async () => {
|
|
171
|
+
const ws = new WebSocket(syncServerUrl);
|
|
172
|
+
let disconnectCalled = false;
|
|
173
|
+
|
|
174
|
+
createWebSocketPeer({
|
|
175
|
+
id: "test-client",
|
|
176
|
+
websocket: ws,
|
|
177
|
+
role: "server",
|
|
178
|
+
onClose: () => {
|
|
179
|
+
disconnectCalled = true;
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await waitFor(() => {
|
|
184
|
+
expect(server.wss.clients.size).toBe(1);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const peerOnServer = server.localNode.syncManager.getPeers()[0];
|
|
188
|
+
|
|
189
|
+
for (const client of server.wss.clients) {
|
|
190
|
+
client.terminate();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await waitFor(() => {
|
|
194
|
+
expect(disconnectCalled).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
expect(peerOnServer?.closed).toBe(true);
|
|
198
|
+
});
|
|
164
199
|
});
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AnyWebSocket } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export const BUFFER_LIMIT = 100_000;
|
|
4
|
+
export const BUFFER_LIMIT_POLLING_INTERVAL = 10;
|
|
5
|
+
|
|
6
|
+
export function isWebSocketOpen(websocket: AnyWebSocket) {
|
|
7
|
+
return websocket.readyState === 1;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function hasWebSocketTooMuchBufferedData(websocket: AnyWebSocket) {
|
|
11
|
+
return websocket.bufferedAmount > BUFFER_LIMIT && isWebSocketOpen(websocket);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function waitForWebSocketOpen(websocket: AnyWebSocket) {
|
|
15
|
+
return new Promise<void>((resolve) => {
|
|
16
|
+
if (websocket.readyState === 1) {
|
|
17
|
+
resolve();
|
|
18
|
+
} else {
|
|
19
|
+
websocket.addEventListener("open", () => resolve(), { once: true });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function waitForWebSocketBufferedAmount(websocket: AnyWebSocket) {
|
|
25
|
+
while (hasWebSocketTooMuchBufferedData(websocket)) {
|
|
26
|
+
await new Promise<void>((resolve) =>
|
|
27
|
+
setTimeout(resolve, BUFFER_LIMIT_POLLING_INTERVAL),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BatchedOutgoingMessages.test.d.ts","sourceRoot":"","sources":["../../src/tests/BatchedOutgoingMessages.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
-
import { BatchedOutgoingMessages, MAX_OUTGOING_MESSAGES_CHUNK_BYTES, } from "../BatchedOutgoingMessages.js";
|
|
3
|
-
beforeEach(() => {
|
|
4
|
-
vi.useFakeTimers();
|
|
5
|
-
});
|
|
6
|
-
afterEach(() => {
|
|
7
|
-
vi.useRealTimers();
|
|
8
|
-
});
|
|
9
|
-
describe("BatchedOutgoingMessages", () => {
|
|
10
|
-
function setup() {
|
|
11
|
-
const sendMock = vi.fn();
|
|
12
|
-
const batchedMessages = new BatchedOutgoingMessages(sendMock);
|
|
13
|
-
return { sendMock, batchedMessages };
|
|
14
|
-
}
|
|
15
|
-
test("should batch messages and send them after a timeout", () => {
|
|
16
|
-
const { sendMock, batchedMessages } = setup();
|
|
17
|
-
const message1 = {
|
|
18
|
-
action: "known",
|
|
19
|
-
id: "co_z1",
|
|
20
|
-
header: false,
|
|
21
|
-
sessions: {},
|
|
22
|
-
};
|
|
23
|
-
const message2 = {
|
|
24
|
-
action: "known",
|
|
25
|
-
id: "co_z2",
|
|
26
|
-
header: false,
|
|
27
|
-
sessions: {},
|
|
28
|
-
};
|
|
29
|
-
batchedMessages.push(message1);
|
|
30
|
-
batchedMessages.push(message2);
|
|
31
|
-
expect(sendMock).not.toHaveBeenCalled();
|
|
32
|
-
vi.runAllTimers();
|
|
33
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
34
|
-
expect(sendMock).toHaveBeenCalledWith(`${JSON.stringify(message1)}\n${JSON.stringify(message2)}`);
|
|
35
|
-
});
|
|
36
|
-
test("should send messages immediately when reaching MAX_OUTGOING_MESSAGES_CHUNK_BYTES", () => {
|
|
37
|
-
const { sendMock, batchedMessages } = setup();
|
|
38
|
-
const largeMessage = {
|
|
39
|
-
action: "known",
|
|
40
|
-
id: "co_z_large",
|
|
41
|
-
header: false,
|
|
42
|
-
sessions: {
|
|
43
|
-
// Add a large payload to exceed MAX_OUTGOING_MESSAGES_CHUNK_BYTES
|
|
44
|
-
payload: "x".repeat(MAX_OUTGOING_MESSAGES_CHUNK_BYTES),
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
batchedMessages.push(largeMessage);
|
|
48
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
49
|
-
expect(sendMock).toHaveBeenCalledWith(JSON.stringify(largeMessage));
|
|
50
|
-
});
|
|
51
|
-
test("should send accumulated messages before a large message", () => {
|
|
52
|
-
const { sendMock, batchedMessages } = setup();
|
|
53
|
-
const smallMessage = {
|
|
54
|
-
action: "known",
|
|
55
|
-
id: "co_z_small",
|
|
56
|
-
header: false,
|
|
57
|
-
sessions: {},
|
|
58
|
-
};
|
|
59
|
-
const largeMessage = {
|
|
60
|
-
action: "known",
|
|
61
|
-
id: "co_z_large",
|
|
62
|
-
header: false,
|
|
63
|
-
sessions: {
|
|
64
|
-
// Add a large payload to exceed MAX_OUTGOING_MESSAGES_CHUNK_BYTES
|
|
65
|
-
payload: "x".repeat(MAX_OUTGOING_MESSAGES_CHUNK_BYTES),
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
batchedMessages.push(smallMessage);
|
|
69
|
-
batchedMessages.push(largeMessage);
|
|
70
|
-
vi.runAllTimers();
|
|
71
|
-
expect(sendMock).toHaveBeenCalledTimes(2);
|
|
72
|
-
expect(sendMock).toHaveBeenNthCalledWith(1, JSON.stringify(smallMessage));
|
|
73
|
-
expect(sendMock).toHaveBeenNthCalledWith(2, JSON.stringify(largeMessage));
|
|
74
|
-
});
|
|
75
|
-
test("should send remaining messages on close", () => {
|
|
76
|
-
const { sendMock, batchedMessages } = setup();
|
|
77
|
-
const message = {
|
|
78
|
-
action: "known",
|
|
79
|
-
id: "co_z_test",
|
|
80
|
-
header: false,
|
|
81
|
-
sessions: {},
|
|
82
|
-
};
|
|
83
|
-
batchedMessages.push(message);
|
|
84
|
-
expect(sendMock).not.toHaveBeenCalled();
|
|
85
|
-
batchedMessages.close();
|
|
86
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
87
|
-
expect(sendMock).toHaveBeenCalledWith(JSON.stringify(message));
|
|
88
|
-
});
|
|
89
|
-
test("should clear timeout when pushing new messages", () => {
|
|
90
|
-
const { sendMock, batchedMessages } = setup();
|
|
91
|
-
const message1 = {
|
|
92
|
-
action: "known",
|
|
93
|
-
id: "co_z1",
|
|
94
|
-
header: false,
|
|
95
|
-
sessions: {},
|
|
96
|
-
};
|
|
97
|
-
const message2 = {
|
|
98
|
-
action: "known",
|
|
99
|
-
id: "co_z2",
|
|
100
|
-
header: false,
|
|
101
|
-
sessions: {},
|
|
102
|
-
};
|
|
103
|
-
batchedMessages.push(message1);
|
|
104
|
-
const clearTimeoutSpy = vi.spyOn(global, "clearTimeout");
|
|
105
|
-
batchedMessages.push(message2);
|
|
106
|
-
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
107
|
-
vi.runAllTimers();
|
|
108
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
109
|
-
expect(sendMock).toHaveBeenCalledWith(`${JSON.stringify(message1)}\n${JSON.stringify(message2)}`);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
//# sourceMappingURL=BatchedOutgoingMessages.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BatchedOutgoingMessages.test.js","sourceRoot":"","sources":["../../src/tests/BatchedOutgoingMessages.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../src/tests/integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { SyncMessage } from "cojson";
|
|
2
|
-
import type { CojsonInternalTypes } from "cojson";
|
|
3
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
BatchedOutgoingMessages,
|
|
6
|
-
MAX_OUTGOING_MESSAGES_CHUNK_BYTES,
|
|
7
|
-
} from "../BatchedOutgoingMessages.js";
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
vi.useFakeTimers();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
vi.useRealTimers();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
describe("BatchedOutgoingMessages", () => {
|
|
18
|
-
function setup() {
|
|
19
|
-
const sendMock = vi.fn();
|
|
20
|
-
const batchedMessages = new BatchedOutgoingMessages(sendMock);
|
|
21
|
-
return { sendMock, batchedMessages };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
test("should batch messages and send them after a timeout", () => {
|
|
25
|
-
const { sendMock, batchedMessages } = setup();
|
|
26
|
-
const message1: SyncMessage = {
|
|
27
|
-
action: "known",
|
|
28
|
-
id: "co_z1",
|
|
29
|
-
header: false,
|
|
30
|
-
sessions: {},
|
|
31
|
-
};
|
|
32
|
-
const message2: SyncMessage = {
|
|
33
|
-
action: "known",
|
|
34
|
-
id: "co_z2",
|
|
35
|
-
header: false,
|
|
36
|
-
sessions: {},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
batchedMessages.push(message1);
|
|
40
|
-
batchedMessages.push(message2);
|
|
41
|
-
|
|
42
|
-
expect(sendMock).not.toHaveBeenCalled();
|
|
43
|
-
|
|
44
|
-
vi.runAllTimers();
|
|
45
|
-
|
|
46
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
47
|
-
expect(sendMock).toHaveBeenCalledWith(
|
|
48
|
-
`${JSON.stringify(message1)}\n${JSON.stringify(message2)}`,
|
|
49
|
-
);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test("should send messages immediately when reaching MAX_OUTGOING_MESSAGES_CHUNK_BYTES", () => {
|
|
53
|
-
const { sendMock, batchedMessages } = setup();
|
|
54
|
-
const largeMessage: SyncMessage = {
|
|
55
|
-
action: "known",
|
|
56
|
-
id: "co_z_large",
|
|
57
|
-
header: false,
|
|
58
|
-
sessions: {
|
|
59
|
-
// Add a large payload to exceed MAX_OUTGOING_MESSAGES_CHUNK_BYTES
|
|
60
|
-
payload: "x".repeat(MAX_OUTGOING_MESSAGES_CHUNK_BYTES),
|
|
61
|
-
} as CojsonInternalTypes.CoValueKnownState["sessions"],
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
batchedMessages.push(largeMessage);
|
|
65
|
-
|
|
66
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
67
|
-
expect(sendMock).toHaveBeenCalledWith(JSON.stringify(largeMessage));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("should send accumulated messages before a large message", () => {
|
|
71
|
-
const { sendMock, batchedMessages } = setup();
|
|
72
|
-
const smallMessage: SyncMessage = {
|
|
73
|
-
action: "known",
|
|
74
|
-
id: "co_z_small",
|
|
75
|
-
header: false,
|
|
76
|
-
sessions: {},
|
|
77
|
-
};
|
|
78
|
-
const largeMessage: SyncMessage = {
|
|
79
|
-
action: "known",
|
|
80
|
-
id: "co_z_large",
|
|
81
|
-
header: false,
|
|
82
|
-
sessions: {
|
|
83
|
-
// Add a large payload to exceed MAX_OUTGOING_MESSAGES_CHUNK_BYTES
|
|
84
|
-
payload: "x".repeat(MAX_OUTGOING_MESSAGES_CHUNK_BYTES),
|
|
85
|
-
} as CojsonInternalTypes.CoValueKnownState["sessions"],
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
batchedMessages.push(smallMessage);
|
|
89
|
-
batchedMessages.push(largeMessage);
|
|
90
|
-
|
|
91
|
-
vi.runAllTimers();
|
|
92
|
-
|
|
93
|
-
expect(sendMock).toHaveBeenCalledTimes(2);
|
|
94
|
-
expect(sendMock).toHaveBeenNthCalledWith(1, JSON.stringify(smallMessage));
|
|
95
|
-
expect(sendMock).toHaveBeenNthCalledWith(2, JSON.stringify(largeMessage));
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("should send remaining messages on close", () => {
|
|
99
|
-
const { sendMock, batchedMessages } = setup();
|
|
100
|
-
const message: SyncMessage = {
|
|
101
|
-
action: "known",
|
|
102
|
-
id: "co_z_test",
|
|
103
|
-
header: false,
|
|
104
|
-
sessions: {},
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
batchedMessages.push(message);
|
|
108
|
-
expect(sendMock).not.toHaveBeenCalled();
|
|
109
|
-
|
|
110
|
-
batchedMessages.close();
|
|
111
|
-
|
|
112
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
113
|
-
expect(sendMock).toHaveBeenCalledWith(JSON.stringify(message));
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test("should clear timeout when pushing new messages", () => {
|
|
117
|
-
const { sendMock, batchedMessages } = setup();
|
|
118
|
-
const message1: SyncMessage = {
|
|
119
|
-
action: "known",
|
|
120
|
-
id: "co_z1",
|
|
121
|
-
header: false,
|
|
122
|
-
sessions: {},
|
|
123
|
-
};
|
|
124
|
-
const message2: SyncMessage = {
|
|
125
|
-
action: "known",
|
|
126
|
-
id: "co_z2",
|
|
127
|
-
header: false,
|
|
128
|
-
sessions: {},
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
batchedMessages.push(message1);
|
|
132
|
-
|
|
133
|
-
const clearTimeoutSpy = vi.spyOn(global, "clearTimeout");
|
|
134
|
-
|
|
135
|
-
batchedMessages.push(message2);
|
|
136
|
-
|
|
137
|
-
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
138
|
-
|
|
139
|
-
vi.runAllTimers();
|
|
140
|
-
|
|
141
|
-
expect(sendMock).toHaveBeenCalledTimes(1);
|
|
142
|
-
expect(sendMock).toHaveBeenCalledWith(
|
|
143
|
-
`${JSON.stringify(message1)}\n${JSON.stringify(message2)}`,
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
});
|