@livestore/webmesh 0.3.0-dev.2 → 0.3.0-dev.22

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.
Files changed (58) hide show
  1. package/README.md +26 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/channel/message-channel-internal.d.ts +26 -0
  4. package/dist/channel/message-channel-internal.d.ts.map +1 -0
  5. package/dist/channel/message-channel-internal.js +217 -0
  6. package/dist/channel/message-channel-internal.js.map +1 -0
  7. package/dist/channel/message-channel.d.ts +21 -19
  8. package/dist/channel/message-channel.d.ts.map +1 -1
  9. package/dist/channel/message-channel.js +132 -162
  10. package/dist/channel/message-channel.js.map +1 -1
  11. package/dist/channel/proxy-channel.d.ts +3 -3
  12. package/dist/channel/proxy-channel.d.ts.map +1 -1
  13. package/dist/channel/proxy-channel.js +38 -19
  14. package/dist/channel/proxy-channel.js.map +1 -1
  15. package/dist/common.d.ts +36 -14
  16. package/dist/common.d.ts.map +1 -1
  17. package/dist/common.js +7 -4
  18. package/dist/common.js.map +1 -1
  19. package/dist/mesh-schema.d.ts +71 -5
  20. package/dist/mesh-schema.d.ts.map +1 -1
  21. package/dist/mesh-schema.js +55 -6
  22. package/dist/mesh-schema.js.map +1 -1
  23. package/dist/mod.d.ts +2 -2
  24. package/dist/mod.d.ts.map +1 -1
  25. package/dist/mod.js +2 -2
  26. package/dist/mod.js.map +1 -1
  27. package/dist/node.d.ts +43 -21
  28. package/dist/node.d.ts.map +1 -1
  29. package/dist/node.js +271 -95
  30. package/dist/node.js.map +1 -1
  31. package/dist/node.test.d.ts +1 -1
  32. package/dist/node.test.d.ts.map +1 -1
  33. package/dist/node.test.js +391 -156
  34. package/dist/node.test.js.map +1 -1
  35. package/dist/websocket-connection.d.ts +6 -7
  36. package/dist/websocket-connection.d.ts.map +1 -1
  37. package/dist/websocket-connection.js +21 -26
  38. package/dist/websocket-connection.js.map +1 -1
  39. package/dist/websocket-edge.d.ts +50 -0
  40. package/dist/websocket-edge.d.ts.map +1 -0
  41. package/dist/websocket-edge.js +69 -0
  42. package/dist/websocket-edge.js.map +1 -0
  43. package/dist/websocket-server.d.ts.map +1 -1
  44. package/dist/websocket-server.js +23 -9
  45. package/dist/websocket-server.js.map +1 -1
  46. package/package.json +7 -6
  47. package/src/channel/message-channel-internal.ts +356 -0
  48. package/src/channel/message-channel.ts +190 -310
  49. package/src/channel/proxy-channel.ts +259 -231
  50. package/src/common.ts +12 -13
  51. package/src/mesh-schema.ts +62 -6
  52. package/src/mod.ts +2 -2
  53. package/src/node.test.ts +554 -189
  54. package/src/node.ts +417 -134
  55. package/src/websocket-edge.ts +159 -0
  56. package/src/websocket-server.ts +26 -9
  57. package/tmp/pack.tgz +0 -0
  58. package/src/websocket-connection.ts +0 -158
@@ -1,175 +1,140 @@
1
- import { casesHandled, shouldNeverHappen } from '@livestore/utils';
2
- import { Deferred, Effect, Either, Fiber, FiberHandle, Queue, Schedule, Stream, SubscriptionRef, WebChannel, } from '@livestore/utils/effect';
3
- import { packetAsOtelAttributes } from '../common.js';
4
- import * as MeshSchema from '../mesh-schema.js';
5
- export const makeMessageChannel = ({ nodeName, queue, newConnectionAvailablePubSub, target, checkTransferableConnections, channelName, schema, sendPacket, }) => Effect.gen(function* () {
6
- const reconnectTriggerQueue = yield* Queue.unbounded();
7
- const reconnect = Queue.offer(reconnectTriggerQueue, void 0);
8
- const makeInitialState = Effect.gen(function* () {
9
- const deferred = yield* Deferred.make();
10
- return { _tag: 'Initial', deferred };
11
- });
12
- const channelStateRef = { current: yield* makeInitialState };
13
- const makeMessageChannelInternal = Effect.gen(function* () {
14
- const processMessagePacket = ({ packet, respondToSender }) => Effect.gen(function* () {
15
- const channelState = channelStateRef.current;
16
- // yield* Effect.log(`${nodeName}:processing packet ${packet._tag}, channel state: ${channelState._tag}`)
17
- switch (packet._tag) {
18
- // Since there can be concurrent MessageChannel responses from both sides,
19
- // we need to decide which side's port we want to use and which side's port we want to ignore.
20
- // This is only relevant in the case where both sides already sent their responses.
21
- // In this case we're using the target name as a "tie breaker" to decide which side's port to use.
22
- // We do this by sorting the target names lexicographically and use the first one as the winner.
23
- case 'MessageChannelResponseSuccess': {
24
- if (channelState._tag === 'Initial') {
25
- return shouldNeverHappen(`Expected to find message channel request from ${target}, but was in ${channelState._tag} state`);
26
- }
27
- if (channelState._tag === 'Established') {
28
- const deferred = yield* Deferred.make();
29
- channelStateRef.current = { _tag: 'RequestSent', deferred };
30
- yield* reconnect;
31
- return;
1
+ import { Cause, Deferred, Effect, Either, Exit, Option, Queue, Schema, Scope, Stream, TQueue, WebChannel, } from '@livestore/utils/effect';
2
+ import { nanoid } from '@livestore/utils/nanoid';
3
+ import * as WebmeshSchema from '../mesh-schema.js';
4
+ import { makeMessageChannelInternal } from './message-channel-internal.js';
5
+ /**
6
+ * Behaviour:
7
+ * - Waits until there is an initial edge
8
+ * - Automatically reconnects on disconnect
9
+ *
10
+ * Implementation notes:
11
+ * - We've split up the functionality into a wrapper channel and an internal channel.
12
+ * - The wrapper channel is responsible for:
13
+ * - Forwarding send/listen messages to the internal channel (via a queue)
14
+ * - Establishing the initial channel and reconnecting on disconnect
15
+ * - Listening for new edges as a hint to reconnect if not already connected
16
+ * - The wrapper channel maintains a edge counter which is used as the channel version
17
+ *
18
+ * If needed we can also implement further functionality (like heartbeat) in this wrapper channel.
19
+ */
20
+ export const makeMessageChannel = ({ schema, newEdgeAvailablePubSub, channelName, checkTransferableEdges, nodeName, incomingPacketsQueue, target, sendPacket, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
21
+ /** Only used to identify whether a source is the same instance to know when to reconnect */
22
+ const sourceId = nanoid();
23
+ const listenQueue = yield* Queue.unbounded();
24
+ const sendQueue = yield* TQueue.unbounded();
25
+ const initialEdgeDeferred = yield* Deferred.make();
26
+ const debugInfo = {
27
+ pendingSends: 0,
28
+ totalSends: 0,
29
+ connectCounter: 0,
30
+ isConnected: false,
31
+ innerChannelRef: { current: undefined },
32
+ };
33
+ // #region reconnect-loop
34
+ yield* Effect.gen(function* () {
35
+ const resultDeferred = yield* Deferred.make();
36
+ while (true) {
37
+ debugInfo.connectCounter++;
38
+ const channelVersion = debugInfo.connectCounter;
39
+ yield* Effect.spanEvent(`Connecting#${channelVersion}`);
40
+ const makeMessageChannelScope = yield* Scope.make();
41
+ // Attach the new scope to the parent scope
42
+ yield* Effect.addFinalizer((ex) => Scope.close(makeMessageChannelScope, ex));
43
+ /**
44
+ * Expected concurrency behaviour:
45
+ * - We're concurrently running the edge setup and the waitForNewEdgeFiber
46
+ * - Happy path:
47
+ * - The edge setup succeeds and we can interrupt the waitForNewEdgeFiber
48
+ * - Tricky paths:
49
+ * - While a edge is still being setup, we want to re-try when there is a new edge
50
+ * - If the edge setup returns a `MessageChannelResponseNoTransferables` error,
51
+ * we want to wait for a new edge and then re-try
52
+ * - Further notes:
53
+ * - If the parent scope closes, we want to also interrupt both the edge setup and the waitForNewEdgeFiber
54
+ * - We're creating a separate scope for each edge attempt, which
55
+ * - we'll use to fork the message channel in which allows us to interrupt it later
56
+ * - We need to make sure that "interruption" isn't "bubbling out"
57
+ */
58
+ const waitForNewEdgeFiber = yield* Stream.fromPubSub(newEdgeAvailablePubSub).pipe(Stream.tap((edgeName) => Effect.spanEvent(`new-conn:${edgeName}`)), Stream.take(1), Stream.runDrain, Effect.as('new-edge'), Effect.fork);
59
+ const makeChannel = makeMessageChannelInternal({
60
+ nodeName,
61
+ sourceId,
62
+ incomingPacketsQueue,
63
+ target,
64
+ checkTransferableEdges,
65
+ channelName,
66
+ schema,
67
+ channelVersion,
68
+ newEdgeAvailablePubSub,
69
+ sendPacket,
70
+ scope: makeMessageChannelScope,
71
+ }).pipe(Scope.extend(makeMessageChannelScope), Effect.forkIn(makeMessageChannelScope),
72
+ // Given we only call `Effect.exit` later when joining the fiber,
73
+ // we don't want Effect to produce a "unhandled error" log message
74
+ Effect.withUnhandledErrorLogLevel(Option.none()));
75
+ const raceResult = yield* Effect.raceFirst(makeChannel, waitForNewEdgeFiber.pipe(Effect.disconnect));
76
+ if (raceResult === 'new-edge') {
77
+ yield* Scope.close(makeMessageChannelScope, Exit.fail('new-edge'));
78
+ // We'll try again
79
+ }
80
+ else {
81
+ const channelExit = yield* raceResult.pipe(Effect.exit);
82
+ if (channelExit._tag === 'Failure') {
83
+ yield* Scope.close(makeMessageChannelScope, channelExit);
84
+ if (Cause.isFailType(channelExit.cause) &&
85
+ Schema.is(WebmeshSchema.MessageChannelResponseNoTransferables)(channelExit.cause.error)) {
86
+ // Only retry when there is a new edge available
87
+ yield* waitForNewEdgeFiber.pipe(Effect.exit);
32
88
  }
33
- const thisSideAlsoResponded = channelState._tag === 'ResponseSent';
34
- const usePortFromThisSide = thisSideAlsoResponded && nodeName > target;
35
- yield* Effect.annotateCurrentSpan({ usePortFromThisSide });
36
- const winnerPort = usePortFromThisSide ? channelState.locallyCreatedPort : packet.port;
37
- yield* Deferred.succeed(channelState.deferred, winnerPort);
38
- return;
39
89
  }
40
- case 'MessageChannelResponseNoTransferables': {
41
- if (channelState._tag === 'Established')
42
- return;
43
- yield* Deferred.fail(channelState.deferred, packet);
44
- channelStateRef.current = yield* makeInitialState;
45
- return;
46
- }
47
- case 'MessageChannelRequest': {
48
- const mc = new MessageChannel();
49
- const shouldReconnect = channelState._tag === 'Established';
50
- const deferred = channelState._tag === 'Established'
51
- ? yield* Deferred.make()
52
- : channelState.deferred;
53
- channelStateRef.current = { _tag: 'ResponseSent', locallyCreatedPort: mc.port1, deferred };
54
- yield* respondToSender(MeshSchema.MessageChannelResponseSuccess.make({
55
- reqId: packet.id,
56
- target,
57
- source: nodeName,
58
- channelName: packet.channelName,
59
- hops: [],
60
- remainingHops: packet.hops,
61
- port: mc.port2,
62
- }));
63
- // If there's an established channel, we use the new request as a signal
64
- // to drop the old channel and use the new one
65
- if (shouldReconnect) {
66
- yield* reconnect;
67
- }
90
+ else {
91
+ const channel = channelExit.value;
92
+ yield* Deferred.succeed(resultDeferred, { channel, makeMessageChannelScope, channelVersion });
68
93
  break;
69
94
  }
70
- default: {
71
- return casesHandled(packet);
72
- }
73
- }
74
- }).pipe(Effect.withSpan(`handleMessagePacket:${packet._tag}:${packet.source}→${packet.target}`, {
75
- attributes: packetAsOtelAttributes(packet),
76
- }));
77
- yield* Stream.fromQueue(queue).pipe(Stream.tap(processMessagePacket), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkScoped);
78
- const channelFromPort = (port) => Effect.gen(function* () {
79
- channelStateRef.current = { _tag: 'Established' };
80
- // NOTE to support re-connects we need to ack each message
81
- const channel = yield* WebChannel.messagePortChannelWithAck({ port, schema });
82
- return channel;
83
- });
84
- const channelState = channelStateRef.current;
85
- if (channelState._tag === 'Initial' || channelState._tag === 'RequestSent') {
86
- // Important to make a new deferred here as the old one might have been used already
87
- // TODO model this better
88
- const deferred = channelState._tag === 'RequestSent'
89
- ? yield* Deferred.make()
90
- : channelState.deferred;
91
- channelStateRef.current = { _tag: 'RequestSent', deferred };
92
- const connectionRequest = Effect.gen(function* () {
93
- const packet = MeshSchema.MessageChannelRequest.make({ source: nodeName, target, channelName, hops: [] });
94
- const noTransferableResponse = checkTransferableConnections(packet);
95
- if (noTransferableResponse !== undefined) {
96
- yield* Effect.spanEvent(`No transferable connections found for ${packet.source}→${packet.target}`);
97
- yield* Deferred.fail(deferred, noTransferableResponse);
98
- return;
99
- }
100
- yield* sendPacket(packet);
101
- });
102
- yield* connectionRequest;
103
- const retryOnNewConnectionFiber = yield* Stream.fromPubSub(newConnectionAvailablePubSub).pipe(Stream.tap(() => Effect.spanEvent(`RetryOnNewConnection`)), Stream.tap(() => connectionRequest), Stream.runDrain, Effect.forkScoped);
104
- const portResult = yield* deferred.pipe(Effect.either);
105
- yield* Fiber.interrupt(retryOnNewConnectionFiber);
106
- if (portResult._tag === 'Right') {
107
- return yield* channelFromPort(portResult.right);
108
- }
109
- else {
110
- // We'll keep retrying with a new connection
111
- yield* Stream.fromPubSub(newConnectionAvailablePubSub).pipe(Stream.take(1), Stream.runDrain);
112
- yield* reconnect;
113
- return yield* Effect.interrupt;
114
95
  }
115
96
  }
116
- else {
117
- // In this case we've already received a request from the other side (before we had a chance to send our request),
118
- // so we already created a MessageChannel,responded with one port
119
- // and are now using the other port to create the channel.
120
- if (channelState._tag === 'ResponseSent') {
121
- return yield* channelFromPort(channelState.locallyCreatedPort);
122
- }
123
- else {
124
- return shouldNeverHappen(`Expected pending message channel to be in ResponseSent state, but was in ${channelState._tag} state`);
97
+ // Now we wait until the first channel is established
98
+ const { channel, makeMessageChannelScope, channelVersion } = yield* resultDeferred;
99
+ yield* Effect.spanEvent(`Connected#${channelVersion}`);
100
+ debugInfo.isConnected = true;
101
+ debugInfo.innerChannelRef.current = channel;
102
+ yield* Deferred.succeed(initialEdgeDeferred, void 0);
103
+ // We'll now forward all incoming messages to the listen queue
104
+ yield* channel.listen.pipe(Stream.flatten(),
105
+ // Stream.tap((msg) => Effect.log(`${target}→${channelName}→${nodeName}:message:${msg.message}`)),
106
+ Stream.tapChunk((chunk) => Queue.offerAll(listenQueue, chunk)), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkIn(makeMessageChannelScope));
107
+ yield* Effect.gen(function* () {
108
+ while (true) {
109
+ const [msg, deferred] = yield* TQueue.peek(sendQueue);
110
+ // NOTE we don't need an explicit retry flow here since in case of the channel being closed,
111
+ // the send will never succeed. Meanwhile the send-loop fiber will be interrupted and
112
+ // given we only peeked at the queue, the message to send is still there.
113
+ yield* channel.send(msg);
114
+ yield* Deferred.succeed(deferred, void 0);
115
+ yield* TQueue.take(sendQueue); // Remove the message from the queue
125
116
  }
126
- }
127
- });
128
- const internalChannelSref = yield* SubscriptionRef.make(false);
129
- const listenQueue = yield* Queue.unbounded();
130
- let connectCounter = 0;
131
- const connect = Effect.gen(function* () {
132
- const connectCount = ++connectCounter;
133
- yield* Effect.spanEvent(`Connecting#${connectCount}`);
134
- yield* SubscriptionRef.set(internalChannelSref, false);
135
- yield* Effect.addFinalizer(() => Effect.spanEvent(`Disconnected#${connectCount}`));
136
- const internalChannel = yield* makeMessageChannelInternal;
137
- yield* SubscriptionRef.set(internalChannelSref, internalChannel);
138
- yield* Effect.spanEvent(`Connected#${connectCount}`);
139
- yield* internalChannel.listen.pipe(Stream.flatten(), Stream.tap((msg) => Queue.offer(listenQueue, msg)), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkScoped);
140
- yield* Effect.never;
141
- }).pipe(Effect.scoped);
142
- const fiberHandle = yield* FiberHandle.make();
143
- const runConnect = Effect.gen(function* () {
144
- // Cleanly shutdown the previous connection first
145
- // Otherwise the old and new connection will "overlap"
146
- yield* FiberHandle.clear(fiberHandle);
147
- yield* FiberHandle.run(fiberHandle, connect);
148
- });
149
- yield* runConnect;
150
- // Then listen for reconnects
151
- yield* Stream.fromQueue(reconnectTriggerQueue).pipe(Stream.tap(() => runConnect), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkScoped);
152
- // Wait for the initial connection to be established or for an error to occur
153
- yield* Effect.raceFirst(SubscriptionRef.waitUntil(internalChannelSref, (channel) => channel !== false), FiberHandle.join(fiberHandle));
117
+ }).pipe(Effect.forkIn(makeMessageChannelScope));
118
+ // Wait until the channel is closed and then try to reconnect
119
+ yield* channel.closedDeferred;
120
+ yield* Scope.close(makeMessageChannelScope, Exit.succeed('channel-closed'));
121
+ yield* Effect.spanEvent(`Disconnected#${channelVersion}`);
122
+ debugInfo.isConnected = false;
123
+ debugInfo.innerChannelRef.current = undefined;
124
+ }).pipe(Effect.scoped, // Additionally scoping here to clean up finalizers after each loop run
125
+ Effect.forever, Effect.tapCauseLogPretty, Effect.forkScoped);
126
+ // #endregion reconnect-loop
154
127
  const parentSpan = yield* Effect.currentSpan.pipe(Effect.orDie);
155
128
  const send = (message) => Effect.gen(function* () {
156
- const sendFiberHandle = yield* FiberHandle.make();
157
129
  const sentDeferred = yield* Deferred.make();
158
- const trySend = Effect.gen(function* () {
159
- const channel = (yield* SubscriptionRef.waitUntil(internalChannelSref, (channel) => channel !== false));
160
- const innerSend = Effect.gen(function* () {
161
- yield* channel.send(message);
162
- yield* Deferred.succeed(sentDeferred, void 0);
163
- });
164
- yield* innerSend.pipe(Effect.timeout(100), Effect.retry(Schedule.exponential(100)), Effect.orDie);
165
- }).pipe(Effect.tapErrorCause(Effect.logError));
166
- const rerunOnNewChannelFiber = yield* internalChannelSref.changes.pipe(Stream.filter((_) => _ === false), Stream.tap(() => FiberHandle.run(sendFiberHandle, trySend)), Stream.runDrain, Effect.fork);
167
- yield* FiberHandle.run(sendFiberHandle, trySend);
130
+ debugInfo.pendingSends++;
131
+ debugInfo.totalSends++;
132
+ yield* TQueue.offer(sendQueue, [message, sentDeferred]);
168
133
  yield* sentDeferred;
169
- yield* Fiber.interrupt(rerunOnNewChannelFiber);
134
+ debugInfo.pendingSends--;
170
135
  }).pipe(Effect.scoped, Effect.withParentSpan(parentSpan));
171
- const listen = Stream.fromQueue(listenQueue).pipe(Stream.map(Either.right));
172
- const closedDeferred = yield* Deferred.make();
136
+ const listen = Stream.fromQueue(listenQueue, { maxChunkSize: 1 }).pipe(Stream.map(Either.right));
137
+ const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
173
138
  const webChannel = {
174
139
  [WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
175
140
  send,
@@ -177,7 +142,12 @@ export const makeMessageChannel = ({ nodeName, queue, newConnectionAvailablePubS
177
142
  closedDeferred,
178
143
  supportsTransferables: true,
179
144
  schema,
145
+ debugInfo,
146
+ shutdown: Scope.close(scope, Exit.succeed('shutdown')),
147
+ };
148
+ return {
149
+ webChannel: webChannel,
150
+ initialEdgeDeferred,
180
151
  };
181
- return webChannel;
182
- }).pipe(Effect.withSpanScoped('makeMessageChannel'));
152
+ }));
183
153
  //# sourceMappingURL=message-channel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-channel.js","sourceRoot":"","sources":["../../src/channel/message-channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message-channel.js","sourceRoot":"","sources":["../../src/channel/message-channel.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import type { PubSub } from '@livestore/utils/effect';
2
- import { Effect, Queue, Schema, WebChannel } from '@livestore/utils/effect';
2
+ import { Effect, Queue, Schema, Scope, WebChannel } from '@livestore/utils/effect';
3
3
  import { type ChannelName, type MeshNodeName, type ProxyQueueItem } from '../common.js';
4
4
  import * as MeshSchema from '../mesh-schema.js';
5
5
  interface MakeProxyChannelArgs {
6
6
  queue: Queue.Queue<ProxyQueueItem>;
7
7
  nodeName: MeshNodeName;
8
- newConnectionAvailablePubSub: PubSub.PubSub<MeshNodeName>;
8
+ newEdgeAvailablePubSub: PubSub.PubSub<MeshNodeName>;
9
9
  sendPacket: (packet: typeof MeshSchema.ProxyChannelPacket.Type) => Effect.Effect<void>;
10
10
  channelName: ChannelName;
11
11
  target: MeshNodeName;
@@ -14,6 +14,6 @@ interface MakeProxyChannelArgs {
14
14
  listen: Schema.Schema<any, any>;
15
15
  };
16
16
  }
17
- export declare const makeProxyChannel: ({ queue, nodeName, newConnectionAvailablePubSub, sendPacket, target, channelName, schema, }: MakeProxyChannelArgs) => Effect.Effect<WebChannel.WebChannel<any, any, never>, never, import("effect/Scope").Scope>;
17
+ export declare const makeProxyChannel: ({ queue, nodeName, newEdgeAvailablePubSub, sendPacket, target, channelName, schema, }: MakeProxyChannelArgs) => Effect.Effect<WebChannel.WebChannel<any, any, never>, never, Scope.Scope>;
18
18
  export {};
19
19
  //# sourceMappingURL=proxy-channel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-channel.d.ts","sourceRoot":"","sources":["../../src/channel/proxy-channel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAEL,MAAM,EAIN,KAAK,EAEL,MAAM,EAGN,UAAU,EACX,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAE/C,UAAU,oBAAoB;IAC5B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAClC,QAAQ,EAAE,YAAY,CAAA;IACtB,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzD,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,kBAAkB,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtF,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;KAChC,CAAA;CACF;AAED,eAAO,MAAM,gBAAgB,gGAQ1B,oBAAoB,+FA4R6B,CAAA"}
1
+ {"version":3,"file":"proxy-channel.d.ts","sourceRoot":"","sources":["../../src/channel/proxy-channel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAEL,MAAM,EAKN,KAAK,EAEL,MAAM,EACN,KAAK,EAGL,UAAU,EACX,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAE/C,UAAU,oBAAoB;IAC5B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAClC,QAAQ,EAAE,YAAY,CAAA;IACtB,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACnD,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,kBAAkB,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtF,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;KAChC,CAAA;CACF;AAED,eAAO,MAAM,gBAAgB,GAAI,uFAQ9B,oBAAoB,8EAsTpB,CAAA"}
@@ -1,10 +1,16 @@
1
1
  import { casesHandled, shouldNeverHappen } from '@livestore/utils';
2
- import { Deferred, Effect, Either, Fiber, FiberHandle, Queue, Schedule, Schema, Stream, SubscriptionRef, WebChannel, } from '@livestore/utils/effect';
2
+ import { Deferred, Effect, Either, Exit, Fiber, FiberHandle, Queue, Schedule, Schema, Scope, Stream, SubscriptionRef, WebChannel, } from '@livestore/utils/effect';
3
3
  import { nanoid } from '@livestore/utils/nanoid';
4
4
  import { packetAsOtelAttributes, } from '../common.js';
5
5
  import * as MeshSchema from '../mesh-schema.js';
6
- export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub, sendPacket, target, channelName, schema, }) => Effect.gen(function* () {
6
+ export const makeProxyChannel = ({ queue, nodeName, newEdgeAvailablePubSub, sendPacket, target, channelName, schema, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
7
7
  const channelStateRef = { current: { _tag: 'Initial' } };
8
+ const debugInfo = {
9
+ pendingSends: 0,
10
+ totalSends: 0,
11
+ connectCounter: 0,
12
+ isConnected: false,
13
+ };
8
14
  /**
9
15
  * We need to unique identify a channel as multiple channels might exist between the same two nodes.
10
16
  * We do this by letting each channel end generate a unique id and then combining them in a deterministic way.
@@ -18,7 +24,7 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
18
24
  return state;
19
25
  });
20
26
  const setStateToEstablished = (channelId) => Effect.gen(function* () {
21
- // TODO avoid "double" `Connected` events (we might call `setStateToEstablished` twice during initial connection)
27
+ // TODO avoid "double" `Connected` events (we might call `setStateToEstablished` twice during initial edge)
22
28
  yield* Effect.spanEvent(`Connected (${channelId})`).pipe(Effect.withParentSpan(channelSpan));
23
29
  channelStateRef.current = {
24
30
  _tag: 'Established',
@@ -28,13 +34,14 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
28
34
  combinedChannelId: channelId,
29
35
  };
30
36
  yield* SubscriptionRef.set(connectedStateRef, channelStateRef.current);
37
+ debugInfo.isConnected = true;
31
38
  });
32
- const connectionRequest = Effect.suspend(() => sendPacket(MeshSchema.ProxyChannelRequest.make({ channelName, hops: [], source: nodeName, target, channelIdCandidate })));
39
+ const edgeRequest = Effect.suspend(() => sendPacket(MeshSchema.ProxyChannelRequest.make({ channelName, hops: [], source: nodeName, target, channelIdCandidate })));
33
40
  const getCombinedChannelId = (otherSideChannelIdCandidate) => [channelIdCandidate, otherSideChannelIdCandidate].sort().join('_');
34
41
  const processProxyPacket = ({ packet, respondToSender }) => Effect.gen(function* () {
35
42
  // yield* Effect.log(`${nodeName}:processing packet ${packet._tag} from ${packet.source}`)
36
43
  const otherSideName = packet.source;
37
- const channelKey = `${otherSideName}-${packet.channelName}`;
44
+ const channelKey = `target:${otherSideName}, channelName:${packet.channelName}`;
38
45
  const channelState = channelStateRef.current;
39
46
  switch (packet._tag) {
40
47
  case 'ProxyChannelRequest': {
@@ -43,9 +50,11 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
43
50
  yield* SubscriptionRef.set(connectedStateRef, false);
44
51
  channelStateRef.current = { _tag: 'Pending', initiatedVia: 'incoming-request' };
45
52
  yield* Effect.spanEvent(`Reconnecting`).pipe(Effect.withParentSpan(channelSpan));
46
- // If we're already connected, we need to re-establish the connection
53
+ debugInfo.isConnected = false;
54
+ debugInfo.connectCounter++;
55
+ // If we're already connected, we need to re-establish the edge
47
56
  if (channelState._tag === 'Established' && channelState.combinedChannelId !== combinedChannelId) {
48
- yield* connectionRequest;
57
+ yield* edgeRequest;
49
58
  }
50
59
  }
51
60
  yield* respondToSender(MeshSchema.ProxyChannelResponseSuccess.make({
@@ -63,8 +72,9 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
63
72
  case 'ProxyChannelResponseSuccess': {
64
73
  if (channelState._tag !== 'Pending') {
65
74
  // return shouldNeverHappen(`Expected proxy channel to be pending but got ${channelState._tag}`)
66
- if (channelState._tag === 'Established' && channelState.combinedChannelId !== packet.combinedChannelId) {
67
- return shouldNeverHappen(`Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
75
+ if (channelState._tag === 'Established' &&
76
+ channelState.combinedChannelId !== packet.combinedChannelId) {
77
+ return shouldNeverHappen(`ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
68
78
  }
69
79
  else {
70
80
  // for now just ignore it but should be looked into (there seems to be some kind of race condition/inefficiency)
@@ -72,7 +82,7 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
72
82
  }
73
83
  const combinedChannelId = getCombinedChannelId(packet.channelIdCandidate);
74
84
  if (combinedChannelId !== packet.combinedChannelId) {
75
- return yield* Effect.die(`Expected proxy channel to have the same combinedChannelId as the packet:\n${combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
85
+ return yield* Effect.die(`ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
76
86
  }
77
87
  yield* setStateToEstablished(packet.combinedChannelId);
78
88
  return;
@@ -84,7 +94,7 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
84
94
  return;
85
95
  }
86
96
  if (channelState.combinedChannelId !== packet.combinedChannelId) {
87
- return yield* Effect.die(`Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
97
+ return yield* Effect.die(`ProxyChannel[${channelKey}]: Expected proxy channel to have the same combinedChannelId as the packet:\n${channelState.combinedChannelId} (channel) === ${packet.combinedChannelId} (packet)`);
88
98
  }
89
99
  yield* respondToSender(MeshSchema.ProxyChannelPayloadAck.make({
90
100
  reqId: packet.id,
@@ -105,7 +115,7 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
105
115
  return;
106
116
  }
107
117
  const ack = channelState.ackMap.get(packet.reqId) ??
108
- shouldNeverHappen(`Expected ack for ${packet.reqId} in proxy channel ${channelKey}`);
118
+ shouldNeverHappen(`[ProxyChannel[${channelKey}]] Expected ack for ${packet.reqId}`);
109
119
  yield* Deferred.succeed(ack, void 0);
110
120
  channelState.ackMap.delete(packet.reqId);
111
121
  return;
@@ -122,23 +132,25 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
122
132
  yield* Effect.spanEvent(`Connecting`);
123
133
  const ackMap = new Map();
124
134
  // check if already established via incoming `ProxyChannelRequest` from other side
125
- // which indicates we already have a connection to the target node
135
+ // which indicates we already have a edge to the target node
126
136
  // const channelState = channelStateRef.current
127
137
  {
128
138
  if (channelStateRef.current._tag !== 'Initial') {
129
139
  return shouldNeverHappen('Expected proxy channel to be Initial');
130
140
  }
131
141
  channelStateRef.current = { _tag: 'Pending', initiatedVia: 'outgoing-request' };
132
- yield* connectionRequest;
133
- const retryOnNewConnectionFiber = yield* Stream.fromPubSub(newConnectionAvailablePubSub).pipe(Stream.tap(() => connectionRequest), Stream.runDrain, Effect.forkScoped);
142
+ yield* edgeRequest;
143
+ const retryOnNewEdgeFiber = yield* Stream.fromPubSub(newEdgeAvailablePubSub).pipe(Stream.tap(() => edgeRequest), Stream.runDrain, Effect.forkScoped);
134
144
  const { combinedChannelId: channelId } = yield* waitForEstablished;
135
- yield* Fiber.interrupt(retryOnNewConnectionFiber);
145
+ yield* Fiber.interrupt(retryOnNewEdgeFiber);
136
146
  yield* setStateToEstablished(channelId);
137
147
  }
138
148
  const send = (message) => Effect.gen(function* () {
139
149
  const payload = yield* Schema.encodeUnknown(schema.send)(message);
140
150
  const sendFiberHandle = yield* FiberHandle.make();
141
151
  const sentDeferred = yield* Deferred.make();
152
+ debugInfo.pendingSends++;
153
+ debugInfo.totalSends++;
142
154
  const trySend = Effect.gen(function* () {
143
155
  const { combinedChannelId } = (yield* SubscriptionRef.waitUntil(connectedStateRef, (channel) => channel !== false));
144
156
  const innerSend = Effect.gen(function* () {
@@ -152,12 +164,17 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
152
164
  target,
153
165
  combinedChannelId,
154
166
  });
167
+ // TODO consider handling previous ackMap entries which might leak/fill-up memory
168
+ // as only successful acks are removed from the map
155
169
  ackMap.set(packet.id, ack);
156
170
  yield* sendPacket(packet);
157
171
  yield* ack;
158
172
  yield* Deferred.succeed(sentDeferred, void 0);
173
+ debugInfo.pendingSends--;
159
174
  });
160
- yield* innerSend.pipe(Effect.timeout(100), Effect.retry(Schedule.exponential(100)), Effect.orDie);
175
+ // TODO make this configurable
176
+ // Schedule.exponential(10): 10, 20, 40, 80, 160, 320, ...
177
+ yield* innerSend.pipe(Effect.timeout(100), Effect.retry(Schedule.exponential(10)), Effect.orDie);
161
178
  }).pipe(Effect.tapErrorCause(Effect.logError));
162
179
  const rerunOnNewChannelFiber = yield* connectedStateRef.changes.pipe(Stream.filter((_) => _ === false), Stream.tap(() => FiberHandle.run(sendFiberHandle, trySend)), Stream.runDrain, Effect.fork);
163
180
  yield* FiberHandle.run(sendFiberHandle, trySend);
@@ -165,7 +182,7 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
165
182
  yield* Fiber.interrupt(rerunOnNewChannelFiber);
166
183
  }).pipe(Effect.scoped, Effect.withSpan(`sendAckWithRetry:ProxyChannelPayload`), Effect.withParentSpan(channelSpan));
167
184
  const listen = Stream.fromQueue(listenQueue).pipe(Stream.map(Either.right));
168
- const closedDeferred = yield* Deferred.make();
185
+ const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
169
186
  const webChannel = {
170
187
  [WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
171
188
  send,
@@ -173,7 +190,9 @@ export const makeProxyChannel = ({ queue, nodeName, newConnectionAvailablePubSub
173
190
  closedDeferred,
174
191
  supportsTransferables: true,
175
192
  schema,
193
+ shutdown: Scope.close(scope, Exit.void),
194
+ debugInfo,
176
195
  };
177
196
  return webChannel;
178
- }).pipe(Effect.withSpanScoped('makeProxyChannel'));
197
+ }).pipe(Effect.withSpanScoped('makeProxyChannel')));
179
198
  //# sourceMappingURL=proxy-channel.js.map