@pylonsync/sync 0.3.213 → 0.3.216
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/package.json +4 -1
- package/src/idb-warm-load.test.ts +426 -0
- package/src/index.ts +412 -12
- package/src/multi-tab-orchestrator.ts +80 -0
- package/src/persistence.ts +55 -0
- package/src/room-push.test.ts +197 -0
- package/src/room-subscriptions.test.ts +189 -0
- package/src/room-subscriptions.ts +301 -0
- package/src/test-harness/env.ts +6 -0
- package/src/test-harness/transport.ts +23 -0
package/src/test-harness/env.ts
CHANGED
|
@@ -62,6 +62,11 @@ export interface CreateTestEnvOptions {
|
|
|
62
62
|
* "poll" to disable the WS-onopen reconcile race in scenarios
|
|
63
63
|
* that only want to pin the in-start pipeline. */
|
|
64
64
|
transport?: "websocket" | "poll" | "sse";
|
|
65
|
+
/** Base delay (ms) for WS reconnect backoff. The default value used
|
|
66
|
+
* inside the harness (`undefined` → 1000) introduces seconds of
|
|
67
|
+
* wall-clock waiting on every reconnect scenario; pass a small
|
|
68
|
+
* value when the test specifically exercises the reconnect path. */
|
|
69
|
+
reconnectDelay?: number;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
export interface TestEnv {
|
|
@@ -116,6 +121,7 @@ export function createTestEnv(opts: CreateTestEnvOptions = {}): TestEnv {
|
|
|
116
121
|
persist: false,
|
|
117
122
|
storage,
|
|
118
123
|
transport: opts.transport ?? "websocket",
|
|
124
|
+
reconnectDelay: opts.reconnectDelay,
|
|
119
125
|
// Tight timings so scenarios don't have to sleep seconds. The
|
|
120
126
|
// engine's reconcile debounce is also relaxed so back-to-back
|
|
121
127
|
// visibility-change triggers don't get coalesced away in tests.
|
|
@@ -19,6 +19,10 @@ export interface TransportHandle {
|
|
|
19
19
|
fetchCount: () => number;
|
|
20
20
|
/** Number of WS connections opened so far. */
|
|
21
21
|
wsConnectCount: () => number;
|
|
22
|
+
/** Close the most-recently-opened mock WS so the engine sees a
|
|
23
|
+
* disconnect and schedules reconnect via its backoff. Returns
|
|
24
|
+
* true if a socket was actually closed, false otherwise. */
|
|
25
|
+
closeLatestWs: () => boolean;
|
|
22
26
|
/** Tear down the global stubs. */
|
|
23
27
|
restore: () => void;
|
|
24
28
|
}
|
|
@@ -33,6 +37,12 @@ export function installTransport(server: TestServer): TransportHandle {
|
|
|
33
37
|
let token: string | undefined;
|
|
34
38
|
let fetchCount = 0;
|
|
35
39
|
let wsConnectCount = 0;
|
|
40
|
+
// Track open mock sockets so a test that needs to simulate a
|
|
41
|
+
// server-side disconnect (cluster bounce, autostop) can grab the
|
|
42
|
+
// latest connection and close it. The engine's reconnect loop
|
|
43
|
+
// builds a fresh MockWebSocket on the next attempt; each shows up
|
|
44
|
+
// here in order so the list maps 1:1 to actual connect attempts.
|
|
45
|
+
const openSockets: MockWebSocket[] = [];
|
|
36
46
|
|
|
37
47
|
const originalFetch = globalThis.fetch;
|
|
38
48
|
const originalWS = (globalThis as { WebSocket?: unknown }).WebSocket;
|
|
@@ -87,6 +97,7 @@ export function installTransport(server: TestServer): TransportHandle {
|
|
|
87
97
|
super();
|
|
88
98
|
this.url = url;
|
|
89
99
|
wsConnectCount += 1;
|
|
100
|
+
openSockets.push(this);
|
|
90
101
|
// The engine encodes the token as `bearer.<percent-encoded>` in
|
|
91
102
|
// the WS subprotocol when one is set. Decode it so the harness
|
|
92
103
|
// can route this connection to the right subscriber bucket
|
|
@@ -144,6 +155,18 @@ export function installTransport(server: TestServer): TransportHandle {
|
|
|
144
155
|
},
|
|
145
156
|
fetchCount: () => fetchCount,
|
|
146
157
|
wsConnectCount: () => wsConnectCount,
|
|
158
|
+
closeLatestWs: () => {
|
|
159
|
+
// Walk back from the most recent socket to find one that's
|
|
160
|
+
// still open. Older closed sockets get skipped silently.
|
|
161
|
+
for (let i = openSockets.length - 1; i >= 0; i--) {
|
|
162
|
+
const s = openSockets[i];
|
|
163
|
+
if (s.readyState !== 3) {
|
|
164
|
+
s.close();
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
},
|
|
147
170
|
restore: () => {
|
|
148
171
|
globalThis.fetch = originalFetch;
|
|
149
172
|
if (originalWS) {
|