@livestore/webmesh 0.4.0-dev.15 → 0.4.0-dev.17

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.
@@ -1,130 +0,0 @@
1
- import { MessageChannel } from 'node:worker_threads';
2
- import { Deferred, Duration, Effect, Fiber, Option, Schema, Stream, WebChannel } from '@livestore/utils/effect';
3
- import { Vitest } from '@livestore/utils-dev/node-vitest';
4
- import { expect } from 'vitest';
5
- import { makeMeshNode } from "./node.js";
6
- import { Packet } from "./mesh-schema.js";
7
- // This test models the observed DevTools behavior during reload: a single leader ping
8
- // times out at handover while clientSession ping remains ok shortly after.
9
- // We use actual Mesh + WebChannel implementations (MessagePort edge, direct channel).
10
- // We assert the desired correct behavior (leader should not timeout across handover),
11
- // which currently FAILS and documents the problem with a minimal repro.
12
- const Ping = Schema.TaggedStruct('Ping', { who: Schema.String, id: Schema.String, t0: Schema.Number });
13
- const Pong = Schema.TaggedStruct('Pong', { who: Schema.String, id: Schema.String, t0: Schema.Number });
14
- const Msg = Schema.Union(Ping, Pong);
15
- const connectViaMessagePort = (a, b) => Effect.gen(function* () {
16
- const mc = new MessageChannel();
17
- const ab = yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Packet });
18
- const ba = yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Packet });
19
- yield* a.addEdge({ target: b.nodeName, edgeChannel: ab, replaceIfExists: true });
20
- yield* b.addEdge({ target: a.nodeName, edgeChannel: ba, replaceIfExists: true });
21
- });
22
- const sendPing = (channel, who, timeoutMs, sendAckTimeoutMs) => Effect.gen(function* () {
23
- const id = Math.random().toString(36).slice(2);
24
- const wait = channel.listen
25
- .pipe(Stream.flatten(), Stream.filter(Schema.is(Pong)), Stream.filter((m) => m.id === id), Stream.runHead);
26
- yield* channel
27
- .send(Ping.make({ who, id, t0: Date.now() }))
28
- .pipe(
29
- // Prevent tests from stalling on ack when the receiver is about to be shutdown
30
- Effect.timeout(Duration.millis(sendAckTimeoutMs ?? timeoutMs)), Effect.catchTag('TimeoutException', () => Effect.void));
31
- const res = yield* wait
32
- .pipe(Effect.map((opt) => (Option.isSome(opt) ? 'ok' : 'timeout')), Effect.timeout(Duration.millis(timeoutMs)), Effect.catchTag('TimeoutException', () => Effect.succeed('timeout')));
33
- return res;
34
- });
35
- Vitest.scopedLive('leader ping should not timeout across reload handover (currently fails)', (test) => Effect.gen(function* () {
36
- const LEADER_TIMEOUT_MS = 80;
37
- const CLIENT_TIMEOUT_MS = 400;
38
- // Nodes
39
- const worker = yield* makeMeshNode('shared-worker');
40
- const devtools = yield* makeMeshNode('devtools-instance');
41
- yield* connectViaMessagePort(worker, devtools);
42
- // Channels: leader
43
- const workerLeader = yield* worker.makeChannel({
44
- target: devtools.nodeName,
45
- channelName: 'leader',
46
- schema: Msg,
47
- mode: 'direct',
48
- closeExisting: true,
49
- });
50
- let devtoolsLeader = yield* devtools.makeChannel({
51
- target: worker.nodeName,
52
- channelName: 'leader',
53
- schema: Msg,
54
- mode: 'direct',
55
- closeExisting: true,
56
- });
57
- // Channels: clientSession
58
- const workerClient = yield* worker.makeChannel({
59
- target: devtools.nodeName,
60
- channelName: 'client',
61
- schema: Msg,
62
- mode: 'direct',
63
- closeExisting: true,
64
- });
65
- const devtoolsClient = yield* devtools.makeChannel({
66
- target: worker.nodeName,
67
- channelName: 'client',
68
- schema: Msg,
69
- mode: 'direct',
70
- closeExisting: true,
71
- });
72
- // Gates to coordinate ordering precisely: ensure Ping acked before shutdown, Pong after
73
- const allowLeaderPong = yield* Deferred.make();
74
- // Responder behavior on worker: on Ping, mark received, then wait for gate to send Pong
75
- const workerLeaderListenFiber = yield* workerLeader.listen
76
- .pipe(Stream.flatten(), Stream.take(1), Stream.tap((m) => Schema.is(Ping)(m)
77
- ? Effect.gen(function* () {
78
- // Hold back Pong until the test signals (post-shutdown), then drop it
79
- // to simulate a lost Pong to a closed pre-reload listener. Avoids ack
80
- // backpressure that could stall scope shutdown.
81
- yield* Deferred.await(allowLeaderPong);
82
- yield* Effect.void;
83
- })
84
- : Effect.void), Stream.runDrain, Effect.fork);
85
- const workerClientListenFiber = yield* workerClient.listen
86
- .pipe(Stream.flatten(), Stream.take(1), Stream.tap((m) => (Schema.is(Ping)(m) ? workerClient.send(Pong.make({ who: m.who, id: m.id, t0: m.t0 })) : Effect.void)), Stream.runDrain, Effect.fork);
87
- // 1) Start leader ping on current (pre-reload) channel and let it run concurrently
88
- // This ensures the ping is in-flight before we shut down the old listener.
89
- console.log('[test] forking leader ping (old channel)');
90
- const leaderFiber = yield* sendPing(devtoolsLeader, 'leader', LEADER_TIMEOUT_MS, 20).pipe(Effect.fork);
91
- // Yield and sleep briefly to allow the forked fiber to start and send
92
- yield* Effect.yieldNow();
93
- yield* Effect.sleep(Duration.millis(10));
94
- console.log('[test] shutting down old leader channel');
95
- // 2) Simulate reload handover: shutdown old leader channel listener; open new leader channel
96
- yield* devtoolsLeader.shutdown;
97
- console.log('[test] opening new leader channel');
98
- devtoolsLeader = yield* devtools.makeChannel({
99
- target: worker.nodeName,
100
- channelName: 'leader',
101
- schema: Msg,
102
- mode: 'direct',
103
- closeExisting: true,
104
- });
105
- // 3) Now allow the worker to send the Pong (which targets the old listener and should be lost)
106
- console.log('[test] allowing leader pong on worker');
107
- yield* Deferred.succeed(allowLeaderPong, void 0);
108
- // Client ping on fresh channel should still succeed
109
- console.log('[test] sending clientSession ping');
110
- const clientRes = yield* sendPing(devtoolsClient, 'clientSession', CLIENT_TIMEOUT_MS);
111
- console.log('[test] clientSession ping done', clientRes);
112
- // 4) Now join the leader result — currently this times out because
113
- // the Pong was delivered to the old, already-shutdown listener. The correct
114
- // behavior would be that leader does not timeout across reload.
115
- console.log('[test] joining leader ping fiber');
116
- const leaderRes = yield* Fiber.join(leaderFiber)
117
- .pipe(
118
- // Guard against join hanging; if it does, fail by assertion rather than test-level timeout
119
- Effect.timeout(Duration.millis(500)), Effect.catchTag('TimeoutException', () => Effect.succeed('HARD_TIMEOUT')));
120
- console.log('[test] leader ping joined', leaderRes);
121
- // Cleanup listening fibers
122
- yield* Fiber.interrupt(workerLeaderListenFiber);
123
- yield* Fiber.interrupt(workerClientListenFiber);
124
- // Expected (correct): no timeout
125
- // Actual (today): timeout → this assertion FAILS and documents the problem.
126
- expect(leaderRes).not.toBe('HARD_TIMEOUT');
127
- expect(leaderRes).toBe('ok');
128
- expect(clientRes).toBe('ok');
129
- }).pipe(Vitest.withTestCtx(test)), 10_000);
130
- //# sourceMappingURL=reload-handover.mesh.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-handover.mesh.test.js","sourceRoot":"","sources":["../src/reload-handover.mesh.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=reload-reconnect.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-reconnect.test.d.ts","sourceRoot":"","sources":["../src/reload-reconnect.test.ts"],"names":[],"mappings":""}
@@ -1,62 +0,0 @@
1
- import { MessageChannel } from 'node:worker_threads';
2
- import { Effect, Schema, Stream, WebChannel } from '@livestore/utils/effect';
3
- import { Vitest } from '@livestore/utils-dev/node-vitest';
4
- import { expect } from 'vitest';
5
- // This test encodes a minimal reload/reconnect scenario over a single MessagePort where
6
- // one leader Pong is dropped exactly at the reload handover window. Today, DevTools
7
- // observations show a single leader timeout near reload while clientSession pings continue
8
- // to succeed. We assert the desired correct behavior (no timeout for leader), which currently
9
- // FAILS, documenting the problem and providing a minimal repro target.
10
- // NOTE: This test uses WebChannel directly (no Mesh) to isolate transport scheduling from Mesh logic.
11
- // It simulates handover by deliberately dropping one leader Pong.
12
- const Ping = Schema.TaggedStruct('Ping', { who: Schema.String, id: Schema.String, t0: Schema.Number });
13
- const Pong = Schema.TaggedStruct('Pong', { who: Schema.String, id: Schema.String, t0: Schema.Number });
14
- const Msg = Schema.Union(Ping, Pong);
15
- const sendPing = (channel, who, timeoutMs) => Effect.gen(function* () {
16
- const id = Math.random().toString(36).slice(2);
17
- const wait = channel.listen
18
- .pipe(Stream.flatten(), Stream.filter(Schema.is(Pong)), Stream.filter((m) => m.id === id), Stream.runHead)
19
- .pipe(Effect.asVoid);
20
- yield* channel.send(Ping.make({ who, id, t0: Date.now() }));
21
- const res = yield* wait
22
- .pipe(Effect.timeout(timeoutMs), Effect.as('ok'), Effect.catchTag('TimeoutException', () => Effect.succeed('timeout')));
23
- return res;
24
- });
25
- Vitest.scopedLive('reload handover: leader ping should not timeout (currently fails)', (test) => Effect.gen(function* () {
26
- // Timings tuned to force a single leader miss at handover
27
- const RELOAD_AT_MS = 300;
28
- const DROP_WINDOW_MS = 80;
29
- const LEADER_TIMEOUT_MS = 50;
30
- const CLIENT_TIMEOUT_MS = 400;
31
- const mc = new MessageChannel();
32
- const a = yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Msg });
33
- const b = yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Msg });
34
- const t0 = Date.now();
35
- let dropLeaderNext = false;
36
- // A: responder drop exactly one leader Pong after reload starts
37
- yield* a.listen
38
- .pipe(Stream.flatten(), Stream.tap((m) => Effect.gen(function* () {
39
- if (Schema.is(Ping)(m)) {
40
- const now = Date.now();
41
- if (m.who === 'leader' && dropLeaderNext) {
42
- // Simulate handover gap: drop one leader Pong
43
- // This models the observed single leader timeout after reload.
44
- dropLeaderNext = false;
45
- }
46
- else {
47
- yield* a.send(Pong.make({ who: m.who, id: m.id, t0: m.t0 }));
48
- }
49
- }
50
- })), Stream.runDrain, Effect.forkScoped);
51
- // Schedule reload marker, then leader ping (tight timeout) and client ping (looser timeout)
52
- yield* Effect.sleep(RELOAD_AT_MS);
53
- dropLeaderNext = true;
54
- const leaderRes = yield* sendPing(b, 'leader', LEADER_TIMEOUT_MS);
55
- const clientRes = yield* sendPing(b, 'clientSession', CLIENT_TIMEOUT_MS);
56
- // Desired behavior: leader should not timeout across reload handover
57
- // Current behavior: times out once → This assertion will FAIL, documenting the issue.
58
- expect(leaderRes).toBe('ok');
59
- // Client should remain healthy
60
- expect(clientRes).toBe('ok');
61
- }).pipe(Vitest.withTestCtx(test)));
62
- //# sourceMappingURL=reload-reconnect.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-reconnect.test.js","sourceRoot":"","sources":["../src/reload-reconnect.test.ts"],"names":[],"mappings":"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"}