@livestore/webmesh 0.3.0-dev.21 → 0.3.0-dev.23
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/dist/.tsbuildinfo +1 -1
- package/dist/channel/message-channel-internal.d.ts +3 -3
- package/dist/channel/message-channel-internal.d.ts.map +1 -1
- package/dist/channel/message-channel-internal.js +8 -8
- package/dist/channel/message-channel-internal.js.map +1 -1
- package/dist/channel/message-channel.d.ts +5 -5
- package/dist/channel/message-channel.d.ts.map +1 -1
- package/dist/channel/message-channel.js +22 -22
- 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 +9 -9
- package/dist/channel/proxy-channel.js.map +1 -1
- package/dist/common.d.ts +7 -12
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +5 -3
- package/dist/common.js.map +1 -1
- package/dist/mesh-schema.d.ts +10 -10
- package/dist/mesh-schema.d.ts.map +1 -1
- package/dist/mesh-schema.js +7 -7
- package/dist/mesh-schema.js.map +1 -1
- package/dist/mod.d.ts +2 -2
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +2 -2
- package/dist/mod.js.map +1 -1
- package/dist/node.d.ts +14 -14
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +86 -86
- package/dist/node.js.map +1 -1
- package/dist/node.test.js +25 -25
- package/dist/node.test.js.map +1 -1
- package/dist/websocket-connection.d.ts +1 -1
- package/dist/websocket-connection.d.ts.map +1 -1
- package/dist/websocket-connection.js +5 -5
- package/dist/websocket-connection.js.map +1 -1
- package/dist/websocket-edge.d.ts +51 -0
- package/dist/websocket-edge.d.ts.map +1 -0
- package/dist/websocket-edge.js +69 -0
- package/dist/websocket-edge.js.map +1 -0
- package/dist/websocket-server.d.ts +2 -2
- package/dist/websocket-server.d.ts.map +1 -1
- package/dist/websocket-server.js +6 -6
- package/dist/websocket-server.js.map +1 -1
- package/package.json +3 -3
- package/src/channel/message-channel-internal.ts +10 -10
- package/src/channel/message-channel.ts +25 -25
- package/src/channel/proxy-channel.ts +11 -11
- package/src/common.ts +8 -11
- package/src/mesh-schema.ts +9 -9
- package/src/mod.ts +2 -2
- package/src/node.test.ts +25 -25
- package/src/node.ts +102 -113
- package/src/{websocket-connection.ts → websocket-edge.ts} +15 -14
- package/src/websocket-server.ts +9 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-edge.js","sourceRoot":"","sources":["../src/websocket-edge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Scope } from '@livestore/utils/effect';
|
|
1
|
+
import type { HttpClient, Scope } from '@livestore/utils/effect';
|
|
2
2
|
import { Effect } from '@livestore/utils/effect';
|
|
3
3
|
import * as WebSocket from 'ws';
|
|
4
4
|
export declare const makeWebSocketServer: ({ relayNodeName, }: {
|
|
5
5
|
relayNodeName: string;
|
|
6
|
-
}) => Effect.Effect<WebSocket.WebSocketServer, never, Scope.Scope>;
|
|
6
|
+
}) => Effect.Effect<WebSocket.WebSocketServer, never, Scope.Scope | HttpClient.HttpClient>;
|
|
7
7
|
//# sourceMappingURL=websocket-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EAAE,MAAM,EAAY,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,SAAS,MAAM,IAAI,CAAA;AAK/B,eAAO,MAAM,mBAAmB,GAAI,oBAEjC;IACD,aAAa,EAAE,MAAM,CAAA;CACtB,KAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CA4CnF,CAAA"}
|
package/dist/websocket-server.js
CHANGED
|
@@ -2,7 +2,7 @@ import { UnexpectedError } from '@livestore/common';
|
|
|
2
2
|
import { Effect, FiberSet } from '@livestore/utils/effect';
|
|
3
3
|
import * as WebSocket from 'ws';
|
|
4
4
|
import { makeMeshNode } from './node.js';
|
|
5
|
-
import {
|
|
5
|
+
import { makeWebSocketEdge } from './websocket-edge.js';
|
|
6
6
|
export const makeWebSocketServer = ({ relayNodeName, }) => Effect.gen(function* () {
|
|
7
7
|
const server = new WebSocket.WebSocketServer({ noServer: true });
|
|
8
8
|
yield* Effect.addFinalizer(() => Effect.async((cb) => {
|
|
@@ -23,12 +23,12 @@ export const makeWebSocketServer = ({ relayNodeName, }) => Effect.gen(function*
|
|
|
23
23
|
// TODO handle node disconnects (i.e. remove respective connection)
|
|
24
24
|
server.on('connection', (socket) => {
|
|
25
25
|
Effect.gen(function* () {
|
|
26
|
-
const { webChannel, from } = yield*
|
|
27
|
-
yield* node.
|
|
28
|
-
yield* Effect.log(`WS Relay ${relayNodeName}: added
|
|
26
|
+
const { webChannel, from } = yield* makeWebSocketEdge(socket, { _tag: 'relay' });
|
|
27
|
+
yield* node.addEdge({ target: from, edgeChannel: webChannel, replaceIfExists: true });
|
|
28
|
+
yield* Effect.log(`WS Relay ${relayNodeName}: added edge from '${from}'`);
|
|
29
29
|
socket.addEventListener('close', () => Effect.gen(function* () {
|
|
30
|
-
yield* node.
|
|
31
|
-
yield* Effect.log(`WS Relay ${relayNodeName}: removed
|
|
30
|
+
yield* node.removeEdge(from);
|
|
31
|
+
yield* Effect.log(`WS Relay ${relayNodeName}: removed edge from '${from}'`);
|
|
32
32
|
}).pipe(Effect.provide(runtime), Effect.tapCauseLogPretty, Effect.runFork));
|
|
33
33
|
yield* Effect.never;
|
|
34
34
|
}).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.provide(runtime), FiberSet.run(fiberSet), Effect.runFork);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,SAAS,MAAM,IAAI,CAAA;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/webmesh",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.23",
|
|
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/
|
|
20
|
-
"@livestore/
|
|
19
|
+
"@livestore/common": "0.3.0-dev.23",
|
|
20
|
+
"@livestore/utils": "0.3.0-dev.23"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/ws": "^8.18.0",
|
|
@@ -20,11 +20,11 @@ export interface MakeMessageChannelArgs {
|
|
|
20
20
|
nodeName: MeshNodeName
|
|
21
21
|
/** Queue of incoming messages for this channel */
|
|
22
22
|
incomingPacketsQueue: Queue.Queue<MessageQueueItem>
|
|
23
|
-
|
|
23
|
+
newEdgeAvailablePubSub: PubSub.PubSub<MeshNodeName>
|
|
24
24
|
channelName: ChannelName
|
|
25
25
|
target: MeshNodeName
|
|
26
26
|
sendPacket: (packet: typeof MeshSchema.MessageChannelPacket.Type) => Effect.Effect<void>
|
|
27
|
-
|
|
27
|
+
checkTransferableEdges: (
|
|
28
28
|
packet: typeof MeshSchema.MessageChannelPacket.Type,
|
|
29
29
|
) => typeof MeshSchema.MessageChannelResponseNoTransferables.Type | undefined
|
|
30
30
|
schema: WebChannel.OutputSchema<any, any, any, any>
|
|
@@ -43,7 +43,7 @@ export const makeMessageChannelInternal = ({
|
|
|
43
43
|
nodeName,
|
|
44
44
|
incomingPacketsQueue,
|
|
45
45
|
target,
|
|
46
|
-
|
|
46
|
+
checkTransferableEdges,
|
|
47
47
|
channelName,
|
|
48
48
|
schema: schema_,
|
|
49
49
|
sendPacket,
|
|
@@ -203,7 +203,7 @@ export const makeMessageChannelInternal = ({
|
|
|
203
203
|
const mc = new MessageChannel()
|
|
204
204
|
|
|
205
205
|
// We're using a message channel with acks here to make sure messages are not lost
|
|
206
|
-
// which might happen during re-
|
|
206
|
+
// which might happen during re-edge scenarios.
|
|
207
207
|
// Also we need to eagerly start listening since we're using the channel "ourselves"
|
|
208
208
|
// for the initial ping-pong sequence.
|
|
209
209
|
const channel = yield* WebChannel.messagePortChannelWithAck({
|
|
@@ -323,7 +323,7 @@ export const makeMessageChannelInternal = ({
|
|
|
323
323
|
return shouldNeverHappen(`Expected channel to be in Initial state, but was in ${channelState._tag} state`)
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
const
|
|
326
|
+
const edgeRequest = Effect.gen(function* () {
|
|
327
327
|
const packet = MeshSchema.MessageChannelRequest.make({
|
|
328
328
|
source: nodeName,
|
|
329
329
|
sourceId,
|
|
@@ -336,19 +336,19 @@ export const makeMessageChannelInternal = ({
|
|
|
336
336
|
|
|
337
337
|
channelStateRef.current = { _tag: 'RequestSent', reqPacketId: packet.id }
|
|
338
338
|
|
|
339
|
-
// yield* Effect.log(`${nodeName}→${channelName}→${target}:
|
|
339
|
+
// yield* Effect.log(`${nodeName}→${channelName}→${target}:edgeRequest [${channelVersion}]`)
|
|
340
340
|
|
|
341
|
-
const noTransferableResponse =
|
|
341
|
+
const noTransferableResponse = checkTransferableEdges(packet)
|
|
342
342
|
if (noTransferableResponse !== undefined) {
|
|
343
|
-
yield* Effect.spanEvent(`No transferable
|
|
343
|
+
yield* Effect.spanEvent(`No transferable edges found for ${packet.source}→${packet.target}`)
|
|
344
344
|
return yield* Effect.fail(noTransferableResponse)
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
yield* sendPacket(packet)
|
|
348
|
-
span?.addEvent(`initial
|
|
348
|
+
span?.addEvent(`initial edge request sent (${packet.id})`)
|
|
349
349
|
})
|
|
350
350
|
|
|
351
|
-
yield*
|
|
351
|
+
yield* edgeRequest
|
|
352
352
|
|
|
353
353
|
const channel = yield* deferred
|
|
354
354
|
|
|
@@ -20,7 +20,7 @@ import { makeMessageChannelInternal } from './message-channel-internal.js'
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Behaviour:
|
|
23
|
-
* - Waits until there is an initial
|
|
23
|
+
* - Waits until there is an initial edge
|
|
24
24
|
* - Automatically reconnects on disconnect
|
|
25
25
|
*
|
|
26
26
|
* Implementation notes:
|
|
@@ -28,16 +28,16 @@ import { makeMessageChannelInternal } from './message-channel-internal.js'
|
|
|
28
28
|
* - The wrapper channel is responsible for:
|
|
29
29
|
* - Forwarding send/listen messages to the internal channel (via a queue)
|
|
30
30
|
* - Establishing the initial channel and reconnecting on disconnect
|
|
31
|
-
* - Listening for new
|
|
32
|
-
* - The wrapper channel maintains a
|
|
31
|
+
* - Listening for new edges as a hint to reconnect if not already connected
|
|
32
|
+
* - The wrapper channel maintains a edge counter which is used as the channel version
|
|
33
33
|
*
|
|
34
34
|
* If needed we can also implement further functionality (like heartbeat) in this wrapper channel.
|
|
35
35
|
*/
|
|
36
36
|
export const makeMessageChannel = ({
|
|
37
37
|
schema,
|
|
38
|
-
|
|
38
|
+
newEdgeAvailablePubSub,
|
|
39
39
|
channelName,
|
|
40
|
-
|
|
40
|
+
checkTransferableEdges,
|
|
41
41
|
nodeName,
|
|
42
42
|
incomingPacketsQueue,
|
|
43
43
|
target,
|
|
@@ -51,7 +51,7 @@ export const makeMessageChannel = ({
|
|
|
51
51
|
const listenQueue = yield* Queue.unbounded<any>()
|
|
52
52
|
const sendQueue = yield* TQueue.unbounded<[msg: any, deferred: Deferred.Deferred<void>]>()
|
|
53
53
|
|
|
54
|
-
const
|
|
54
|
+
const initialEdgeDeferred = yield* Deferred.make<void>()
|
|
55
55
|
|
|
56
56
|
const debugInfo = {
|
|
57
57
|
pendingSends: 0,
|
|
@@ -81,24 +81,24 @@ export const makeMessageChannel = ({
|
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Expected concurrency behaviour:
|
|
84
|
-
* - We're concurrently running the
|
|
84
|
+
* - We're concurrently running the edge setup and the waitForNewEdgeFiber
|
|
85
85
|
* - Happy path:
|
|
86
|
-
* - The
|
|
86
|
+
* - The edge setup succeeds and we can interrupt the waitForNewEdgeFiber
|
|
87
87
|
* - Tricky paths:
|
|
88
|
-
* - While a
|
|
89
|
-
* - If the
|
|
90
|
-
* we want to wait for a new
|
|
88
|
+
* - While a edge is still being setup, we want to re-try when there is a new edge
|
|
89
|
+
* - If the edge setup returns a `MessageChannelResponseNoTransferables` error,
|
|
90
|
+
* we want to wait for a new edge and then re-try
|
|
91
91
|
* - Further notes:
|
|
92
|
-
* - If the parent scope closes, we want to also interrupt both the
|
|
93
|
-
* - We're creating a separate scope for each
|
|
92
|
+
* - If the parent scope closes, we want to also interrupt both the edge setup and the waitForNewEdgeFiber
|
|
93
|
+
* - We're creating a separate scope for each edge attempt, which
|
|
94
94
|
* - we'll use to fork the message channel in which allows us to interrupt it later
|
|
95
95
|
* - We need to make sure that "interruption" isn't "bubbling out"
|
|
96
96
|
*/
|
|
97
|
-
const
|
|
98
|
-
Stream.tap((
|
|
97
|
+
const waitForNewEdgeFiber = yield* Stream.fromPubSub(newEdgeAvailablePubSub).pipe(
|
|
98
|
+
Stream.tap((edgeName) => Effect.spanEvent(`new-conn:${edgeName}`)),
|
|
99
99
|
Stream.take(1),
|
|
100
100
|
Stream.runDrain,
|
|
101
|
-
Effect.as('new-
|
|
101
|
+
Effect.as('new-edge' as const),
|
|
102
102
|
Effect.fork,
|
|
103
103
|
)
|
|
104
104
|
|
|
@@ -107,11 +107,11 @@ export const makeMessageChannel = ({
|
|
|
107
107
|
sourceId,
|
|
108
108
|
incomingPacketsQueue,
|
|
109
109
|
target,
|
|
110
|
-
|
|
110
|
+
checkTransferableEdges,
|
|
111
111
|
channelName,
|
|
112
112
|
schema,
|
|
113
113
|
channelVersion,
|
|
114
|
-
|
|
114
|
+
newEdgeAvailablePubSub,
|
|
115
115
|
sendPacket,
|
|
116
116
|
scope: makeMessageChannelScope,
|
|
117
117
|
}).pipe(
|
|
@@ -122,10 +122,10 @@ export const makeMessageChannel = ({
|
|
|
122
122
|
Effect.withUnhandledErrorLogLevel(Option.none()),
|
|
123
123
|
)
|
|
124
124
|
|
|
125
|
-
const raceResult = yield* Effect.raceFirst(makeChannel,
|
|
125
|
+
const raceResult = yield* Effect.raceFirst(makeChannel, waitForNewEdgeFiber.pipe(Effect.disconnect))
|
|
126
126
|
|
|
127
|
-
if (raceResult === 'new-
|
|
128
|
-
yield* Scope.close(makeMessageChannelScope, Exit.fail('new-
|
|
127
|
+
if (raceResult === 'new-edge') {
|
|
128
|
+
yield* Scope.close(makeMessageChannelScope, Exit.fail('new-edge'))
|
|
129
129
|
// We'll try again
|
|
130
130
|
} else {
|
|
131
131
|
const channelExit = yield* raceResult.pipe(Effect.exit)
|
|
@@ -136,8 +136,8 @@ export const makeMessageChannel = ({
|
|
|
136
136
|
Cause.isFailType(channelExit.cause) &&
|
|
137
137
|
Schema.is(WebmeshSchema.MessageChannelResponseNoTransferables)(channelExit.cause.error)
|
|
138
138
|
) {
|
|
139
|
-
// Only retry when there is a new
|
|
140
|
-
yield*
|
|
139
|
+
// Only retry when there is a new edge available
|
|
140
|
+
yield* waitForNewEdgeFiber.pipe(Effect.exit)
|
|
141
141
|
}
|
|
142
142
|
} else {
|
|
143
143
|
const channel = channelExit.value
|
|
@@ -155,7 +155,7 @@ export const makeMessageChannel = ({
|
|
|
155
155
|
debugInfo.isConnected = true
|
|
156
156
|
debugInfo.innerChannelRef.current = channel
|
|
157
157
|
|
|
158
|
-
yield* Deferred.succeed(
|
|
158
|
+
yield* Deferred.succeed(initialEdgeDeferred, void 0)
|
|
159
159
|
|
|
160
160
|
// We'll now forward all incoming messages to the listen queue
|
|
161
161
|
yield* channel.listen.pipe(
|
|
@@ -228,7 +228,7 @@ export const makeMessageChannel = ({
|
|
|
228
228
|
|
|
229
229
|
return {
|
|
230
230
|
webChannel: webChannel as WebChannel.WebChannel<any, any>,
|
|
231
|
-
|
|
231
|
+
initialEdgeDeferred,
|
|
232
232
|
}
|
|
233
233
|
}),
|
|
234
234
|
)
|
|
@@ -29,7 +29,7 @@ import * as MeshSchema from '../mesh-schema.js'
|
|
|
29
29
|
interface MakeProxyChannelArgs {
|
|
30
30
|
queue: Queue.Queue<ProxyQueueItem>
|
|
31
31
|
nodeName: MeshNodeName
|
|
32
|
-
|
|
32
|
+
newEdgeAvailablePubSub: PubSub.PubSub<MeshNodeName>
|
|
33
33
|
sendPacket: (packet: typeof MeshSchema.ProxyChannelPacket.Type) => Effect.Effect<void>
|
|
34
34
|
channelName: ChannelName
|
|
35
35
|
target: MeshNodeName
|
|
@@ -42,7 +42,7 @@ interface MakeProxyChannelArgs {
|
|
|
42
42
|
export const makeProxyChannel = ({
|
|
43
43
|
queue,
|
|
44
44
|
nodeName,
|
|
45
|
-
|
|
45
|
+
newEdgeAvailablePubSub,
|
|
46
46
|
sendPacket,
|
|
47
47
|
target,
|
|
48
48
|
channelName,
|
|
@@ -96,7 +96,7 @@ export const makeProxyChannel = ({
|
|
|
96
96
|
|
|
97
97
|
const setStateToEstablished = (channelId: string) =>
|
|
98
98
|
Effect.gen(function* () {
|
|
99
|
-
// TODO avoid "double" `Connected` events (we might call `setStateToEstablished` twice during initial
|
|
99
|
+
// TODO avoid "double" `Connected` events (we might call `setStateToEstablished` twice during initial edge)
|
|
100
100
|
yield* Effect.spanEvent(`Connected (${channelId})`).pipe(Effect.withParentSpan(channelSpan))
|
|
101
101
|
channelStateRef.current = {
|
|
102
102
|
_tag: 'Established',
|
|
@@ -109,7 +109,7 @@ export const makeProxyChannel = ({
|
|
|
109
109
|
debugInfo.isConnected = true
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
-
const
|
|
112
|
+
const edgeRequest = Effect.suspend(() =>
|
|
113
113
|
sendPacket(
|
|
114
114
|
MeshSchema.ProxyChannelRequest.make({ channelName, hops: [], source: nodeName, target, channelIdCandidate }),
|
|
115
115
|
),
|
|
@@ -137,9 +137,9 @@ export const makeProxyChannel = ({
|
|
|
137
137
|
debugInfo.isConnected = false
|
|
138
138
|
debugInfo.connectCounter++
|
|
139
139
|
|
|
140
|
-
// If we're already connected, we need to re-establish the
|
|
140
|
+
// If we're already connected, we need to re-establish the edge
|
|
141
141
|
if (channelState._tag === 'Established' && channelState.combinedChannelId !== combinedChannelId) {
|
|
142
|
-
yield*
|
|
142
|
+
yield* edgeRequest
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -254,7 +254,7 @@ export const makeProxyChannel = ({
|
|
|
254
254
|
const ackMap = new Map<string, Deferred.Deferred<void, never>>()
|
|
255
255
|
|
|
256
256
|
// check if already established via incoming `ProxyChannelRequest` from other side
|
|
257
|
-
// which indicates we already have a
|
|
257
|
+
// which indicates we already have a edge to the target node
|
|
258
258
|
// const channelState = channelStateRef.current
|
|
259
259
|
{
|
|
260
260
|
if (channelStateRef.current._tag !== 'Initial') {
|
|
@@ -263,17 +263,17 @@ export const makeProxyChannel = ({
|
|
|
263
263
|
|
|
264
264
|
channelStateRef.current = { _tag: 'Pending', initiatedVia: 'outgoing-request' }
|
|
265
265
|
|
|
266
|
-
yield*
|
|
266
|
+
yield* edgeRequest
|
|
267
267
|
|
|
268
|
-
const
|
|
269
|
-
Stream.tap(() =>
|
|
268
|
+
const retryOnNewEdgeFiber = yield* Stream.fromPubSub(newEdgeAvailablePubSub).pipe(
|
|
269
|
+
Stream.tap(() => edgeRequest),
|
|
270
270
|
Stream.runDrain,
|
|
271
271
|
Effect.forkScoped,
|
|
272
272
|
)
|
|
273
273
|
|
|
274
274
|
const { combinedChannelId: channelId } = yield* waitForEstablished
|
|
275
275
|
|
|
276
|
-
yield* Fiber.interrupt(
|
|
276
|
+
yield* Fiber.interrupt(retryOnNewEdgeFiber)
|
|
277
277
|
|
|
278
278
|
yield* setStateToEstablished(channelId)
|
|
279
279
|
}
|
package/src/common.ts
CHANGED
|
@@ -18,17 +18,14 @@ export type ChannelName = string
|
|
|
18
18
|
export type ChannelKey = `target:${MeshNodeName}, channelName:${ChannelName}`
|
|
19
19
|
|
|
20
20
|
// TODO actually use this to avoid timeouts in certain cases
|
|
21
|
-
export class NoConnectionRouteSignal extends Schema.TaggedError<NoConnectionRouteSignal>()(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) {}
|
|
25
|
-
|
|
26
|
-
export class
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
target: Schema.String,
|
|
30
|
-
},
|
|
31
|
-
) {}
|
|
21
|
+
// export class NoConnectionRouteSignal extends Schema.TaggedError<NoConnectionRouteSignal>()(
|
|
22
|
+
// 'NoConnectionRouteSignal',
|
|
23
|
+
// {},
|
|
24
|
+
// ) {}
|
|
25
|
+
|
|
26
|
+
export class EdgeAlreadyExistsError extends Schema.TaggedError<EdgeAlreadyExistsError>()('EdgeAlreadyExistsError', {
|
|
27
|
+
target: Schema.String,
|
|
28
|
+
}) {}
|
|
32
29
|
|
|
33
30
|
export const packetAsOtelAttributes = (packet: typeof Packet.Type) => ({
|
|
34
31
|
packetId: packet.id,
|
package/src/mesh-schema.ts
CHANGED
|
@@ -17,7 +17,7 @@ const defaultPacketFields = {
|
|
|
17
17
|
const remainingHopsUndefined = Schema.Undefined.pipe(Schema.optional)
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Needs to go through already existing MessageChannel
|
|
20
|
+
* Needs to go through already existing MessageChannel edges, times out otherwise
|
|
21
21
|
*
|
|
22
22
|
* Can't yet contain the `port` because the request might be duplicated while forwarding to multiple nodes.
|
|
23
23
|
* We need a clear path back to the sender to avoid this, thus we respond with a separate
|
|
@@ -83,16 +83,16 @@ export class ProxyChannelPayloadAck extends Schema.TaggedStruct('ProxyChannelPay
|
|
|
83
83
|
}) {}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* Broadcast to all nodes when a new
|
|
86
|
+
* Broadcast to all nodes when a new edge is added.
|
|
87
87
|
* Mostly used for auto-reconnect purposes.
|
|
88
88
|
*/
|
|
89
|
-
export class
|
|
89
|
+
export class NetworkEdgeAdded extends Schema.TaggedStruct('NetworkEdgeAdded', {
|
|
90
90
|
id,
|
|
91
91
|
source: Schema.String,
|
|
92
92
|
target: Schema.String,
|
|
93
93
|
}) {}
|
|
94
94
|
|
|
95
|
-
export class
|
|
95
|
+
export class NetworkTopologyRequest extends Schema.TaggedStruct('NetworkTopologyRequest', {
|
|
96
96
|
id,
|
|
97
97
|
hops: Schema.Array(Schema.String),
|
|
98
98
|
/** Always fixed to who requested the topology */
|
|
@@ -100,12 +100,12 @@ export class NetworkConnectionTopologyRequest extends Schema.TaggedStruct('Netwo
|
|
|
100
100
|
target: Schema.Literal('-'),
|
|
101
101
|
}) {}
|
|
102
102
|
|
|
103
|
-
export class
|
|
103
|
+
export class NetworkTopologyResponse extends Schema.TaggedStruct('NetworkTopologyResponse', {
|
|
104
104
|
id,
|
|
105
105
|
reqId: Schema.String,
|
|
106
106
|
remainingHops: Schema.Array(Schema.String),
|
|
107
107
|
nodeName: Schema.String,
|
|
108
|
-
|
|
108
|
+
edges: Schema.Array(Schema.String),
|
|
109
109
|
/** Always fixed to who requested the topology */
|
|
110
110
|
source: Schema.String,
|
|
111
111
|
target: Schema.Literal('-'),
|
|
@@ -140,9 +140,9 @@ export class ProxyChannelPacket extends Schema.Union(
|
|
|
140
140
|
export class Packet extends Schema.Union(
|
|
141
141
|
MessageChannelPacket,
|
|
142
142
|
ProxyChannelPacket,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
NetworkEdgeAdded,
|
|
144
|
+
NetworkTopologyRequest,
|
|
145
|
+
NetworkTopologyResponse,
|
|
146
146
|
BroadcastChannelPacket,
|
|
147
147
|
) {}
|
|
148
148
|
|
package/src/mod.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './websocket-
|
|
1
|
+
export * from './websocket-edge.js'
|
|
2
2
|
export * from './node.js'
|
|
3
3
|
export * as WebmeshSchema from './mesh-schema.js'
|
|
4
|
-
export {
|
|
4
|
+
export { EdgeAlreadyExistsError } from './common.js'
|
package/src/node.test.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { makeMeshNode } from './node.js'
|
|
|
24
24
|
|
|
25
25
|
// TODO test cases where in-between node only comes online later
|
|
26
26
|
// TODO test cases where other side tries to reconnect
|
|
27
|
-
// TODO test combination of
|
|
27
|
+
// TODO test combination of channel types (message, proxy)
|
|
28
28
|
// TODO test "diamond shape" topology (A <> B1, A <> B2, B1 <> C, B2 <> C)
|
|
29
29
|
// TODO test cases where multiple entities try to claim to be the same channel end (e.g. A,B,B)
|
|
30
30
|
// TODO write tests with worker threads
|
|
@@ -37,14 +37,14 @@ const connectNodesViaMessageChannel = (nodeA: MeshNode, nodeB: MeshNode, options
|
|
|
37
37
|
const meshChannelAToB = yield* WebChannel.messagePortChannel({ port: mc.port1, schema: Packet })
|
|
38
38
|
const meshChannelBToA = yield* WebChannel.messagePortChannel({ port: mc.port2, schema: Packet })
|
|
39
39
|
|
|
40
|
-
yield* nodeA.
|
|
40
|
+
yield* nodeA.addEdge({
|
|
41
41
|
target: nodeB.nodeName,
|
|
42
|
-
|
|
42
|
+
edgeChannel: meshChannelAToB,
|
|
43
43
|
replaceIfExists: options?.replaceIfExists,
|
|
44
44
|
})
|
|
45
|
-
yield* nodeB.
|
|
45
|
+
yield* nodeB.addEdge({
|
|
46
46
|
target: nodeA.nodeName,
|
|
47
|
-
|
|
47
|
+
edgeChannel: meshChannelBToA,
|
|
48
48
|
replaceIfExists: options?.replaceIfExists,
|
|
49
49
|
})
|
|
50
50
|
}).pipe(Effect.withSpan(`connectNodesViaMessageChannel:${nodeA.nodeName}↔${nodeB.nodeName}`))
|
|
@@ -62,14 +62,14 @@ const connectNodesViaBroadcastChannel = (nodeA: MeshNode, nodeB: MeshNode, optio
|
|
|
62
62
|
schema: Packet,
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
-
yield* nodeA.
|
|
65
|
+
yield* nodeA.addEdge({
|
|
66
66
|
target: nodeB.nodeName,
|
|
67
|
-
|
|
67
|
+
edgeChannel: broadcastWebChannelA,
|
|
68
68
|
replaceIfExists: options?.replaceIfExists,
|
|
69
69
|
})
|
|
70
|
-
yield* nodeB.
|
|
70
|
+
yield* nodeB.addEdge({
|
|
71
71
|
target: nodeA.nodeName,
|
|
72
|
-
|
|
72
|
+
edgeChannel: broadcastWebChannelB,
|
|
73
73
|
replaceIfExists: options?.replaceIfExists,
|
|
74
74
|
})
|
|
75
75
|
}).pipe(Effect.withSpan(`connectNodesViaBroadcastChannel:${nodeA.nodeName}↔${nodeB.nodeName}`))
|
|
@@ -239,7 +239,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
239
239
|
|
|
240
240
|
const { mode, connectNodes } = fromChannelType(channelType)
|
|
241
241
|
|
|
242
|
-
// TODO also optionally delay the
|
|
242
|
+
// TODO also optionally delay the edge
|
|
243
243
|
yield* connectNodes(nodeA, nodeB)
|
|
244
244
|
|
|
245
245
|
const waitForBToBeOffline =
|
|
@@ -350,16 +350,16 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
350
350
|
// test: Shrunk 0 time(s)
|
|
351
351
|
// test: Got AssertionError: expected { _tag: 'MessageChannelPing' } to deeply equal { message: 'A1' }
|
|
352
352
|
// test: at next (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/webmesh/src/node.test.ts:376:59)
|
|
353
|
-
// test: at prop tests:replace
|
|
353
|
+
// test: at prop tests:replace edge while keeping the channel:channelType=messagechannel nodeNames=A,B (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/webmesh/src/node.test.ts:801:14)
|
|
354
354
|
// test: Hint: Enable verbose mode in order to have the list of all failing values encountered during the run
|
|
355
355
|
// test: ✓ webmesh node > A <> B > prop tests > TODO improve latency > concurrent messages 2110ms
|
|
356
356
|
// test: ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯
|
|
357
|
-
// test: FAIL src/node.test.ts > webmesh node > A <> B > prop tests > replace
|
|
357
|
+
// test: FAIL src/node.test.ts > webmesh node > A <> B > prop tests > replace edge while keeping the channel
|
|
358
358
|
// test: Error: Property failed after 2 tests
|
|
359
359
|
// test: { seed: -964670352, path: "1", endOnFailure: true }
|
|
360
360
|
// test: Counterexample: ["messagechannel",["A","B"]]
|
|
361
361
|
Vitest.scopedLive.prop(
|
|
362
|
-
'replace
|
|
362
|
+
'replace edge while keeping the channel',
|
|
363
363
|
[ChannelTypeWithoutMessageChannelProxy, NodeNames],
|
|
364
364
|
([channelType, nodeNames], test) =>
|
|
365
365
|
Effect.gen(function* () {
|
|
@@ -372,7 +372,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
372
372
|
|
|
373
373
|
yield* connectNodes(nodeX, nodeY)
|
|
374
374
|
|
|
375
|
-
const
|
|
375
|
+
const waitForEdgeReplacement = yield* Deferred.make<void>()
|
|
376
376
|
|
|
377
377
|
const nodeXCode = Effect.gen(function* () {
|
|
378
378
|
const channelXToY = yield* createChannel(nodeX, nodeLabel.y, { mode })
|
|
@@ -380,7 +380,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
380
380
|
yield* channelXToY.send({ message: `${nodeLabel.x}1` })
|
|
381
381
|
expect(yield* getFirstMessage(channelXToY)).toEqual({ message: `${nodeLabel.y}1` })
|
|
382
382
|
|
|
383
|
-
yield*
|
|
383
|
+
yield* waitForEdgeReplacement
|
|
384
384
|
|
|
385
385
|
yield* channelXToY.send({ message: `${nodeLabel.x}2` })
|
|
386
386
|
expect(yield* getFirstMessage(channelXToY)).toEqual({ message: `${nodeLabel.y}2` })
|
|
@@ -392,11 +392,11 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
392
392
|
yield* channelYToX.send({ message: `${nodeLabel.y}1` })
|
|
393
393
|
expect(yield* getFirstMessage(channelYToX)).toEqual({ message: `${nodeLabel.x}1` })
|
|
394
394
|
|
|
395
|
-
// Switch out
|
|
396
|
-
yield* nodeX.
|
|
397
|
-
yield* nodeY.
|
|
395
|
+
// Switch out edge while keeping the channel
|
|
396
|
+
yield* nodeX.removeEdge(nodeLabel.y)
|
|
397
|
+
yield* nodeY.removeEdge(nodeLabel.x)
|
|
398
398
|
yield* connectNodes(nodeX, nodeY)
|
|
399
|
-
yield* Deferred.succeed(
|
|
399
|
+
yield* Deferred.succeed(waitForEdgeReplacement, void 0)
|
|
400
400
|
|
|
401
401
|
yield* channelYToX.send({ message: `${nodeLabel.y}2` })
|
|
402
402
|
expect(yield* getFirstMessage(channelYToX)).toEqual({ message: `${nodeLabel.x}2` })
|
|
@@ -472,7 +472,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
472
472
|
})
|
|
473
473
|
|
|
474
474
|
Vitest.describe('message channel specific tests', () => {
|
|
475
|
-
Vitest.scopedLive('differing initial
|
|
475
|
+
Vitest.scopedLive('differing initial edge counter', (test) =>
|
|
476
476
|
Effect.gen(function* () {
|
|
477
477
|
const nodeA = yield* makeMeshNode('A')
|
|
478
478
|
const nodeB = yield* makeMeshNode('B')
|
|
@@ -533,7 +533,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
533
533
|
}).pipe(withCtx(test)),
|
|
534
534
|
)
|
|
535
535
|
|
|
536
|
-
Vitest.scopedLive('broadcast
|
|
536
|
+
Vitest.scopedLive('broadcast edge with message channel', (test) =>
|
|
537
537
|
Effect.gen(function* () {
|
|
538
538
|
const nodeA = yield* makeMeshNode('A')
|
|
539
539
|
const nodeB = yield* makeMeshNode('B')
|
|
@@ -577,7 +577,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
577
577
|
}).pipe(withCtx(test)),
|
|
578
578
|
)
|
|
579
579
|
|
|
580
|
-
Vitest.scopedLive('should work - delayed
|
|
580
|
+
Vitest.scopedLive('should work - delayed edge', (test) =>
|
|
581
581
|
Effect.gen(function* () {
|
|
582
582
|
const nodeA = yield* makeMeshNode('A')
|
|
583
583
|
const nodeB = yield* makeMeshNode('B')
|
|
@@ -637,7 +637,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
637
637
|
}).pipe(withCtx(test)),
|
|
638
638
|
)
|
|
639
639
|
|
|
640
|
-
Vitest.scopedLive('should fail with timeout due to missing
|
|
640
|
+
Vitest.scopedLive('should fail with timeout due to missing edge', (test) =>
|
|
641
641
|
Effect.gen(function* () {
|
|
642
642
|
const nodeA = yield* makeMeshNode('A')
|
|
643
643
|
const nodeB = yield* makeMeshNode('B')
|
|
@@ -805,7 +805,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
805
805
|
)
|
|
806
806
|
})
|
|
807
807
|
|
|
808
|
-
Vitest.describe('mixture of messagechannel and proxy connections', () => {
|
|
808
|
+
Vitest.describe('mixture of messagechannel and proxy edge connections', () => {
|
|
809
809
|
// TODO test case to better guard against case where side A tries to create a proxy channel to B
|
|
810
810
|
// and side B tries to create a messagechannel to A
|
|
811
811
|
Vitest.scopedLive('should work for proxy channels', (test) =>
|
|
@@ -816,7 +816,7 @@ Vitest.describe('webmesh node', { timeout: testTimeout }, () => {
|
|
|
816
816
|
yield* connectNodesViaMessageChannel(nodeB, nodeA)
|
|
817
817
|
const err = yield* connectNodesViaBroadcastChannel(nodeA, nodeB).pipe(Effect.flip)
|
|
818
818
|
|
|
819
|
-
expect(err._tag).toBe('
|
|
819
|
+
expect(err._tag).toBe('EdgeAlreadyExistsError')
|
|
820
820
|
}).pipe(withCtx(test)),
|
|
821
821
|
)
|
|
822
822
|
|