@livestore/webmesh 0.0.0-snapshot-12c4570d047bcfaefc85bc6243c1b61f57580913 → 0.0.0-snapshot-b12fe44662a4a2f917d402ea2562edb3c404f26a

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.
@@ -24,12 +24,13 @@ export const makeWebSocketConnection = (socket, socketType) => Effect.scopeWithC
24
24
  socket.binaryType = 'arraybuffer';
25
25
  const fromDeferred = yield* Deferred.make();
26
26
  const listenQueue = yield* Queue.unbounded().pipe(Effect.acquireRelease(Queue.shutdown));
27
+ const schema = WebChannel.mapSchema(WebmeshSchema.Packet);
27
28
  yield* Stream.fromEventListener(socket, 'message').pipe(Stream.map((msg) => Schema.decodeUnknownEither(MessageMsgPack)(new Uint8Array(msg.data))), Stream.flatten(), Stream.tap((msg) => Effect.gen(function* () {
28
29
  if (msg._tag === 'WSConnectionInit') {
29
30
  yield* Deferred.succeed(fromDeferred, msg.from);
30
31
  }
31
32
  else {
32
- const decodedPayload = yield* Schema.decode(WebmeshSchema.Packet)(msg.payload);
33
+ const decodedPayload = yield* Schema.decode(schema.listen)(msg.payload);
33
34
  yield* Queue.offer(listenQueue, decodedPayload);
34
35
  }
35
36
  })), Stream.runDrain, Effect.interruptible, Effect.tapCauseLogPretty, Effect.forkScoped);
@@ -50,16 +51,16 @@ export const makeWebSocketConnection = (socket, socketType) => Effect.scopeWithC
50
51
  }), { once: true });
51
52
  const send = (message) => Effect.gen(function* () {
52
53
  yield* isConnectedLatch.await;
53
- const payload = yield* Schema.encode(WebmeshSchema.Packet)(message);
54
+ const payload = yield* Schema.encode(schema.send)(message);
54
55
  socket.send(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSConnectionPayload', payload, from }));
55
56
  });
56
- const listen = Stream.fromQueue(listenQueue).pipe(Stream.map(Either.right));
57
+ const listen = Stream.fromQueue(listenQueue).pipe(Stream.map(Either.right), WebChannel.listenToDebugPing('websocket-connection'));
57
58
  const webChannel = {
58
59
  [WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
59
60
  send,
60
61
  listen,
61
62
  closedDeferred,
62
- schema: { listen: WebmeshSchema.Packet, send: WebmeshSchema.Packet },
63
+ schema,
63
64
  supportsTransferables: false,
64
65
  shutdown: Scope.close(scope, Exit.void),
65
66
  };
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-connection.js","sourceRoot":"","sources":["../src/websocket-connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket-connection.js","sourceRoot":"","sources":["../src/websocket-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,MAAM,EACN,UAAU,EACV,SAAS,GACV,MAAM,yBAAyB,CAAA;AAGhC,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAA;AAGjD,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,YAAY,CAAC,kBAAkB,EAAE;IAC5E,IAAI,EAAE,MAAM,CAAC,MAAM;CACpB,CAAC;CAAG;AAEL,MAAM,OAAO,mBAAoB,SAAQ,MAAM,CAAC,YAAY,CAAC,qBAAqB,EAAE;IAClF,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,GAAG;CACpB,CAAC;CAAG;AAEL,MAAM,OAAO,mBAAoB,SAAQ,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;CAAG;AAE/F,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAWjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,IAAI,EACJ,GAAG,EACH,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAKtC,EAA2C,EAAE,CAC5C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAA;IAEjD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAA;IAEjE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAEpF,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,uBAAuB,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEhG,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5G,KAAK,CAAC,CAAC,YAAY,CAAA;AACrB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAEzF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,MAAsD,EACtD,UAAsB,EAQtB,EAAE,CACF,MAAM,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE,CAClC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,UAAU,GAAG,aAAa,CAAA;IAEjC,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAU,CAAA;IAEnD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,EAAoC,CAAC,IAAI,CACjF,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CACtC,CAAA;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAEzD,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAe,MAAa,EAAE,SAAS,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EACzF,MAAM,CAAC,OAAO,EAAE,EAChB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACpC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACvE,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;QACjD,CAAC;IACH,CAAC,CAAC,CACH,EACD,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,aAAa,EACpB,MAAM,CAAC,iBAAiB,EACxB,MAAM,CAAC,UAAU,CAClB,CAAA;IAED,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,EAAE,CACrC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAEpF,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC/B,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAA;IAE1E,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAChC,aAAa,CAAC,IAAI,CAAC,CAAA;IACrB,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAEtD,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEzG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CACzB,MAAM,EACN,OAAO,EACP,GAAG,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,KAAK,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAA;QAC7B,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,CAAC,CAAA;IACpD,CAAC,CAAC,EACJ,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,OAAyC,EAAE,EAAE,CACzD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,KAAK,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAA;QAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAA;QAC1D,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAChG,CAAC,CAAC,CAAA;IAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,CAC/C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EACxB,UAAU,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,CACrD,CAAA;IAED,MAAM,UAAU,GAAG;QACjB,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,gBAAgB;QAC1D,IAAI;QACJ,MAAM;QACN,cAAc;QACd,MAAM;QACN,qBAAqB,EAAE,KAAK;QAC5B,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;KAC4D,CAAA;IAErG,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AAC7B,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC,CAC1D,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/webmesh",
3
- "version": "0.0.0-snapshot-12c4570d047bcfaefc85bc6243c1b61f57580913",
3
+ "version": "0.0.0-snapshot-b12fe44662a4a2f917d402ea2562edb3c404f26a",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -16,8 +16,8 @@
16
16
  "types": "./dist/mod.d.ts",
17
17
  "dependencies": {
18
18
  "ws": "8.18.0",
19
- "@livestore/common": "0.0.0-snapshot-12c4570d047bcfaefc85bc6243c1b61f57580913",
20
- "@livestore/utils": "0.0.0-snapshot-12c4570d047bcfaefc85bc6243c1b61f57580913"
19
+ "@livestore/common": "0.0.0-snapshot-b12fe44662a4a2f917d402ea2562edb3c404f26a",
20
+ "@livestore/utils": "0.0.0-snapshot-b12fe44662a4a2f917d402ea2562edb3c404f26a"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/ws": "^8.18.0",
@@ -219,7 +219,7 @@ export const makeMessageChannelInternal = ({
219
219
  source: nodeName,
220
220
  channelName: packet.channelName,
221
221
  hops: [],
222
- remainingHops: packet.hops,
222
+ remainingHops: packet.hops.slice(0, -1),
223
223
  port: mc.port2,
224
224
  channelVersion,
225
225
  }),
@@ -123,7 +123,7 @@ export const makeProxyChannel = ({
123
123
  // yield* Effect.log(`${nodeName}:processing packet ${packet._tag} from ${packet.source}`)
124
124
 
125
125
  const otherSideName = packet.source
126
- const channelKey = `${otherSideName}-${packet.channelName}` satisfies ChannelKey
126
+ const channelKey = `target:${otherSideName}, channelName:${packet.channelName}` satisfies ChannelKey
127
127
  const channelState = channelStateRef.current
128
128
 
129
129
  switch (packet._tag) {
@@ -166,7 +166,7 @@ export const makeProxyChannel = ({
166
166
  channelState.combinedChannelId !== packet.combinedChannelId
167
167
  ) {
168
168
  return shouldNeverHappen(
169
- `Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
169
+ `ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
170
170
  )
171
171
  } else {
172
172
  // for now just ignore it but should be looked into (there seems to be some kind of race condition/inefficiency)
@@ -176,7 +176,7 @@ export const makeProxyChannel = ({
176
176
  const combinedChannelId = getCombinedChannelId(packet.channelIdCandidate)
177
177
  if (combinedChannelId !== packet.combinedChannelId) {
178
178
  return yield* Effect.die(
179
- `Expected proxy channel to have the same combinedChannelId as the packet:\n${combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
179
+ `ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
180
180
  )
181
181
  }
182
182
 
@@ -193,7 +193,7 @@ export const makeProxyChannel = ({
193
193
 
194
194
  if (channelState.combinedChannelId !== packet.combinedChannelId) {
195
195
  return yield* Effect.die(
196
- `Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
196
+ `ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`,
197
197
  )
198
198
  }
199
199
 
@@ -222,7 +222,7 @@ export const makeProxyChannel = ({
222
222
 
223
223
  const ack =
224
224
  channelState.ackMap.get(packet.reqId) ??
225
- shouldNeverHappen(`Expected ack for ${packet.reqId} in proxy channel ${channelKey}`)
225
+ shouldNeverHappen(`[ProxyChannel[${channelKey}]] Expected ack for ${packet.reqId}`)
226
226
 
227
227
  yield* Deferred.succeed(ack, void 0)
228
228
 
@@ -305,6 +305,8 @@ export const makeProxyChannel = ({
305
305
  target,
306
306
  combinedChannelId,
307
307
  })
308
+ // TODO consider handling previous ackMap entries which might leak/fill-up memory
309
+ // as only successful acks are removed from the map
308
310
  ackMap.set(packet.id, ack)
309
311
 
310
312
  yield* sendPacket(packet)
@@ -315,7 +317,9 @@ export const makeProxyChannel = ({
315
317
  debugInfo.pendingSends--
316
318
  })
317
319
 
318
- yield* innerSend.pipe(Effect.timeout(100), Effect.retry(Schedule.exponential(100)), Effect.orDie)
320
+ // TODO make this configurable
321
+ // Schedule.exponential(10): 10, 20, 40, 80, 160, 320, ...
322
+ yield* innerSend.pipe(Effect.timeout(100), Effect.retry(Schedule.exponential(10)), Effect.orDie)
319
323
  }).pipe(Effect.tapErrorCause(Effect.logError))
320
324
 
321
325
  const rerunOnNewChannelFiber = yield* connectedStateRef.changes.pipe(
package/src/common.ts CHANGED
@@ -15,7 +15,7 @@ export type MessageQueueItem = {
15
15
  export type MeshNodeName = string
16
16
 
17
17
  export type ChannelName = string
18
- export type ChannelKey = `${MeshNodeName}-${ChannelName}`
18
+ export type ChannelKey = `target:${MeshNodeName}, channelName:${ChannelName}`
19
19
 
20
20
  // TODO actually use this to avoid timeouts in certain cases
21
21
  export class NoConnectionRouteSignal extends Schema.TaggedError<NoConnectionRouteSignal>()(
@@ -86,13 +86,44 @@ export class ProxyChannelPayloadAck extends Schema.TaggedStruct('ProxyChannelPay
86
86
  * Broadcast to all nodes when a new connection is added.
87
87
  * Mostly used for auto-reconnect purposes.
88
88
  */
89
- // TODO actually use for this use case
90
89
  export class NetworkConnectionAdded extends Schema.TaggedStruct('NetworkConnectionAdded', {
91
90
  id,
92
91
  source: Schema.String,
93
92
  target: Schema.String,
94
93
  }) {}
95
94
 
95
+ export class NetworkConnectionTopologyRequest extends Schema.TaggedStruct('NetworkConnectionTopologyRequest', {
96
+ id,
97
+ hops: Schema.Array(Schema.String),
98
+ /** Always fixed to who requested the topology */
99
+ source: Schema.String,
100
+ target: Schema.Literal('-'),
101
+ }) {}
102
+
103
+ export class NetworkConnectionTopologyResponse extends Schema.TaggedStruct('NetworkConnectionTopologyResponse', {
104
+ id,
105
+ reqId: Schema.String,
106
+ remainingHops: Schema.Array(Schema.String),
107
+ nodeName: Schema.String,
108
+ connections: Schema.Array(Schema.String),
109
+ /** Always fixed to who requested the topology */
110
+ source: Schema.String,
111
+ target: Schema.Literal('-'),
112
+ }) {}
113
+
114
+ export const BroadcastChannelPacket = Schema.TaggedStruct('BroadcastChannelPacket', {
115
+ id,
116
+ channelName: Schema.String,
117
+ /**
118
+ * The payload is expected to be encoded/decoded by the send/listen schema.
119
+ * Transferables are not supported.
120
+ */
121
+ payload: Schema.Any,
122
+ hops: Schema.Array(Schema.String),
123
+ source: Schema.String,
124
+ target: Schema.Literal('-'),
125
+ })
126
+
96
127
  export class MessageChannelPacket extends Schema.Union(
97
128
  MessageChannelRequest,
98
129
  MessageChannelResponseSuccess,
@@ -106,7 +137,14 @@ export class ProxyChannelPacket extends Schema.Union(
106
137
  ProxyChannelPayloadAck,
107
138
  ) {}
108
139
 
109
- export class Packet extends Schema.Union(MessageChannelPacket, ProxyChannelPacket, NetworkConnectionAdded) {}
140
+ export class Packet extends Schema.Union(
141
+ MessageChannelPacket,
142
+ ProxyChannelPacket,
143
+ NetworkConnectionAdded,
144
+ NetworkConnectionTopologyRequest,
145
+ NetworkConnectionTopologyResponse,
146
+ BroadcastChannelPacket,
147
+ ) {}
110
148
 
111
149
  export class MessageChannelPing extends Schema.TaggedStruct('MessageChannelPing', {}) {}
112
150
  export class MessageChannelPong extends Schema.TaggedStruct('MessageChannelPong', {}) {}
package/src/node.test.ts CHANGED
@@ -204,6 +204,8 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
204
204
  channelType,
205
205
  delays: { x: delayX, y: delayY, connect: connectDelay },
206
206
  })
207
+
208
+ yield* Effect.promise(() => nodeX.debug.requestTopology(100))
207
209
  }).pipe(
208
210
  withCtx(test, {
209
211
  skipOtel: true,
@@ -759,6 +761,50 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
759
761
  )
760
762
  })
761
763
 
764
+ /**
765
+ * A E
766
+ * \ /
767
+ * C---D
768
+ * / \
769
+ * B F
770
+ *
771
+ * Topology: Butterfly topology with two connected hubs (C-D) each serving multiple nodes
772
+ */
773
+ Vitest.describe('butterfly topology', () => {
774
+ Vitest.scopedLive('should work', (test) =>
775
+ Effect.gen(function* () {
776
+ const nodeA = yield* makeMeshNode('A')
777
+ const nodeB = yield* makeMeshNode('B')
778
+ const nodeC = yield* makeMeshNode('C')
779
+ const nodeD = yield* makeMeshNode('D')
780
+ const nodeE = yield* makeMeshNode('E')
781
+ const nodeF = yield* makeMeshNode('F')
782
+
783
+ yield* connectNodesViaMessageChannel(nodeA, nodeC)
784
+ yield* connectNodesViaMessageChannel(nodeB, nodeC)
785
+ yield* connectNodesViaMessageChannel(nodeC, nodeD)
786
+ yield* connectNodesViaMessageChannel(nodeD, nodeE)
787
+ yield* connectNodesViaMessageChannel(nodeD, nodeF)
788
+
789
+ yield* Effect.promise(() => nodeA.debug.requestTopology(100))
790
+
791
+ const nodeACode = Effect.gen(function* () {
792
+ const channelAToE = yield* createChannel(nodeA, 'E')
793
+ yield* channelAToE.send({ message: 'A1' })
794
+ expect(yield* getFirstMessage(channelAToE)).toEqual({ message: 'E1' })
795
+ })
796
+
797
+ const nodeECode = Effect.gen(function* () {
798
+ const channelEToA = yield* createChannel(nodeE, 'A')
799
+ yield* channelEToA.send({ message: 'E1' })
800
+ expect(yield* getFirstMessage(channelEToA)).toEqual({ message: 'A1' })
801
+ })
802
+
803
+ yield* Effect.all([nodeACode, nodeECode], { concurrency: 'unbounded' })
804
+ }).pipe(withCtx(test)),
805
+ )
806
+ })
807
+
762
808
  Vitest.describe('mixture of messagechannel and proxy connections', () => {
763
809
  // TODO test case to better guard against case where side A tries to create a proxy channel to B
764
810
  // and side B tries to create a messagechannel to A
@@ -799,6 +845,41 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
799
845
  }).pipe(withCtx(test)),
800
846
  )
801
847
  })
848
+
849
+ Vitest.describe('broadcast channel', () => {
850
+ Vitest.scopedLive('should work', (test) =>
851
+ Effect.gen(function* () {
852
+ const nodeA = yield* makeMeshNode('A')
853
+ const nodeB = yield* makeMeshNode('B')
854
+ const nodeC = yield* makeMeshNode('C')
855
+
856
+ yield* connectNodesViaMessageChannel(nodeA, nodeB)
857
+ yield* connectNodesViaMessageChannel(nodeB, nodeC)
858
+
859
+ const channelOnA = yield* nodeA.makeBroadcastChannel({ channelName: 'test', schema: Schema.String })
860
+ const channelOnC = yield* nodeC.makeBroadcastChannel({ channelName: 'test', schema: Schema.String })
861
+
862
+ const listenOnAFiber = yield* channelOnA.listen.pipe(
863
+ Stream.flatten(),
864
+ Stream.runHead,
865
+ Effect.flatten,
866
+ Effect.fork,
867
+ )
868
+ const listenOnCFiber = yield* channelOnC.listen.pipe(
869
+ Stream.flatten(),
870
+ Stream.runHead,
871
+ Effect.flatten,
872
+ Effect.fork,
873
+ )
874
+
875
+ yield* channelOnA.send('A1')
876
+ yield* channelOnC.send('C1')
877
+
878
+ expect(yield* listenOnAFiber).toEqual('C1')
879
+ expect(yield* listenOnCFiber).toEqual('A1')
880
+ }).pipe(withCtx(test)),
881
+ )
882
+ })
802
883
  })
803
884
 
804
885
  const otelLayer = IS_CI ? Layer.empty : OtelLiveHttp({ serviceName: 'webmesh-node-test', skipLogUrl: false })