@livestore/webmesh 0.3.0-dev.10 → 0.3.0-dev.12
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/README.md +20 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/channel/message-channel copy.d.ts +9 -0
- package/dist/channel/message-channel copy.d.ts.map +1 -0
- package/dist/channel/message-channel copy.js +137 -0
- package/dist/channel/message-channel copy.js.map +1 -0
- package/dist/channel/message-channel-internal copy.d.ts +42 -0
- package/dist/channel/message-channel-internal copy.d.ts.map +1 -0
- package/dist/channel/message-channel-internal copy.js +239 -0
- package/dist/channel/message-channel-internal copy.js.map +1 -0
- package/dist/channel/message-channel-internal.d.ts +26 -0
- package/dist/channel/message-channel-internal.d.ts.map +1 -0
- package/dist/channel/message-channel-internal.js +217 -0
- package/dist/channel/message-channel-internal.js.map +1 -0
- package/dist/channel/message-channel.d.ts +21 -19
- package/dist/channel/message-channel.d.ts.map +1 -1
- package/dist/channel/message-channel.js +128 -162
- package/dist/channel/message-channel.js.map +1 -1
- package/dist/channel/proxy-channel.d.ts +2 -2
- package/dist/channel/proxy-channel.d.ts.map +1 -1
- package/dist/channel/proxy-channel.js +7 -5
- package/dist/channel/proxy-channel.js.map +1 -1
- package/dist/common.d.ts +8 -4
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +2 -1
- package/dist/common.js.map +1 -1
- package/dist/mesh-schema.d.ts +23 -1
- package/dist/mesh-schema.d.ts.map +1 -1
- package/dist/mesh-schema.js +21 -2
- package/dist/mesh-schema.js.map +1 -1
- package/dist/node.d.ts +12 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +40 -9
- package/dist/node.js.map +1 -1
- package/dist/node.test.d.ts +1 -1
- package/dist/node.test.d.ts.map +1 -1
- package/dist/node.test.js +300 -147
- package/dist/node.test.js.map +1 -1
- package/dist/websocket-connection.d.ts +1 -2
- package/dist/websocket-connection.d.ts.map +1 -1
- package/dist/websocket-connection.js +5 -4
- package/dist/websocket-connection.js.map +1 -1
- package/package.json +3 -3
- package/src/channel/message-channel-internal.ts +356 -0
- package/src/channel/message-channel.ts +183 -311
- package/src/channel/proxy-channel.ts +238 -230
- package/src/common.ts +3 -1
- package/src/mesh-schema.ts +20 -2
- package/src/node.test.ts +426 -177
- package/src/node.ts +70 -12
- package/src/websocket-connection.ts +83 -79
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Effect, Scope, WebChannel } from '@livestore/utils/effect';
|
|
2
|
+
import type { MakeMessageChannelArgs } from './message-channel-internal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Behaviour:
|
|
5
|
+
* - Waits until there is an initial connection
|
|
6
|
+
* - Automatically reconnects on disconnect
|
|
7
|
+
*/
|
|
8
|
+
export declare const makeMessageChannel: ({ schema, newConnectionAvailablePubSub, channelName, checkTransferableConnections, nodeName, incomingPacketsQueue, target, sendPacket, }: MakeMessageChannelArgs) => Effect.Effect<WebChannel.WebChannel<any, any, never>, never, Scope.Scope>;
|
|
9
|
+
//# sourceMappingURL=message-channel%20copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel copy.d.ts","sourceRoot":"","sources":["../../src/channel/message-channel copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,MAAM,EAKN,KAAK,EAGL,UAAU,EACX,MAAM,yBAAyB,CAAA;AAIhC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAE3E;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,6IAS5B,sBAAsB,8EAwLtB,CAAA"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Cause, Deferred, Effect, Either, Exit, Queue, Schema, Scope, Stream, TQueue, WebChannel, } from '@livestore/utils/effect';
|
|
2
|
+
import { nanoid } from '@livestore/utils/nanoid';
|
|
3
|
+
import { WebmeshSchema } from '../mod.js';
|
|
4
|
+
import { makeMessageChannelInternal } from './message-channel-internal.js';
|
|
5
|
+
/**
|
|
6
|
+
* Behaviour:
|
|
7
|
+
* - Waits until there is an initial connection
|
|
8
|
+
* - Automatically reconnects on disconnect
|
|
9
|
+
*/
|
|
10
|
+
export const makeMessageChannel = ({ schema, newConnectionAvailablePubSub, channelName, checkTransferableConnections, nodeName, incomingPacketsQueue, target, sendPacket, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
|
|
11
|
+
// const internalChannelSref = yield* SubscriptionRef.make<WebChannel.WebChannel<any, any> | false>(false)
|
|
12
|
+
// const state: 'connecting' | 'connected' = 'connecting'
|
|
13
|
+
const sourceId = nanoid();
|
|
14
|
+
const listenQueue = yield* Queue.unbounded();
|
|
15
|
+
const sendQueue = yield* TQueue.unbounded();
|
|
16
|
+
const initialConnectionDeferred = yield* Deferred.make();
|
|
17
|
+
let connectionCounter = 0;
|
|
18
|
+
// #region reconnect-loop
|
|
19
|
+
yield* Effect.gen(function* () {
|
|
20
|
+
const resultDeferred = yield* Deferred.make();
|
|
21
|
+
while (true) {
|
|
22
|
+
connectionCounter++;
|
|
23
|
+
const channelVersion = connectionCounter;
|
|
24
|
+
yield* Effect.spanEvent(`Connecting#${channelVersion}`);
|
|
25
|
+
const makeMessageChannelScope = yield* Scope.make();
|
|
26
|
+
// Attach the new scope to the parent scope
|
|
27
|
+
yield* Effect.addFinalizer((ex) => Scope.close(makeMessageChannelScope, ex));
|
|
28
|
+
/**
|
|
29
|
+
* Expected concurrency behaviour:
|
|
30
|
+
* - We're concurrently running the connection setup and the waitForNewConnectionFiber
|
|
31
|
+
* - Happy path:
|
|
32
|
+
* - The connection setup succeeds and we can interrupt the waitForNewConnectionFiber
|
|
33
|
+
* - Tricky paths:
|
|
34
|
+
* - While a connection is still being setup, we want to re-try when there is a new connection
|
|
35
|
+
* - If the connection setup returns a `MessageChannelResponseNoTransferables` error,
|
|
36
|
+
* we want to wait for a new connection and then re-try
|
|
37
|
+
* - Further notes:
|
|
38
|
+
* - If the parent scope closes, we want to also interrupt both the connection setup and the waitForNewConnectionFiber
|
|
39
|
+
* - We're creating a separate scope for each connection attempt, which
|
|
40
|
+
* - we'll use to fork the message channel in which allows us to interrupt it later
|
|
41
|
+
* - We need to make sure that "interruption" isn't "bubbling out"
|
|
42
|
+
*/
|
|
43
|
+
const waitForNewConnectionFiber = yield* Stream.fromPubSub(newConnectionAvailablePubSub).pipe(Stream.tap((connectionName) => Effect.spanEvent(`new-conn:${connectionName}`)), Stream.take(1), Stream.runDrain, Effect.as('new-connection'), Effect.fork);
|
|
44
|
+
const makeChannel = makeMessageChannelInternal({
|
|
45
|
+
nodeName,
|
|
46
|
+
sourceId,
|
|
47
|
+
incomingPacketsQueue,
|
|
48
|
+
target,
|
|
49
|
+
checkTransferableConnections,
|
|
50
|
+
channelName,
|
|
51
|
+
schema,
|
|
52
|
+
channelVersion,
|
|
53
|
+
newConnectionAvailablePubSub,
|
|
54
|
+
sendPacket,
|
|
55
|
+
scope: makeMessageChannelScope,
|
|
56
|
+
}).pipe(Scope.extend(makeMessageChannelScope), Effect.forkIn(makeMessageChannelScope));
|
|
57
|
+
const res = yield* Effect.raceFirst(makeChannel, waitForNewConnectionFiber.pipe(Effect.disconnect));
|
|
58
|
+
if (res === 'new-connection') {
|
|
59
|
+
yield* Scope.close(makeMessageChannelScope, Exit.fail('new-connection'));
|
|
60
|
+
// We'll try again
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const result = yield* res.pipe(Effect.exit);
|
|
64
|
+
if (result._tag === 'Failure') {
|
|
65
|
+
yield* Scope.close(makeMessageChannelScope, result);
|
|
66
|
+
if (Cause.isFailType(result.cause) &&
|
|
67
|
+
Schema.is(WebmeshSchema.MessageChannelResponseNoTransferables)(result.cause.error)) {
|
|
68
|
+
yield* waitForNewConnectionFiber.pipe(Effect.exit);
|
|
69
|
+
}
|
|
70
|
+
// yield* Effect.log('result.fail', { nodeName, channelVersion }, Cause.pretty(result.cause))
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const channel = result.value;
|
|
74
|
+
yield* Deferred.succeed(resultDeferred, { channel, makeMessageChannelScope, channelVersion });
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Now we wait until the first channel is established
|
|
80
|
+
const { channel, makeMessageChannelScope, channelVersion } = yield* resultDeferred;
|
|
81
|
+
yield* Effect.spanEvent(`Connected#${channelVersion}`);
|
|
82
|
+
yield* Deferred.succeed(initialConnectionDeferred, void 0);
|
|
83
|
+
// We'll now forward all incoming messages to the listen queue
|
|
84
|
+
yield* channel.listen.pipe(Stream.flatten(),
|
|
85
|
+
// Stream.tap((msg) => Effect.log(`${target}→${channelName}→${nodeName}:message:${msg.message}`)),
|
|
86
|
+
Stream.tapChunk((chunk) => Queue.offerAll(listenQueue, chunk)), Stream.runDrain, Effect.tapCauseLogPretty, Effect.forkIn(makeMessageChannelScope));
|
|
87
|
+
yield* Effect.gen(function* () {
|
|
88
|
+
while (true) {
|
|
89
|
+
const [msg, deferred] = yield* TQueue.peek(sendQueue);
|
|
90
|
+
// NOTE we don't need an explicit retry flow here since in case of the channel being closed,
|
|
91
|
+
// the send will never succeed. Meanwhile the send-loop fiber will be interrupted and
|
|
92
|
+
// given we only peeked at the queue, the message to send is still there.
|
|
93
|
+
yield* channel.send(msg);
|
|
94
|
+
yield* Deferred.succeed(deferred, void 0);
|
|
95
|
+
yield* TQueue.take(sendQueue); // Remove the message from the queue
|
|
96
|
+
}
|
|
97
|
+
}).pipe(Effect.forkIn(makeMessageChannelScope));
|
|
98
|
+
// Wait until the channel is closed and then try to reconnect
|
|
99
|
+
yield* channel.closedDeferred;
|
|
100
|
+
yield* Scope.close(makeMessageChannelScope, Exit.succeed('channel-closed'));
|
|
101
|
+
yield* Effect.spanEvent(`Disconnected#${channelVersion}`);
|
|
102
|
+
}).pipe(Effect.scoped, // Additionally scoping here to clean up finalizers after each loop run
|
|
103
|
+
Effect.forever,
|
|
104
|
+
// Effect.withSpan('makeMessageChannelManaged:connect-loop'),
|
|
105
|
+
Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
106
|
+
// #endregion reconnect-loop
|
|
107
|
+
const debugInfo = {
|
|
108
|
+
pendingSends: 0,
|
|
109
|
+
totalSends: 0,
|
|
110
|
+
connectCounter: 1,
|
|
111
|
+
};
|
|
112
|
+
const parentSpan = yield* Effect.currentSpan.pipe(Effect.orDie);
|
|
113
|
+
const send = (message) => Effect.gen(function* () {
|
|
114
|
+
// const sendFiberHandle = yield* FiberHandle.make<void, never>()
|
|
115
|
+
const sentDeferred = yield* Deferred.make();
|
|
116
|
+
debugInfo.pendingSends++;
|
|
117
|
+
debugInfo.totalSends++;
|
|
118
|
+
yield* TQueue.offer(sendQueue, [message, sentDeferred]);
|
|
119
|
+
yield* sentDeferred;
|
|
120
|
+
debugInfo.pendingSends--;
|
|
121
|
+
}).pipe(Effect.scoped, Effect.withParentSpan(parentSpan));
|
|
122
|
+
const listen = Stream.fromQueue(listenQueue, { maxChunkSize: 1 }).pipe(Stream.map(Either.right));
|
|
123
|
+
const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
|
|
124
|
+
yield* initialConnectionDeferred;
|
|
125
|
+
const webChannel = {
|
|
126
|
+
[WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
|
|
127
|
+
send,
|
|
128
|
+
listen,
|
|
129
|
+
closedDeferred,
|
|
130
|
+
supportsTransferables: true,
|
|
131
|
+
schema,
|
|
132
|
+
debugInfo,
|
|
133
|
+
shutdown: Scope.close(scope, Exit.succeed('shutdown')),
|
|
134
|
+
};
|
|
135
|
+
return webChannel;
|
|
136
|
+
}));
|
|
137
|
+
//# sourceMappingURL=message-channel%20copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel copy.js","sourceRoot":"","sources":["../../src/channel/message-channel copy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PubSub } from '@livestore/utils/effect';
|
|
2
|
+
import { Effect, Queue, Scope, WebChannel } from '@livestore/utils/effect';
|
|
3
|
+
import { type ChannelName, type MeshNodeName, type MessageQueueItem } from '../common.js';
|
|
4
|
+
import * as MeshSchema from '../mesh-schema.js';
|
|
5
|
+
export interface MakeMessageChannelArgs {
|
|
6
|
+
nodeName: MeshNodeName;
|
|
7
|
+
/** Queue of incoming messages for this channel */
|
|
8
|
+
incomingPacketsQueue: Queue.Queue<MessageQueueItem>;
|
|
9
|
+
newConnectionAvailablePubSub: PubSub.PubSub<MeshNodeName>;
|
|
10
|
+
channelName: ChannelName;
|
|
11
|
+
target: MeshNodeName;
|
|
12
|
+
sendPacket: (packet: typeof MeshSchema.MessageChannelPacket.Type) => Effect.Effect<void>;
|
|
13
|
+
checkTransferableConnections: (packet: typeof MeshSchema.MessageChannelPacket.Type) => typeof MeshSchema.MessageChannelResponseNoTransferables.Type | undefined;
|
|
14
|
+
schema: WebChannel.OutputSchema<any, any, any, any>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* `makeChannel` needs to be called on both sides to establish a connection ("symmetrically")
|
|
18
|
+
*
|
|
19
|
+
* Implementation notes:
|
|
20
|
+
* - There is an internal web channel and a wrapping "proxy channel"
|
|
21
|
+
* - Reasons for outside proxy channel:
|
|
22
|
+
* - Re-try to establish initial channel when there are new connections available
|
|
23
|
+
* - Re-connect if the connection is lost
|
|
24
|
+
* - Create a separate layer as "channel wrapper" which is responsible for:
|
|
25
|
+
* - initial connection based on new connection available
|
|
26
|
+
* - re-connect on disconnect
|
|
27
|
+
* - heartbeat
|
|
28
|
+
* - ...
|
|
29
|
+
*
|
|
30
|
+
* Channel connection init process:
|
|
31
|
+
* - Both sides send a `MessageChannelRequest` packet which includes a channel version
|
|
32
|
+
* - The other side responds with a `MessageChannelResponseSuccess` packet which includes
|
|
33
|
+
* the max version of both sides as the agreed upon version for the channel
|
|
34
|
+
* - The channel starts listening on the port of the side with the highest version (or with the "larger" name as tie-breaker)
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
export declare const makeMessageChannelInternal: ({ nodeName, incomingPacketsQueue, target, checkTransferableConnections, channelName, schema: schema_, sendPacket, channelVersion, scope, sourceId, }: MakeMessageChannelArgs & {
|
|
38
|
+
channelVersion: number;
|
|
39
|
+
scope: Scope.CloseableScope;
|
|
40
|
+
sourceId: string;
|
|
41
|
+
}) => Effect.Effect<WebChannel.WebChannel<any, any>, typeof MeshSchema.MessageChannelResponseNoTransferables.Type, Scope.Scope>;
|
|
42
|
+
//# sourceMappingURL=message-channel-internal%20copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel-internal copy.d.ts","sourceRoot":"","sources":["../../src/channel/message-channel-internal copy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAEL,MAAM,EAIN,KAAK,EAEL,KAAK,EAEL,UAAU,EACX,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAA0B,MAAM,cAAc,CAAA;AACjH,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAE/C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,YAAY,CAAA;IACtB,kDAAkD;IAClD,oBAAoB,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACnD,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzD,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACxF,4BAA4B,EAAE,CAC5B,MAAM,EAAE,OAAO,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAChD,OAAO,UAAU,CAAC,qCAAqC,CAAC,IAAI,GAAG,SAAS,CAAA;IAC7E,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CACpD;AAOD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,0BAA0B,yJAWpC,sBAAsB,GAAG;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,KAAK,CAAC,cAAc,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;CACjB,KAAG,MAAM,CAAC,MAAM,CACf,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAC/B,OAAO,UAAU,CAAC,qCAAqC,CAAC,IAAI,EAC5D,KAAK,CAAC,KAAK,CA0S2D,CAAA"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { casesHandled, shouldNeverHappen } from '@livestore/utils';
|
|
2
|
+
import { Deferred, Effect, Exit, OtelTracer, Predicate, Queue, Schema, Scope, Stream, WebChannel, } from '@livestore/utils/effect';
|
|
3
|
+
import { packetAsOtelAttributes } from '../common.js';
|
|
4
|
+
import * as MeshSchema from '../mesh-schema.js';
|
|
5
|
+
const makeDeferredResult = (Deferred.make);
|
|
6
|
+
/**
|
|
7
|
+
* `makeChannel` needs to be called on both sides to establish a connection ("symmetrically")
|
|
8
|
+
*
|
|
9
|
+
* Implementation notes:
|
|
10
|
+
* - There is an internal web channel and a wrapping "proxy channel"
|
|
11
|
+
* - Reasons for outside proxy channel:
|
|
12
|
+
* - Re-try to establish initial channel when there are new connections available
|
|
13
|
+
* - Re-connect if the connection is lost
|
|
14
|
+
* - Create a separate layer as "channel wrapper" which is responsible for:
|
|
15
|
+
* - initial connection based on new connection available
|
|
16
|
+
* - re-connect on disconnect
|
|
17
|
+
* - heartbeat
|
|
18
|
+
* - ...
|
|
19
|
+
*
|
|
20
|
+
* Channel connection init process:
|
|
21
|
+
* - Both sides send a `MessageChannelRequest` packet which includes a channel version
|
|
22
|
+
* - The other side responds with a `MessageChannelResponseSuccess` packet which includes
|
|
23
|
+
* the max version of both sides as the agreed upon version for the channel
|
|
24
|
+
* - The channel starts listening on the port of the side with the highest version (or with the "larger" name as tie-breaker)
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
export const makeMessageChannelInternal = ({ nodeName, incomingPacketsQueue, target, checkTransferableConnections, channelName, schema: schema_, sendPacket, channelVersion, scope, sourceId, }) => Effect.gen(function* () {
|
|
28
|
+
// yield* Effect.addFinalizer((exit) =>
|
|
29
|
+
// Effect.spanEvent(`shutdown:${exit._tag === 'Success' ? 'Success' : Cause.pretty(exit.cause)}`),
|
|
30
|
+
// )
|
|
31
|
+
const deferred = yield* makeDeferredResult();
|
|
32
|
+
const span = yield* OtelTracer.currentOtelSpan.pipe(Effect.catchAll(() => Effect.succeed(undefined)));
|
|
33
|
+
const schema = {
|
|
34
|
+
send: Schema.Union(schema_.send, MeshSchema.MessageChannelPing, MeshSchema.MessageChannelPong),
|
|
35
|
+
listen: Schema.Union(schema_.listen, MeshSchema.MessageChannelPing, MeshSchema.MessageChannelPong),
|
|
36
|
+
};
|
|
37
|
+
const channelStateRef = {
|
|
38
|
+
current: { _tag: 'Initial' },
|
|
39
|
+
};
|
|
40
|
+
const processMessagePacket = ({ packet, respondToSender }) => Effect.gen(function* () {
|
|
41
|
+
const channelState = channelStateRef.current;
|
|
42
|
+
span?.addEvent(`process:${packet._tag}`, {
|
|
43
|
+
channelState: channelState._tag,
|
|
44
|
+
packetId: packet.id,
|
|
45
|
+
packetReqId: packet.reqId,
|
|
46
|
+
packetChannelVersion: Predicate.hasProperty('channelVersion')(packet) ? packet.channelVersion : undefined,
|
|
47
|
+
});
|
|
48
|
+
yield* Effect.log(`${nodeName}→${channelName}→${target}:process packet ${packet._tag} [${channelVersion}], channel state: ${channelState._tag}`);
|
|
49
|
+
if (channelState._tag === 'Initial')
|
|
50
|
+
return shouldNeverHappen();
|
|
51
|
+
if (packet._tag === 'MessageChannelResponseNoTransferables') {
|
|
52
|
+
yield* Deferred.fail(deferred, packet);
|
|
53
|
+
return 'close';
|
|
54
|
+
}
|
|
55
|
+
// If the other side has a higher version, we need to close this channel and
|
|
56
|
+
// recreate it with the new version
|
|
57
|
+
if (packet.channelVersion > channelVersion) {
|
|
58
|
+
span?.addEvent(`incoming packet has higher version (${packet.channelVersion}), closing channel`);
|
|
59
|
+
yield* Scope.close(scope, Exit.succeed('higher-version-expected'));
|
|
60
|
+
// TODO include expected version in the error so the channel gets recreated with the new version
|
|
61
|
+
return 'close';
|
|
62
|
+
}
|
|
63
|
+
// If this channel has a higher version, we need to signal the other side to close
|
|
64
|
+
// and recreate the channel with the new version
|
|
65
|
+
if (packet.channelVersion < channelVersion) {
|
|
66
|
+
const newPacket = MeshSchema.MessageChannelRequest.make({
|
|
67
|
+
source: nodeName,
|
|
68
|
+
sourceId,
|
|
69
|
+
target,
|
|
70
|
+
channelName,
|
|
71
|
+
channelVersion,
|
|
72
|
+
hops: [],
|
|
73
|
+
remainingHops: packet.hops,
|
|
74
|
+
reqId: undefined,
|
|
75
|
+
});
|
|
76
|
+
span?.addEvent(`incoming packet has lower version (${packet.channelVersion}), sending request to reconnect (${newPacket.id})`);
|
|
77
|
+
yield* sendPacket(newPacket);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Ignore further incoming packets if the channel is already established
|
|
81
|
+
// if (channelState._tag === 'Established') return
|
|
82
|
+
if (channelState._tag === 'Established' && packet._tag === 'MessageChannelRequest') {
|
|
83
|
+
if (packet.sourceId === channelState.otherSourceId) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
span?.addEvent(`force-new-channel`);
|
|
88
|
+
yield* Scope.close(scope, Exit.succeed('force-new-channel'));
|
|
89
|
+
return 'close';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
switch (packet._tag) {
|
|
93
|
+
case 'MessageChannelRequest': {
|
|
94
|
+
/*
|
|
95
|
+
New impl idea:
|
|
96
|
+
- For request that has a lower version, send its own request as a signal
|
|
97
|
+
- Determine "winner" in request handler and only the winner is sending a response
|
|
98
|
+
- The loser will instead listen for a response on the channel itself
|
|
99
|
+
|
|
100
|
+
How to avoid request loops / circuit-breakering
|
|
101
|
+
- we need to gurantee that each side has received the request
|
|
102
|
+
- each other side needs to know it
|
|
103
|
+
- idea: use the request packet id from A as a reference when sending a request back from B to A
|
|
104
|
+
- this way A knows that
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
Assumptions:
|
|
108
|
+
- each side has sent their request which has to arrive at the other side
|
|
109
|
+
*/
|
|
110
|
+
if (channelState._tag !== 'RequestSent') {
|
|
111
|
+
// We can safely ignore further incoming requests as we're already creating a channel
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (packet.reqId === channelState.reqPacketId) {
|
|
115
|
+
// Circuit-breaker: We've already sent a request so we don't need to send another one
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const newRequestPacket = MeshSchema.MessageChannelRequest.make({
|
|
119
|
+
source: nodeName,
|
|
120
|
+
sourceId,
|
|
121
|
+
target,
|
|
122
|
+
channelName,
|
|
123
|
+
channelVersion,
|
|
124
|
+
hops: [],
|
|
125
|
+
remainingHops: packet.hops,
|
|
126
|
+
reqId: packet.id,
|
|
127
|
+
});
|
|
128
|
+
span?.addEvent(`Re-sending new request (${newRequestPacket.id}) for incoming request (${packet.id})`);
|
|
129
|
+
yield* sendPacket(newRequestPacket);
|
|
130
|
+
}
|
|
131
|
+
const isWinner = nodeName > target;
|
|
132
|
+
if (isWinner) {
|
|
133
|
+
span?.addEvent(`winner side: creating message channel and sending response`);
|
|
134
|
+
const mc = new MessageChannel();
|
|
135
|
+
const channel = yield* WebChannel.messagePortChannelWithAck({
|
|
136
|
+
port: mc.port1,
|
|
137
|
+
schema,
|
|
138
|
+
debugId: channelVersion,
|
|
139
|
+
}).pipe(Effect.andThen(WebChannel.toOpenChannel));
|
|
140
|
+
yield* respondToSender(MeshSchema.MessageChannelResponseSuccess.make({
|
|
141
|
+
reqId: packet.id,
|
|
142
|
+
target,
|
|
143
|
+
source: nodeName,
|
|
144
|
+
channelName: packet.channelName,
|
|
145
|
+
hops: [],
|
|
146
|
+
remainingHops: packet.hops,
|
|
147
|
+
port: mc.port2,
|
|
148
|
+
channelVersion,
|
|
149
|
+
}));
|
|
150
|
+
channelStateRef.current = { _tag: 'winner:ResponseSent', channel, otherSourceId: packet.sourceId };
|
|
151
|
+
// Now we wait for the other side to respond via the channel
|
|
152
|
+
yield* channel.listen.pipe(Stream.flatten(), Stream.filter(Schema.is(MeshSchema.MessageChannelPing)), Stream.take(1), Stream.runDrain);
|
|
153
|
+
yield* channel.send(MeshSchema.MessageChannelPong.make({}));
|
|
154
|
+
span?.addEvent(`winner side: established`);
|
|
155
|
+
channelStateRef.current = { _tag: 'Established', otherSourceId: packet.sourceId };
|
|
156
|
+
yield* Deferred.succeed(deferred, channel);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
span?.addEvent(`loser side: waiting for response`);
|
|
160
|
+
// Wait for `MessageChannelResponseSuccess` packet
|
|
161
|
+
channelStateRef.current = { _tag: 'loser:WaitingForResponse', otherSourceId: packet.sourceId };
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
// Since there can be concurrent MessageChannel responses from both sides,
|
|
166
|
+
// we need to decide which side's port we want to use and which side's port we want to ignore.
|
|
167
|
+
// This is only relevant in the case where both sides already sent their responses.
|
|
168
|
+
// In this case we're using the target name as a "tie breaker" to decide which side's port to use.
|
|
169
|
+
// We do this by sorting the target names lexicographically and use the first one as the winner.
|
|
170
|
+
case 'MessageChannelResponseSuccess': {
|
|
171
|
+
if (channelState._tag !== 'loser:WaitingForResponse') {
|
|
172
|
+
return shouldNeverHappen(`Expected to find message channel response from ${target}, but was in ${channelState._tag} state`);
|
|
173
|
+
}
|
|
174
|
+
const channel = yield* WebChannel.messagePortChannelWithAck({
|
|
175
|
+
port: packet.port,
|
|
176
|
+
schema,
|
|
177
|
+
debugId: channelVersion,
|
|
178
|
+
}).pipe(Effect.andThen(WebChannel.toOpenChannel));
|
|
179
|
+
const waitForPongFiber = yield* channel.listen.pipe(Stream.flatten(), Stream.filter(Schema.is(MeshSchema.MessageChannelPong)), Stream.take(1), Stream.runDrain, Effect.fork);
|
|
180
|
+
yield* channel.send(MeshSchema.MessageChannelPing.make({}));
|
|
181
|
+
yield* waitForPongFiber;
|
|
182
|
+
span?.addEvent(`loser side: established`);
|
|
183
|
+
channelStateRef.current = { _tag: 'Established', otherSourceId: channelState.otherSourceId };
|
|
184
|
+
yield* Deferred.succeed(deferred, channel);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
default: {
|
|
188
|
+
return casesHandled(packet);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}).pipe(Effect.withSpan(`handleMessagePacket:${packet._tag}:${packet.source}→${packet.target}`, {
|
|
192
|
+
attributes: packetAsOtelAttributes(packet),
|
|
193
|
+
}));
|
|
194
|
+
// yield* Stream.fromQueue(queue).pipe(
|
|
195
|
+
// Stream.tap(processMessagePacket),
|
|
196
|
+
// Stream.runDrain,
|
|
197
|
+
// Effect.interruptible,
|
|
198
|
+
// Effect.tapCauseLogPretty,
|
|
199
|
+
// Effect.forkScoped,
|
|
200
|
+
// )
|
|
201
|
+
yield* Effect.gen(function* () {
|
|
202
|
+
while (true) {
|
|
203
|
+
const packet = yield* Queue.take(incomingPacketsQueue);
|
|
204
|
+
const res = yield* processMessagePacket(packet);
|
|
205
|
+
// We want to give requests another chance to be processed
|
|
206
|
+
if (res === 'close') {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}).pipe(Effect.interruptible, Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
211
|
+
const channelState = channelStateRef.current;
|
|
212
|
+
if (channelState._tag !== 'Initial') {
|
|
213
|
+
return shouldNeverHappen(`Expected channel to be in Initial state, but was in ${channelState._tag} state`);
|
|
214
|
+
}
|
|
215
|
+
const connectionRequest = Effect.gen(function* () {
|
|
216
|
+
const packet = MeshSchema.MessageChannelRequest.make({
|
|
217
|
+
source: nodeName,
|
|
218
|
+
sourceId,
|
|
219
|
+
target,
|
|
220
|
+
channelName,
|
|
221
|
+
channelVersion,
|
|
222
|
+
hops: [],
|
|
223
|
+
reqId: undefined,
|
|
224
|
+
});
|
|
225
|
+
channelStateRef.current = { _tag: 'RequestSent', reqPacketId: packet.id };
|
|
226
|
+
// yield* Effect.log(`${nodeName}→${channelName}→${target}:connectionRequest [${channelVersion}]`)
|
|
227
|
+
const noTransferableResponse = checkTransferableConnections(packet);
|
|
228
|
+
if (noTransferableResponse !== undefined) {
|
|
229
|
+
yield* Effect.spanEvent(`No transferable connections found for ${packet.source}→${packet.target}`);
|
|
230
|
+
return yield* Effect.fail(noTransferableResponse);
|
|
231
|
+
}
|
|
232
|
+
yield* sendPacket(packet);
|
|
233
|
+
span?.addEvent(`initial connection request sent (${packet.id})`);
|
|
234
|
+
});
|
|
235
|
+
yield* connectionRequest;
|
|
236
|
+
const channel = yield* deferred;
|
|
237
|
+
return channel;
|
|
238
|
+
}).pipe(Effect.withSpanScoped(`makeMessageChannel:${channelVersion}`));
|
|
239
|
+
//# sourceMappingURL=message-channel-internal%20copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel-internal copy.js","sourceRoot":"","sources":["../../src/channel/message-channel-internal copy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PubSub } from '@livestore/utils/effect';
|
|
2
|
+
import { Effect, Queue, Scope, WebChannel } from '@livestore/utils/effect';
|
|
3
|
+
import { type ChannelName, type MeshNodeName, type MessageQueueItem } from '../common.js';
|
|
4
|
+
import * as MeshSchema from '../mesh-schema.js';
|
|
5
|
+
export interface MakeMessageChannelArgs {
|
|
6
|
+
nodeName: MeshNodeName;
|
|
7
|
+
/** Queue of incoming messages for this channel */
|
|
8
|
+
incomingPacketsQueue: Queue.Queue<MessageQueueItem>;
|
|
9
|
+
newConnectionAvailablePubSub: PubSub.PubSub<MeshNodeName>;
|
|
10
|
+
channelName: ChannelName;
|
|
11
|
+
target: MeshNodeName;
|
|
12
|
+
sendPacket: (packet: typeof MeshSchema.MessageChannelPacket.Type) => Effect.Effect<void>;
|
|
13
|
+
checkTransferableConnections: (packet: typeof MeshSchema.MessageChannelPacket.Type) => typeof MeshSchema.MessageChannelResponseNoTransferables.Type | undefined;
|
|
14
|
+
schema: WebChannel.OutputSchema<any, any, any, any>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The channel version is important here, as a channel will only be established once both sides have the same version.
|
|
18
|
+
* The version is used to avoid concurrency issues where both sides have different incompatible message ports.
|
|
19
|
+
*/
|
|
20
|
+
export declare const makeMessageChannelInternal: ({ nodeName, incomingPacketsQueue, target, checkTransferableConnections, channelName, schema: schema_, sendPacket, channelVersion, scope, sourceId, }: MakeMessageChannelArgs & {
|
|
21
|
+
channelVersion: number;
|
|
22
|
+
/** We're passing in the closeable scope from the wrapping message channel */
|
|
23
|
+
scope: Scope.CloseableScope;
|
|
24
|
+
sourceId: string;
|
|
25
|
+
}) => Effect.Effect<WebChannel.WebChannel<any, any>, typeof MeshSchema.MessageChannelResponseNoTransferables.Type, Scope.Scope>;
|
|
26
|
+
//# sourceMappingURL=message-channel-internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-channel-internal.d.ts","sourceRoot":"","sources":["../../src/channel/message-channel-internal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAEL,MAAM,EAIN,KAAK,EAEL,KAAK,EAEL,UAAU,EACX,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAA0B,MAAM,cAAc,CAAA;AACjH,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAE/C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,YAAY,CAAA;IACtB,kDAAkD;IAClD,oBAAoB,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACnD,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzD,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACxF,4BAA4B,EAAE,CAC5B,MAAM,EAAE,OAAO,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAChD,OAAO,UAAU,CAAC,qCAAqC,CAAC,IAAI,GAAG,SAAS,CAAA;IAC7E,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CACpD;AAOD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,yJAWpC,sBAAsB,GAAG;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,6EAA6E;IAC7E,KAAK,EAAE,KAAK,CAAC,cAAc,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;CACjB,KAAG,MAAM,CAAC,MAAM,CACf,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAC/B,OAAO,UAAU,CAAC,qCAAqC,CAAC,IAAI,EAC5D,KAAK,CAAC,KAAK,CAuS2D,CAAA"}
|