@livestore/webmesh 0.4.0-dev.14 → 0.4.0-dev.16

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/webmesh",
3
- "version": "0.4.0-dev.14",
3
+ "version": "0.4.0-dev.16",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -8,11 +8,11 @@
8
8
  "./websocket-server": "./dist/websocket-server.js"
9
9
  },
10
10
  "dependencies": {
11
- "@livestore/utils": "0.4.0-dev.14"
11
+ "@livestore/utils": "0.4.0-dev.16"
12
12
  },
13
13
  "devDependencies": {
14
14
  "vitest": "3.2.4",
15
- "@livestore/utils-dev": "0.4.0-dev.14"
15
+ "@livestore/utils-dev": "0.4.0-dev.16"
16
16
  },
17
17
  "files": [
18
18
  "package.json",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=reload-repro.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-repro.d.ts","sourceRoot":"","sources":["../../src/examples/reload-repro.ts"],"names":[],"mappings":""}
@@ -1,136 +0,0 @@
1
- import { MessageChannel } from 'node:worker_threads';
2
- import { Duration, Effect, Schema, Stream, Fiber } from '@livestore/utils/effect';
3
- import { WebChannel } from '@livestore/utils/effect';
4
- import { PlatformNode } from '@livestore/utils/node';
5
- // Minimal reload/reconnect repro on a single MessagePort.
6
- // Two logical roles: 'leader' and 'clientSession' ping loops.
7
- // Simulates a reload event by stopping old loops and starting new ones while heavy/blocked work occurs.
8
- // Goal: demonstrate a single leader timeout around reload while clientSession pings keep succeeding.
9
- const env = (k, d) => (process.env[k] ?? d).trim();
10
- const PING_INTERVAL_MS = Number(env('PING_INTERVAL_MS', '200'));
11
- const LEADER_TIMEOUT_MS = Number(env('LEADER_TIMEOUT_MS', '120'));
12
- const CLIENT_TIMEOUT_MS = Number(env('CLIENT_TIMEOUT_MS', '500'));
13
- const RELOAD_AT_MS = Number(env('RELOAD_AT_MS', '1500'));
14
- const BLOCK_MS = Number(env('BLOCK_MS', '300'));
15
- const HEAVY_SIZE = Number(env('HEAVY_SIZE', '100000'));
16
- const HEAVY_BURST = Number(env('HEAVY_BURST', '20')); // number of heavy messages near reload
17
- const DROP_WINDOW_MS = Number(env('DROP_WINDOW_MS', '120')); // drop leader pongs in this window after reload
18
- const Ping = Schema.TaggedStruct('Ping', { who: Schema.String, id: Schema.String, t0: Schema.Number });
19
- const Pong = Schema.TaggedStruct('Pong', { who: Schema.String, id: Schema.String, t0: Schema.Number });
20
- const Heavy = Schema.TaggedStruct('Heavy', { n: Schema.Number, payload: Schema.String });
21
- const Msg = Schema.Union(Ping, Pong, Heavy);
22
- const pad = (n, ch = 'x') => (n <= 0 ? '' : ch.repeat(n));
23
- const main = Effect.gen(function* () {
24
- const payload = pad(HEAVY_SIZE);
25
- console.log('[reload-repro] cfg', {
26
- PING_INTERVAL_MS,
27
- LEADER_TIMEOUT_MS,
28
- CLIENT_TIMEOUT_MS,
29
- RELOAD_AT_MS,
30
- BLOCK_MS,
31
- HEAVY_SIZE,
32
- HEAVY_BURST,
33
- });
34
- const mc = new MessageChannel();
35
- const a = yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Msg });
36
- const b = yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Msg });
37
- // A: responder + heavy sender near reload
38
- let heavySent = 0;
39
- const t0 = Date.now();
40
- let dropLeaderNext = false;
41
- yield* a.listen
42
- .pipe(Stream.flatten(), Stream.tap((m) => Effect.gen(function* () {
43
- if (Schema.is(Ping)(m)) {
44
- console.log('[responder] recv', m.who, Date.now());
45
- const now = Date.now();
46
- if (m.who === 'leader' && dropLeaderNext) {
47
- console.log('[responder] drop pong for leader in drop window');
48
- dropLeaderNext = false;
49
- }
50
- else {
51
- yield* a.send(Pong.make({ who: m.who, id: m.id, t0: m.t0 }));
52
- }
53
- }
54
- })), Stream.runDrain, Effect.forkScoped);
55
- // Schedule a heavy burst around reload
56
- yield* Effect.sleep(Duration.millis(RELOAD_AT_MS - 50));
57
- yield* Effect.gen(function* () {
58
- for (let i = 0; i < HEAVY_BURST; i++) {
59
- yield* a.send(Heavy.make({ n: i, payload }));
60
- }
61
- });
62
- // B: receive heavy; simulate blocking around reload window
63
- yield* b.listen
64
- .pipe(Stream.flatten(), Stream.tap((m) => Effect.sync(() => {
65
- if (Schema.is(Heavy)(m))
66
- heavySent += 1;
67
- const now = Date.now();
68
- // Busy block during a window around reload to induce a timeout
69
- if (Math.abs(now - (t0 + RELOAD_AT_MS)) < 150 && BLOCK_MS > 0) {
70
- const until = now + BLOCK_MS;
71
- while (Date.now() < until) { }
72
- }
73
- })), Stream.runDrain, Effect.forkScoped);
74
- // Explicit main-thread block on B exactly at reload to induce timeout (scheduled in parallel)
75
- yield* Effect.gen(function* () {
76
- yield* Effect.sleep(Duration.millis(RELOAD_AT_MS));
77
- if (BLOCK_MS > 0) {
78
- const until = Date.now() + BLOCK_MS;
79
- while (Date.now() < until) { }
80
- }
81
- }).pipe(Effect.forkScoped);
82
- let okLeader = 0;
83
- let timeoutLeader = 0;
84
- let okClient = 0;
85
- let timeoutClient = 0;
86
- // t0 set above
87
- const sendPing = (who, timeoutMs, blockBeforeWaitMs = 0) => Effect.gen(function* () {
88
- const id = Math.random().toString(36).slice(2);
89
- const start = Date.now();
90
- const wait = b.listen
91
- .pipe(Stream.flatten(), Stream.filter(Schema.is(Pong)), Stream.filter((m) => m.id === id), Stream.runHead)
92
- .pipe(Effect.asVoid);
93
- yield* b.send(Ping.make({ who, id, t0: start }));
94
- // Simulate main-thread work immediately after sending, before waiting for pong
95
- if (blockBeforeWaitMs > 0) {
96
- const until = Date.now() + blockBeforeWaitMs;
97
- while (Date.now() < until) { }
98
- }
99
- const res = yield* wait
100
- .pipe(Effect.timeout(Duration.millis(timeoutMs)), Effect.as('ok'), Effect.catchTag('TimeoutException', () => Effect.succeed('timeout')));
101
- if (res === 'ok') {
102
- if (who === 'leader')
103
- okLeader += 1;
104
- else
105
- okClient += 1;
106
- console.log('[ping]', who, 'ok', Date.now() - start);
107
- }
108
- else {
109
- if (who === 'leader')
110
- timeoutLeader += 1;
111
- else
112
- timeoutClient += 1;
113
- console.log('[ping]', who, 'timeout');
114
- }
115
- });
116
- // Deterministic timeline:
117
- // t0 + RELOAD_AT_MS + 10ms: send leader ping (expect timeout due to responder dropping leader pongs in window)
118
- // t0 + RELOAD_AT_MS: optional block on receiver (B) for BLOCK_MS (to mimic heavy)
119
- // t0 + RELOAD_AT_MS + DROP_WINDOW_MS + 30ms: send clientSession ping (expect ok)
120
- console.log('[reload]', 'start', Date.now());
121
- yield* Effect.sleep(Duration.millis(RELOAD_AT_MS));
122
- dropLeaderNext = true;
123
- yield* Effect.sleep(Duration.millis(10));
124
- console.log('[ping-loop] leader start', Date.now());
125
- yield* sendPing('leader', LEADER_TIMEOUT_MS, 0);
126
- console.log('[reload]', 'block done', Date.now());
127
- // Client ping after drop window
128
- yield* Effect.sleep(Duration.millis(DROP_WINDOW_MS + 30));
129
- console.log('[ping-loop] clientSession start', Date.now());
130
- yield* sendPing('clientSession', CLIENT_TIMEOUT_MS);
131
- console.log('[ping-loop] clientSession stop', Date.now());
132
- console.log('[ping-loop] leader stop', Date.now());
133
- console.log('[summary]', JSON.stringify({ okLeader, timeoutLeader, okClient, timeoutClient, heavySent }));
134
- });
135
- PlatformNode.NodeRuntime.runMain(main.pipe(Effect.scoped));
136
- //# sourceMappingURL=reload-repro.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-repro.js","sourceRoot":"","sources":["../../src/examples/reload-repro.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=starvation-repro-single-port.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"starvation-repro-single-port.d.ts","sourceRoot":"","sources":["../../src/examples/starvation-repro-single-port.ts"],"names":[],"mappings":""}
@@ -1,89 +0,0 @@
1
- import { MessageChannel } from 'node:worker_threads';
2
- import { Effect, Schema, Stream, Duration } from '@livestore/utils/effect';
3
- import { WebChannel } from '@livestore/utils/effect';
4
- import { PlatformNode } from '@livestore/utils/node';
5
- // Standalone single-port repro (no Mesh): a single MessagePort carries both
6
- // ping/pong and heavy payloads. Receiver blocks on heavy, causing ping timeouts.
7
- // Co-located with WebMesh package for convenience.
8
- const env = (k, d) => (process.env[k] ?? d).trim();
9
- const HEAVY = env('HEAVY', '1') === '1';
10
- const HEAVY_SIZE = Number(env('HEAVY_SIZE', '200000'));
11
- const HEAVY_FREQ_MS = Number(env('HEAVY_FREQ_MS', '1'));
12
- const BLOCK_MS = Number(env('BLOCK_MS', '10'));
13
- const PING_INTERVAL_MS = Number(env('PING_INTERVAL_MS', '200'));
14
- const TIMEOUT_MS = Number(env('TIMEOUT_MS', '400'));
15
- const DURATION_MS = Number(env('DURATION_MS', '5000'));
16
- const WITH_ACK = env('WITH_ACK', '0') === '1';
17
- const Ping = Schema.TaggedStruct('Ping', { id: Schema.String, t0: Schema.Number });
18
- const Pong = Schema.TaggedStruct('Pong', { id: Schema.String, t0: Schema.Number });
19
- const Heavy = Schema.TaggedStruct('Heavy', { n: Schema.Number, payload: Schema.String });
20
- const Msg = Schema.Union(Ping, Pong, Heavy);
21
- const pad = (n, ch = 'x') => (n <= 0 ? '' : ch.repeat(n));
22
- const main = Effect.gen(function* () {
23
- const payload = pad(HEAVY_SIZE);
24
- console.log('[single-port] config', {
25
- HEAVY,
26
- HEAVY_SIZE: payload.length,
27
- HEAVY_FREQ_MS,
28
- BLOCK_MS,
29
- PING_INTERVAL_MS,
30
- TIMEOUT_MS,
31
- DURATION_MS,
32
- WITH_ACK,
33
- });
34
- const mc = new MessageChannel();
35
- const a = WITH_ACK
36
- ? yield* WebChannel.messagePortChannelWithAck({ port: mc.port1, schema: Msg })
37
- : yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Msg });
38
- const b = WITH_ACK
39
- ? yield* WebChannel.messagePortChannelWithAck({ port: mc.port2, schema: Msg })
40
- : yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Msg });
41
- // A: heavy producer + ping responder
42
- if (HEAVY) {
43
- yield* Effect.gen(function* () {
44
- let n = 0;
45
- while (true) {
46
- yield* a.send(Heavy.make({ n, payload }));
47
- n += 1;
48
- if (HEAVY_FREQ_MS > 0)
49
- yield* Effect.sleep(Duration.millis(HEAVY_FREQ_MS));
50
- }
51
- }).pipe(Effect.forkScoped);
52
- }
53
- yield* a.listen
54
- .pipe(Stream.flatten(), Stream.filter(Schema.is(Ping)), Stream.tap((m) => a.send(Pong.make({ id: m.id, t0: m.t0 }))), Stream.runDrain, Effect.forkScoped);
55
- // B: receiver blocks on Heavy; also pings A periodically
56
- yield* b.listen
57
- .pipe(Stream.flatten(), Stream.tap((m) => Effect.sync(() => {
58
- if (Schema.is(Heavy)(m) && BLOCK_MS > 0) {
59
- const until = Date.now() + BLOCK_MS;
60
- while (Date.now() < until) { }
61
- }
62
- })), Stream.runDrain, Effect.forkScoped);
63
- let ok = 0;
64
- let timeouts = 0;
65
- const deadline = Date.now() + DURATION_MS;
66
- while (Date.now() < deadline) {
67
- const id = Math.random().toString(36).slice(2);
68
- const t0 = Date.now();
69
- const waitForPong = b.listen
70
- .pipe(Stream.flatten(), Stream.filter(Schema.is(Pong)), Stream.filter((m) => m.id === id), Stream.runHead)
71
- .pipe(Effect.asVoid);
72
- yield* b.send(Ping.make({ id, t0 }));
73
- console.log('[single-port] ping sent', id);
74
- const res = yield* waitForPong
75
- .pipe(Effect.timeout(Duration.millis(TIMEOUT_MS)), Effect.as('ok'), Effect.catchTag('TimeoutException', () => Effect.succeed('timeout')));
76
- if (res === 'ok') {
77
- ok += 1;
78
- console.log('[single-port] ping ok', Date.now() - t0);
79
- }
80
- else {
81
- timeouts += 1;
82
- console.log('[single-port] ping timeout');
83
- }
84
- yield* Effect.sleep(Duration.millis(PING_INTERVAL_MS));
85
- }
86
- console.log('[single-port] summary', JSON.stringify({ ok, timeouts }));
87
- });
88
- PlatformNode.NodeRuntime.runMain(main.pipe(Effect.scoped));
89
- //# sourceMappingURL=starvation-repro-single-port.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"starvation-repro-single-port.js","sourceRoot":"","sources":["../../src/examples/starvation-repro-single-port.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=starvation-repro.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"starvation-repro.d.ts","sourceRoot":"","sources":["../../src/examples/starvation-repro.ts"],"names":[],"mappings":""}
@@ -1,171 +0,0 @@
1
- import { MessageChannel } from 'node:worker_threads';
2
- import { Effect, Schema, Stream, Duration } from '@livestore/utils/effect';
3
- import { WebChannel } from '@livestore/utils/effect';
4
- import * as Webmesh from '@livestore/webmesh';
5
- import { PlatformNode } from '@livestore/utils/node';
6
- // Minimal, self-contained WebMesh repro for single-port starvation under heavy traffic.
7
- //
8
- // Scenario:
9
- // - Two MeshNodes (A and B) connected by one MessagePort edge.
10
- // - Two logical channels multiplexed over that edge:
11
- // - "leader" (ping/pong) to simulate control traffic.
12
- // - "heavy" to simulate frequent, large messages that occupy the receiver's main thread.
13
- // - Under heavy load (and/or simulated blocking), ping timeouts occur although the transport is healthy.
14
- //
15
- // Run (fish):
16
- // bun submodules/livestore/packages/@livestore/webmesh/src/examples/starvation-repro.ts
17
- //
18
- // Tunables via env:
19
- // HEAVY=1|0 enable heavy traffic (default 1)
20
- // HEAVY_SIZE=500000 payload size in bytes per message (default 200000)
21
- // HEAVY_FREQ_MS=10 interval between heavy messages (default 10)
22
- // BLOCK_MS=0 busy-loop on B after each heavy message (default 0)
23
- // PING_INTERVAL_MS=500 ping interval (default 500)
24
- // TIMEOUT_MS=1500 ping timeout (default 1500)
25
- // DURATION_MS=30000 run duration (default 30000)
26
- //
27
- // Optional: WITH_ACK=1 to use messagePortChannelWithAck for the edge (diagnostic only)
28
- const env = (k, d) => (process.env[k] ?? d).trim();
29
- const HEAVY = env('HEAVY', '1') === '1';
30
- const HEAVY_SIZE = Number(env('HEAVY_SIZE', '200000'));
31
- const HEAVY_FREQ_MS = Number(env('HEAVY_FREQ_MS', '10'));
32
- const BLOCK_MS = Number(env('BLOCK_MS', '0'));
33
- const PING_INTERVAL_MS = Number(env('PING_INTERVAL_MS', '500'));
34
- const TIMEOUT_MS = Number(env('TIMEOUT_MS', '1500'));
35
- const DURATION_MS = Number(env('DURATION_MS', '30000'));
36
- const WITH_ACK = env('WITH_ACK', '0') === '1';
37
- const LeaderPing = Schema.TaggedStruct('LeaderPing', {
38
- id: Schema.String,
39
- t0: Schema.Number,
40
- });
41
- const LeaderPong = Schema.TaggedStruct('LeaderPong', {
42
- id: Schema.String,
43
- t0: Schema.Number,
44
- });
45
- const LeaderMsg = Schema.Union(LeaderPing, LeaderPong);
46
- const HeavyMsg = Schema.Struct({
47
- n: Schema.Number, // sequence number
48
- payload: Schema.String, // large string payload
49
- });
50
- const pad = (n, ch = 'x') => (n <= 0 ? '' : ch.repeat(n));
51
- const main = Effect.gen(function* () {
52
- const payload = pad(HEAVY_SIZE);
53
- console.log('[repro] config', {
54
- HEAVY,
55
- HEAVY_SIZE: payload.length,
56
- HEAVY_FREQ_MS,
57
- BLOCK_MS,
58
- PING_INTERVAL_MS,
59
- TIMEOUT_MS,
60
- DURATION_MS,
61
- WITH_ACK,
62
- });
63
- // Create two MeshNodes and connect them via a single MessagePort edge
64
- const nodeA = yield* Webmesh.makeMeshNode('A');
65
- const nodeB = yield* Webmesh.makeMeshNode('B');
66
- const mc = new MessageChannel();
67
- const edgeA = WITH_ACK
68
- ? yield* WebChannel.messagePortChannelWithAck({ port: mc.port1, schema: Webmesh.WebmeshSchema.Packet })
69
- : yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Webmesh.WebmeshSchema.Packet });
70
- const edgeB = WITH_ACK
71
- ? yield* WebChannel.messagePortChannelWithAck({ port: mc.port2, schema: Webmesh.WebmeshSchema.Packet })
72
- : yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Webmesh.WebmeshSchema.Packet });
73
- yield* nodeA.addEdge({ target: 'B', edgeChannel: edgeA, replaceIfExists: true });
74
- yield* nodeB.addEdge({ target: 'A', edgeChannel: edgeB, replaceIfExists: true });
75
- console.log('[repro] edges ready');
76
- // Application channels multiplexed over the same edge
77
- const [leaderA, leaderB] = yield* Effect.all([
78
- nodeA.makeChannel({
79
- target: 'B',
80
- channelName: 'leader',
81
- schema: { listen: LeaderMsg, send: LeaderMsg },
82
- mode: 'direct',
83
- closeExisting: true,
84
- }),
85
- nodeB.makeChannel({
86
- target: 'A',
87
- channelName: 'leader',
88
- schema: { listen: LeaderMsg, send: LeaderMsg },
89
- mode: 'direct',
90
- closeExisting: true,
91
- }),
92
- ], { concurrency: 'unbounded' });
93
- const [heavyA, heavyB] = yield* Effect.all([
94
- nodeA.makeChannel({
95
- target: 'B',
96
- channelName: 'heavy',
97
- schema: HeavyMsg,
98
- mode: 'direct',
99
- closeExisting: true,
100
- }),
101
- nodeB.makeChannel({
102
- target: 'A',
103
- channelName: 'heavy',
104
- schema: HeavyMsg,
105
- mode: 'direct',
106
- closeExisting: true,
107
- }),
108
- ], { concurrency: 'unbounded' });
109
- console.log('[repro] channels ready');
110
- // A: answer pings
111
- yield* leaderA.listen
112
- .pipe(Stream.flatten(), Stream.filter(Schema.is(LeaderPing)), Stream.tap((msg) => leaderA.send(LeaderPong.make({ id: msg.id, t0: msg.t0 }))), Stream.runDrain, Effect.forkScoped);
113
- // B: issue periodic pings, track timeouts
114
- let ok = 0;
115
- let timeouts = 0;
116
- // B: process heavy messages (simulate UI main-thread work)
117
- if (HEAVY) {
118
- yield* heavyB.listen
119
- .pipe(Stream.flatten(), Stream.tap(() => Effect.sync(() => {
120
- if (BLOCK_MS > 0) {
121
- const until = Date.now() + BLOCK_MS;
122
- while (Date.now() < until) {
123
- // busy wait
124
- }
125
- }
126
- })), Stream.runDrain, Effect.forkScoped);
127
- }
128
- // A: produce heavy messages
129
- if (HEAVY) {
130
- yield* Effect.gen(function* () {
131
- let n = 0;
132
- while (true) {
133
- yield* heavyA.send({ n, payload });
134
- n += 1;
135
- yield* Effect.sleep(Duration.millis(HEAVY_FREQ_MS));
136
- }
137
- }).pipe(Effect.forkScoped);
138
- }
139
- // Run ping loop for a fixed duration
140
- const deadline = Date.now() + DURATION_MS;
141
- while (Date.now() < deadline) {
142
- const id = Math.random().toString(36).slice(2);
143
- const t0 = Date.now();
144
- const waitForPong = leaderB.listen
145
- .pipe(Stream.flatten(), Stream.filter(Schema.is(LeaderPong)), Stream.filter((m) => m.id === id), Stream.runHead)
146
- .pipe(Effect.asVoid);
147
- yield* leaderB.send(LeaderPing.make({ id, t0 }));
148
- console.log('[ping] sent', id);
149
- const res = yield* waitForPong
150
- .pipe(Effect.timeout(Duration.millis(TIMEOUT_MS)), Effect.as('ok'), Effect.catchTag('TimeoutException', () => Effect.succeed('timeout')));
151
- if (res === 'ok') {
152
- ok += 1;
153
- console.log('[ping] ok', Date.now() - t0);
154
- }
155
- else {
156
- timeouts += 1;
157
- console.log('[ping] timeout');
158
- }
159
- yield* Effect.sleep(Duration.millis(PING_INTERVAL_MS));
160
- }
161
- console.log('[summary]', JSON.stringify({ ok, timeouts }));
162
- if (timeouts > 0) {
163
- console.log('[summary] ping timeouts observed under heavy traffic');
164
- }
165
- else {
166
- console.log('[summary] no timeouts observed');
167
- }
168
- // Done
169
- });
170
- PlatformNode.NodeRuntime.runMain(main.pipe(Effect.scoped));
171
- //# sourceMappingURL=starvation-repro.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"starvation-repro.js","sourceRoot":"","sources":["../../src/examples/starvation-repro.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=reload-handover.mesh.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload-handover.mesh.test.d.ts","sourceRoot":"","sources":["../src/reload-handover.mesh.test.ts"],"names":[],"mappings":""}
@@ -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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"}