@dxos/edge-client 0.8.2-main.85fa0e5 → 0.8.2-main.f11618f
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/lib/browser/{chunk-CFIVYHE6.mjs → chunk-5DDWS5EC.mjs} +32 -37
- package/dist/lib/browser/chunk-5DDWS5EC.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3 -9
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/{chunk-FQM4JFRT.cjs → chunk-CNAHGYSS.cjs} +39 -46
- package/dist/lib/node/chunk-CNAHGYSS.cjs.map +7 -0
- package/dist/lib/node/index.cjs +10 -16
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +5 -5
- package/dist/lib/node-esm/{chunk-APWFVC3U.mjs → chunk-O4TFZRSP.mjs} +32 -37
- package/dist/lib/node-esm/chunk-O4TFZRSP.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +3 -9
- package/dist/lib/node-esm/index.mjs.map +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +1 -1
- package/dist/types/src/edge-ws-connection.d.ts +0 -1
- package/dist/types/src/edge-ws-connection.d.ts.map +1 -1
- package/dist/types/src/edge-ws-muxer.d.ts +7 -16
- package/dist/types/src/edge-ws-muxer.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/edge-ws-connection.ts +3 -3
- package/src/edge-ws-muxer.ts +28 -43
- package/src/index.ts +0 -1
- package/dist/lib/browser/chunk-CFIVYHE6.mjs.map +0 -7
- package/dist/lib/node/chunk-FQM4JFRT.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-APWFVC3U.mjs.map +0 -7
package/src/edge-ws-muxer.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
|
+
import WebSocket from 'isomorphic-ws';
|
|
4
5
|
|
|
5
6
|
import { Trigger } from '@dxos/async';
|
|
6
7
|
import { log } from '@dxos/log';
|
|
@@ -24,23 +25,22 @@ const FLAG_SEGMENT_SEQ = 1;
|
|
|
24
25
|
const FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
|
-
* https://developers.cloudflare.com/durable-objects/platform/limits/
|
|
28
|
+
* 1MB websocket message limit: https://developers.cloudflare.com/durable-objects/platform/limits/
|
|
28
29
|
*/
|
|
29
|
-
export const
|
|
30
|
-
export const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB
|
|
30
|
+
export const CLOUDFLARE_MESSAGE_LENGTH_LIMIT = 1024 * 1024;
|
|
31
31
|
|
|
32
32
|
const MAX_CHUNK_LENGTH = 16384;
|
|
33
|
-
const MAX_BUFFERED_AMOUNT =
|
|
33
|
+
const MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_LENGTH_LIMIT;
|
|
34
34
|
const BUFFER_FULL_BACKOFF_TIMEOUT = 100;
|
|
35
35
|
|
|
36
36
|
export class WebSocketMuxer {
|
|
37
|
-
private readonly
|
|
38
|
-
private readonly
|
|
39
|
-
private readonly
|
|
37
|
+
private readonly _incomingMessageAccumulator = new Map<number, Buffer[]>();
|
|
38
|
+
private readonly _outgoingMessageChunks = new Map<number, MessageChunk[]>();
|
|
39
|
+
private readonly _serviceToChannel = new Map<string, number>();
|
|
40
40
|
|
|
41
41
|
private _sendTimeout: any | undefined;
|
|
42
42
|
|
|
43
|
-
constructor(private readonly _ws:
|
|
43
|
+
constructor(private readonly _ws: WebSocket) {}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Resolves when all the message chunks get enqueued for sending.
|
|
@@ -48,15 +48,11 @@ export class WebSocketMuxer {
|
|
|
48
48
|
public async send(message: Message): Promise<void> {
|
|
49
49
|
const binary = buf.toBinary(MessageSchema, message);
|
|
50
50
|
const channelId = this._resolveChannel(message);
|
|
51
|
-
if (
|
|
52
|
-
(
|
|
53
|
-
binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES
|
|
54
|
-
) {
|
|
55
|
-
log.error('Large message dropped', {
|
|
51
|
+
if (channelId == null && binary.length > CLOUDFLARE_MESSAGE_LENGTH_LIMIT) {
|
|
52
|
+
log.error('Large message dropped because channel resolution failed.', {
|
|
56
53
|
byteLength: binary.byteLength,
|
|
57
54
|
serviceId: message.serviceId,
|
|
58
55
|
payload: protocol.getPayloadType(message),
|
|
59
|
-
channelId,
|
|
60
56
|
});
|
|
61
57
|
return;
|
|
62
58
|
}
|
|
@@ -81,11 +77,11 @@ export class WebSocketMuxer {
|
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
const queuedMessages = this.
|
|
80
|
+
const queuedMessages = this._outgoingMessageChunks.get(channelId);
|
|
85
81
|
if (queuedMessages) {
|
|
86
82
|
queuedMessages.push(...messageChunks);
|
|
87
83
|
} else {
|
|
88
|
-
this.
|
|
84
|
+
this._outgoingMessageChunks.set(channelId, messageChunks);
|
|
89
85
|
}
|
|
90
86
|
|
|
91
87
|
this._sendChunkedMessages();
|
|
@@ -99,12 +95,12 @@ export class WebSocketMuxer {
|
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
const [flags, channelId, ...payload] = data;
|
|
102
|
-
let chunkAccumulator = this.
|
|
98
|
+
let chunkAccumulator = this._incomingMessageAccumulator.get(channelId);
|
|
103
99
|
if (chunkAccumulator) {
|
|
104
100
|
chunkAccumulator.push(Buffer.from(payload));
|
|
105
101
|
} else {
|
|
106
102
|
chunkAccumulator = [Buffer.from(payload)];
|
|
107
|
-
this.
|
|
103
|
+
this._incomingMessageAccumulator.set(channelId, chunkAccumulator);
|
|
108
104
|
}
|
|
109
105
|
|
|
110
106
|
if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {
|
|
@@ -112,7 +108,7 @@ export class WebSocketMuxer {
|
|
|
112
108
|
}
|
|
113
109
|
|
|
114
110
|
const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));
|
|
115
|
-
this.
|
|
111
|
+
this._incomingMessageAccumulator.delete(channelId);
|
|
116
112
|
return message;
|
|
117
113
|
}
|
|
118
114
|
|
|
@@ -121,12 +117,12 @@ export class WebSocketMuxer {
|
|
|
121
117
|
clearTimeout(this._sendTimeout);
|
|
122
118
|
this._sendTimeout = undefined;
|
|
123
119
|
}
|
|
124
|
-
for (const channelChunks of this.
|
|
120
|
+
for (const channelChunks of this._outgoingMessageChunks.values()) {
|
|
125
121
|
channelChunks.forEach((chunk) => chunk.trigger?.wake());
|
|
126
122
|
}
|
|
127
|
-
this.
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
123
|
+
this._outgoingMessageChunks.clear();
|
|
124
|
+
this._incomingMessageAccumulator.clear();
|
|
125
|
+
this._serviceToChannel.clear();
|
|
130
126
|
}
|
|
131
127
|
|
|
132
128
|
private _sendChunkedMessages() {
|
|
@@ -143,12 +139,10 @@ export class WebSocketMuxer {
|
|
|
143
139
|
|
|
144
140
|
let timeout = 0;
|
|
145
141
|
const emptyChannels: number[] = [];
|
|
146
|
-
for (const [channelId, messages] of this.
|
|
147
|
-
if (this._ws.bufferedAmount
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
142
|
+
for (const [channelId, messages] of this._outgoingMessageChunks.entries()) {
|
|
143
|
+
if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {
|
|
144
|
+
timeout = BUFFER_FULL_BACKOFF_TIMEOUT;
|
|
145
|
+
break;
|
|
152
146
|
}
|
|
153
147
|
|
|
154
148
|
const nextMessage = messages.shift();
|
|
@@ -160,9 +154,9 @@ export class WebSocketMuxer {
|
|
|
160
154
|
}
|
|
161
155
|
}
|
|
162
156
|
|
|
163
|
-
emptyChannels.forEach((channelId) => this.
|
|
157
|
+
emptyChannels.forEach((channelId) => this._outgoingMessageChunks.delete(channelId));
|
|
164
158
|
|
|
165
|
-
if (this.
|
|
159
|
+
if (this._outgoingMessageChunks.size > 0) {
|
|
166
160
|
this._sendTimeout = setTimeout(send, timeout);
|
|
167
161
|
} else {
|
|
168
162
|
this._sendTimeout = undefined;
|
|
@@ -175,24 +169,15 @@ export class WebSocketMuxer {
|
|
|
175
169
|
if (!message.serviceId) {
|
|
176
170
|
return undefined;
|
|
177
171
|
}
|
|
178
|
-
let id = this.
|
|
172
|
+
let id = this._serviceToChannel.get(message.serviceId);
|
|
179
173
|
if (!id) {
|
|
180
|
-
id = this.
|
|
181
|
-
this.
|
|
174
|
+
id = this._serviceToChannel.size + 1;
|
|
175
|
+
this._serviceToChannel.set(message.serviceId, id);
|
|
182
176
|
}
|
|
183
177
|
return id;
|
|
184
178
|
}
|
|
185
179
|
}
|
|
186
180
|
|
|
187
|
-
type WebSocketCompat = {
|
|
188
|
-
readonly readyState: number;
|
|
189
|
-
/**
|
|
190
|
-
* Not available in workerd.
|
|
191
|
-
*/
|
|
192
|
-
bufferedAmount?: number;
|
|
193
|
-
send(message: (ArrayBuffer | ArrayBufferView) | string): void;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
181
|
type MessageChunk = {
|
|
197
182
|
payload: Buffer;
|
|
198
183
|
/**
|
package/src/index.ts
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/protocol.ts", "../../../src/defs.ts", "../../../src/edge-ws-muxer.ts", "../../../src/edge-ws-connection.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\n\n/**\n * 0000 0001 - message contains a part of segmented message chunk sequence.\n * The next byte defines a channel id and the rest of the message contains a part of Message proto binary.\n * Messages from different channels might interleave.\n * When the flag is NOT set the rest of the message should be interpreted as the valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ = 1;\n/**\n * 0000 0010 - message terminates a segmented message chunk sequence.\n * All the chunks accumulated for the channel specified by the second byte can be concatenated\n * and interpreted as a valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;\n\n/**\n * https://developers.cloudflare.com/durable-objects/platform/limits/\n */\nexport const CLOUDFLARE_MESSAGE_MAX_BYTES = 1000 * 1000; // 1MB\nexport const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB\n\nconst MAX_CHUNK_LENGTH = 16384;\nconst MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_MAX_BYTES;\nconst BUFFER_FULL_BACKOFF_TIMEOUT = 100;\n\nexport class WebSocketMuxer {\n private readonly _inMessageAccumulator = new Map<number, Buffer[]>();\n private readonly _outMessageChunks = new Map<number, MessageChunk[]>();\n private readonly _outMessageChannelByService = new Map<string, number>();\n\n private _sendTimeout: any | undefined;\n\n constructor(private readonly _ws: WebSocketCompat) {}\n\n /**\n * Resolves when all the message chunks get enqueued for sending.\n */\n public async send(message: Message): Promise<void> {\n const binary = buf.toBinary(MessageSchema, message);\n const channelId = this._resolveChannel(message);\n if (\n (channelId == null && binary.byteLength > CLOUDFLARE_MESSAGE_MAX_BYTES) ||\n binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES\n ) {\n log.error('Large message dropped', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n channelId,\n });\n return;\n }\n\n if (channelId == null || binary.length < MAX_CHUNK_LENGTH) {\n const flags = Buffer.from([0]);\n this._ws.send(Buffer.concat([flags, binary]));\n return;\n }\n\n const terminatorSentTrigger = new Trigger();\n const messageChunks: MessageChunk[] = [];\n for (let i = 0; i < binary.length; i += MAX_CHUNK_LENGTH) {\n const chunk = binary.slice(i, i + MAX_CHUNK_LENGTH);\n const isLastChunk = i + MAX_CHUNK_LENGTH < binary.length;\n if (isLastChunk) {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ | FLAG_SEGMENT_SEQ_TERMINATED, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]), trigger: terminatorSentTrigger });\n } else {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]) });\n }\n }\n\n const queuedMessages = this._outMessageChunks.get(channelId);\n if (queuedMessages) {\n queuedMessages.push(...messageChunks);\n } else {\n this._outMessageChunks.set(channelId, messageChunks);\n }\n\n this._sendChunkedMessages();\n\n return terminatorSentTrigger.wait();\n }\n\n public receiveData(data: Uint8Array): Message | undefined {\n if ((data[0] & FLAG_SEGMENT_SEQ) === 0) {\n return buf.fromBinary(MessageSchema, data.slice(1));\n }\n\n const [flags, channelId, ...payload] = data;\n let chunkAccumulator = this._inMessageAccumulator.get(channelId);\n if (chunkAccumulator) {\n chunkAccumulator.push(Buffer.from(payload));\n } else {\n chunkAccumulator = [Buffer.from(payload)];\n this._inMessageAccumulator.set(channelId, chunkAccumulator);\n }\n\n if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {\n return undefined;\n }\n\n const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));\n this._inMessageAccumulator.delete(channelId);\n return message;\n }\n\n public destroy() {\n if (this._sendTimeout) {\n clearTimeout(this._sendTimeout);\n this._sendTimeout = undefined;\n }\n for (const channelChunks of this._outMessageChunks.values()) {\n channelChunks.forEach((chunk) => chunk.trigger?.wake());\n }\n this._outMessageChunks.clear();\n this._inMessageAccumulator.clear();\n this._outMessageChannelByService.clear();\n }\n\n private _sendChunkedMessages() {\n if (this._sendTimeout) {\n return;\n }\n\n const send = () => {\n if (this._ws.readyState === WebSocket.CLOSING || this._ws.readyState === WebSocket.CLOSED) {\n log.warn('send called for closed websocket');\n this._sendTimeout = undefined;\n return;\n }\n\n let timeout = 0;\n const emptyChannels: number[] = [];\n for (const [channelId, messages] of this._outMessageChunks.entries()) {\n if (this._ws.bufferedAmount != null) {\n if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {\n timeout = BUFFER_FULL_BACKOFF_TIMEOUT;\n break;\n }\n }\n\n const nextMessage = messages.shift();\n if (nextMessage) {\n this._ws.send(nextMessage.payload);\n nextMessage.trigger?.wake();\n } else {\n emptyChannels.push(channelId);\n }\n }\n\n emptyChannels.forEach((channelId) => this._outMessageChunks.delete(channelId));\n\n if (this._outMessageChunks.size > 0) {\n this._sendTimeout = setTimeout(send, timeout);\n } else {\n this._sendTimeout = undefined;\n }\n };\n this._sendTimeout = setTimeout(send);\n }\n\n private _resolveChannel(message: Message): number | undefined {\n if (!message.serviceId) {\n return undefined;\n }\n let id = this._outMessageChannelByService.get(message.serviceId);\n if (!id) {\n id = this._outMessageChannelByService.size + 1;\n this._outMessageChannelByService.set(message.serviceId, id);\n }\n return id;\n }\n}\n\ntype WebSocketCompat = {\n readonly readyState: number;\n /**\n * Not available in workerd.\n */\n bufferedAmount?: number;\n send(message: (ArrayBuffer | ArrayBufferView) | string): void;\n};\n\ntype MessageChunk = {\n payload: Buffer;\n /**\n * Wakes when the payload is enqueued by WebSocket.\n */\n trigger?: Trigger;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { scheduleTask, scheduleTaskInterval } from '@dxos/async';\nimport { Context, Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log, logInfo } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\nimport { type EdgeIdentity } from './edge-identity';\nimport { CLOUDFLARE_MESSAGE_MAX_BYTES, WebSocketMuxer } from './edge-ws-muxer';\nimport { toUint8Array } from './protocol';\n\nconst SIGNAL_KEEPALIVE_INTERVAL = 4_000;\nconst SIGNAL_KEEPALIVE_TIMEOUT = 12_000;\n\nexport const EDGE_WEBSOCKET_PROTOCOL_V0 = 'edge-ws-v0';\n/**\n * Supports message segmentation and muxing.\n */\nexport const EDGE_WEBSOCKET_PROTOCOL_V1 = 'edge-ws-v1';\n\nexport type EdgeWsConnectionCallbacks = {\n onConnected: () => void;\n onMessage: (message: Message) => void;\n onRestartRequired: () => void;\n};\n\nexport class EdgeWsConnection extends Resource {\n private _inactivityTimeoutCtx: Context | undefined;\n private _ws: WebSocket | undefined;\n private _wsMuxer: WebSocketMuxer | undefined;\n\n constructor(\n private readonly _identity: EdgeIdentity,\n private readonly _connectionInfo: { url: URL; protocolHeader?: string },\n private readonly _callbacks: EdgeWsConnectionCallbacks,\n ) {\n super();\n }\n\n @logInfo\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identity.identityKey,\n device: this._identity.peerKey,\n };\n }\n\n public send(message: Message) {\n invariant(this._ws);\n invariant(this._wsMuxer);\n log('sending...', { peerKey: this._identity.peerKey, payload: protocol.getPayloadType(message) });\n if (this._ws?.protocol.includes(EDGE_WEBSOCKET_PROTOCOL_V0)) {\n const binary = buf.toBinary(MessageSchema, message);\n if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {\n log.error('Message dropped because it was too large (>1MB).', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n });\n return;\n }\n this._ws.send(binary);\n } else {\n this._wsMuxer.send(message).catch((e) => log.catch(e));\n }\n }\n\n protected override async _open() {\n const baseProtocols = [EDGE_WEBSOCKET_PROTOCOL_V0, EDGE_WEBSOCKET_PROTOCOL_V1];\n this._ws = new WebSocket(\n this._connectionInfo.url.toString(),\n this._connectionInfo.protocolHeader\n ? [...baseProtocols, this._connectionInfo.protocolHeader]\n : [...baseProtocols],\n );\n const muxer = new WebSocketMuxer(this._ws);\n this._wsMuxer = muxer;\n\n this._ws.onopen = () => {\n if (this.isOpen) {\n log('connected');\n this._callbacks.onConnected();\n this._scheduleHeartbeats();\n } else {\n log.verbose('connected after becoming inactive', { currentIdentity: this._identity });\n }\n };\n this._ws.onclose = (event) => {\n if (this.isOpen) {\n log.warn('disconnected while being open', { code: event.code, reason: event.reason });\n this._callbacks.onRestartRequired();\n muxer.destroy();\n }\n };\n this._ws.onerror = (event) => {\n if (this.isOpen) {\n log.warn('edge connection socket error', { error: event.error, info: event.message });\n this._callbacks.onRestartRequired();\n } else {\n log.verbose('error ignored on closed connection', { error: event.error });\n }\n };\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data\n */\n this._ws.onmessage = async (event) => {\n if (!this.isOpen) {\n log.verbose('message ignored on closed connection', { event: event.type });\n return;\n }\n if (event.data === '__pong__') {\n this._rescheduleHeartbeatTimeout();\n return;\n }\n const bytes = await toUint8Array(event.data);\n if (!this.isOpen) {\n return;\n }\n\n const message = this._ws?.protocol?.includes(EDGE_WEBSOCKET_PROTOCOL_V0)\n ? buf.fromBinary(MessageSchema, bytes)\n : muxer.receiveData(bytes);\n\n if (message) {\n log('received', { from: message.source, payload: protocol.getPayloadType(message) });\n this._callbacks.onMessage(message);\n }\n };\n }\n\n protected override async _close() {\n void this._inactivityTimeoutCtx?.dispose().catch(() => {});\n\n try {\n this._ws?.close();\n this._ws = undefined;\n this._wsMuxer?.destroy();\n this._wsMuxer = undefined;\n } catch (err) {\n if (err instanceof Error && err.message.includes('WebSocket is closed before the connection is established.')) {\n return;\n }\n log.warn('Error closing websocket', { err });\n }\n }\n\n private _scheduleHeartbeats() {\n invariant(this._ws);\n scheduleTaskInterval(\n this._ctx,\n async () => {\n // TODO(mykola): use RFC6455 ping/pong once implemented in the browser?\n // Cloudflare's worker responds to this `without interrupting hibernation`. https://developers.cloudflare.com/durable-objects/api/websockets/#setwebsocketautoresponse\n this._ws?.send('__ping__');\n },\n SIGNAL_KEEPALIVE_INTERVAL,\n );\n this._ws.send('__ping__');\n this._rescheduleHeartbeatTimeout();\n }\n\n private _rescheduleHeartbeatTimeout() {\n if (!this.isOpen) {\n return;\n }\n void this._inactivityTimeoutCtx?.dispose();\n this._inactivityTimeoutCtx = new Context();\n scheduleTask(\n this._inactivityTimeoutCtx,\n () => {\n if (this.isOpen) {\n log.warn('restart due to inactivity timeout');\n this._callbacks.onRestartRequired();\n }\n },\n SIGNAL_KEEPALIVE_TIMEOUT,\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["invariant", "buf", "bufWkt", "MessageSchema", "bufferToArray", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "createRegistry", "typeRegistry", "toJson", "message", "registry", "err", "type", "getPayloadType", "getPayload", "payload", "payloadTypename", "Error", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "Blob", "Uint8Array", "arrayBuffer", "bufWkt", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "protocol", "Protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "bufWkt", "AnySchema", "Trigger", "log", "buf", "MessageSchema", "FLAG_SEGMENT_SEQ", "FLAG_SEGMENT_SEQ_TERMINATED", "CLOUDFLARE_MESSAGE_MAX_BYTES", "CLOUDFLARE_RPC_MAX_BYTES", "MAX_CHUNK_LENGTH", "MAX_BUFFERED_AMOUNT", "BUFFER_FULL_BACKOFF_TIMEOUT", "WebSocketMuxer", "constructor", "_ws", "_inMessageAccumulator", "Map", "_outMessageChunks", "_outMessageChannelByService", "send", "message", "binary", "buf", "toBinary", "MessageSchema", "channelId", "_resolveChannel", "byteLength", "log", "error", "serviceId", "payload", "protocol", "getPayloadType", "length", "flags", "Buffer", "from", "concat", "terminatorSentTrigger", "Trigger", "messageChunks", "i", "chunk", "slice", "isLastChunk", "push", "trigger", "queuedMessages", "get", "set", "_sendChunkedMessages", "wait", "receiveData", "data", "fromBinary", "chunkAccumulator", "undefined", "delete", "destroy", "_sendTimeout", "clearTimeout", "channelChunks", "values", "forEach", "wake", "clear", "readyState", "WebSocket", "CLOSING", "CLOSED", "warn", "timeout", "emptyChannels", "messages", "entries", "bufferedAmount", "nextMessage", "shift", "size", "setTimeout", "id", "WebSocket", "scheduleTask", "scheduleTaskInterval", "Context", "Resource", "invariant", "log", "logInfo", "buf", "MessageSchema", "SIGNAL_KEEPALIVE_INTERVAL", "SIGNAL_KEEPALIVE_TIMEOUT", "EDGE_WEBSOCKET_PROTOCOL_V0", "EDGE_WEBSOCKET_PROTOCOL_V1", "EdgeWsConnection", "Resource", "constructor", "_identity", "_connectionInfo", "_callbacks", "info", "open", "isOpen", "identity", "identityKey", "device", "peerKey", "send", "message", "invariant", "_ws", "_wsMuxer", "log", "payload", "protocol", "getPayloadType", "includes", "binary", "buf", "toBinary", "MessageSchema", "length", "CLOUDFLARE_MESSAGE_MAX_BYTES", "error", "byteLength", "serviceId", "catch", "e", "_open", "baseProtocols", "WebSocket", "url", "toString", "protocolHeader", "muxer", "WebSocketMuxer", "onopen", "onConnected", "_scheduleHeartbeats", "verbose", "currentIdentity", "onclose", "event", "warn", "code", "reason", "onRestartRequired", "destroy", "onerror", "onmessage", "type", "data", "_rescheduleHeartbeatTimeout", "bytes", "toUint8Array", "fromBinary", "receiveData", "from", "source", "onMessage", "_close", "_inactivityTimeoutCtx", "dispose", "close", "undefined", "err", "Error", "scheduleTaskInterval", "_ctx", "Context", "scheduleTask", "logInfo"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/protocol.ts", "../../../src/defs.ts", "../../../src/edge-ws-muxer.ts", "../../../src/edge-ws-connection.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\n\n/**\n * 0000 0001 - message contains a part of segmented message chunk sequence.\n * The next byte defines a channel id and the rest of the message contains a part of Message proto binary.\n * Messages from different channels might interleave.\n * When the flag is NOT set the rest of the message should be interpreted as the valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ = 1;\n/**\n * 0000 0010 - message terminates a segmented message chunk sequence.\n * All the chunks accumulated for the channel specified by the second byte can be concatenated\n * and interpreted as a valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;\n\n/**\n * https://developers.cloudflare.com/durable-objects/platform/limits/\n */\nexport const CLOUDFLARE_MESSAGE_MAX_BYTES = 1000 * 1000; // 1MB\nexport const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB\n\nconst MAX_CHUNK_LENGTH = 16384;\nconst MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_MAX_BYTES;\nconst BUFFER_FULL_BACKOFF_TIMEOUT = 100;\n\nexport class WebSocketMuxer {\n private readonly _inMessageAccumulator = new Map<number, Buffer[]>();\n private readonly _outMessageChunks = new Map<number, MessageChunk[]>();\n private readonly _outMessageChannelByService = new Map<string, number>();\n\n private _sendTimeout: any | undefined;\n\n constructor(private readonly _ws: WebSocketCompat) {}\n\n /**\n * Resolves when all the message chunks get enqueued for sending.\n */\n public async send(message: Message): Promise<void> {\n const binary = buf.toBinary(MessageSchema, message);\n const channelId = this._resolveChannel(message);\n if (\n (channelId == null && binary.byteLength > CLOUDFLARE_MESSAGE_MAX_BYTES) ||\n binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES\n ) {\n log.error('Large message dropped', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n channelId,\n });\n return;\n }\n\n if (channelId == null || binary.length < MAX_CHUNK_LENGTH) {\n const flags = Buffer.from([0]);\n this._ws.send(Buffer.concat([flags, binary]));\n return;\n }\n\n const terminatorSentTrigger = new Trigger();\n const messageChunks: MessageChunk[] = [];\n for (let i = 0; i < binary.length; i += MAX_CHUNK_LENGTH) {\n const chunk = binary.slice(i, i + MAX_CHUNK_LENGTH);\n const isLastChunk = i + MAX_CHUNK_LENGTH < binary.length;\n if (isLastChunk) {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ | FLAG_SEGMENT_SEQ_TERMINATED, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]), trigger: terminatorSentTrigger });\n } else {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]) });\n }\n }\n\n const queuedMessages = this._outMessageChunks.get(channelId);\n if (queuedMessages) {\n queuedMessages.push(...messageChunks);\n } else {\n this._outMessageChunks.set(channelId, messageChunks);\n }\n\n this._sendChunkedMessages();\n\n return terminatorSentTrigger.wait();\n }\n\n public receiveData(data: Uint8Array): Message | undefined {\n if ((data[0] & FLAG_SEGMENT_SEQ) === 0) {\n return buf.fromBinary(MessageSchema, data.slice(1));\n }\n\n const [flags, channelId, ...payload] = data;\n let chunkAccumulator = this._inMessageAccumulator.get(channelId);\n if (chunkAccumulator) {\n chunkAccumulator.push(Buffer.from(payload));\n } else {\n chunkAccumulator = [Buffer.from(payload)];\n this._inMessageAccumulator.set(channelId, chunkAccumulator);\n }\n\n if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {\n return undefined;\n }\n\n const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));\n this._inMessageAccumulator.delete(channelId);\n return message;\n }\n\n public destroy() {\n if (this._sendTimeout) {\n clearTimeout(this._sendTimeout);\n this._sendTimeout = undefined;\n }\n for (const channelChunks of this._outMessageChunks.values()) {\n channelChunks.forEach((chunk) => chunk.trigger?.wake());\n }\n this._outMessageChunks.clear();\n this._inMessageAccumulator.clear();\n this._outMessageChannelByService.clear();\n }\n\n private _sendChunkedMessages() {\n if (this._sendTimeout) {\n return;\n }\n\n const send = () => {\n if (this._ws.readyState === WebSocket.CLOSING || this._ws.readyState === WebSocket.CLOSED) {\n log.warn('send called for closed websocket');\n this._sendTimeout = undefined;\n return;\n }\n\n let timeout = 0;\n const emptyChannels: number[] = [];\n for (const [channelId, messages] of this._outMessageChunks.entries()) {\n if (this._ws.bufferedAmount != null) {\n if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {\n timeout = BUFFER_FULL_BACKOFF_TIMEOUT;\n break;\n }\n }\n\n const nextMessage = messages.shift();\n if (nextMessage) {\n this._ws.send(nextMessage.payload);\n nextMessage.trigger?.wake();\n } else {\n emptyChannels.push(channelId);\n }\n }\n\n emptyChannels.forEach((channelId) => this._outMessageChunks.delete(channelId));\n\n if (this._outMessageChunks.size > 0) {\n this._sendTimeout = setTimeout(send, timeout);\n } else {\n this._sendTimeout = undefined;\n }\n };\n this._sendTimeout = setTimeout(send);\n }\n\n private _resolveChannel(message: Message): number | undefined {\n if (!message.serviceId) {\n return undefined;\n }\n let id = this._outMessageChannelByService.get(message.serviceId);\n if (!id) {\n id = this._outMessageChannelByService.size + 1;\n this._outMessageChannelByService.set(message.serviceId, id);\n }\n return id;\n }\n}\n\ntype WebSocketCompat = {\n readonly readyState: number;\n /**\n * Not available in workerd.\n */\n bufferedAmount?: number;\n send(message: (ArrayBuffer | ArrayBufferView) | string): void;\n};\n\ntype MessageChunk = {\n payload: Buffer;\n /**\n * Wakes when the payload is enqueued by WebSocket.\n */\n trigger?: Trigger;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { scheduleTask, scheduleTaskInterval } from '@dxos/async';\nimport { Context, Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log, logInfo } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\nimport { type EdgeIdentity } from './edge-identity';\nimport { CLOUDFLARE_MESSAGE_MAX_BYTES, WebSocketMuxer } from './edge-ws-muxer';\nimport { toUint8Array } from './protocol';\n\nconst SIGNAL_KEEPALIVE_INTERVAL = 4_000;\nconst SIGNAL_KEEPALIVE_TIMEOUT = 12_000;\n\nexport const EDGE_WEBSOCKET_PROTOCOL_V0 = 'edge-ws-v0';\n/**\n * Supports message segmentation and muxing.\n */\nexport const EDGE_WEBSOCKET_PROTOCOL_V1 = 'edge-ws-v1';\n\nexport type EdgeWsConnectionCallbacks = {\n onConnected: () => void;\n onMessage: (message: Message) => void;\n onRestartRequired: () => void;\n};\n\nexport class EdgeWsConnection extends Resource {\n private _inactivityTimeoutCtx: Context | undefined;\n private _ws: WebSocket | undefined;\n private _wsMuxer: WebSocketMuxer | undefined;\n\n constructor(\n private readonly _identity: EdgeIdentity,\n private readonly _connectionInfo: { url: URL; protocolHeader?: string },\n private readonly _callbacks: EdgeWsConnectionCallbacks,\n ) {\n super();\n }\n\n @logInfo\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identity.identityKey,\n device: this._identity.peerKey,\n };\n }\n\n public send(message: Message) {\n invariant(this._ws);\n invariant(this._wsMuxer);\n log('sending...', { peerKey: this._identity.peerKey, payload: protocol.getPayloadType(message) });\n if (this._ws?.protocol.includes(EDGE_WEBSOCKET_PROTOCOL_V0)) {\n const binary = buf.toBinary(MessageSchema, message);\n if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {\n log.error('Message dropped because it was too large (>1MB).', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n });\n return;\n }\n this._ws.send(binary);\n } else {\n this._wsMuxer.send(message).catch((e) => log.catch(e));\n }\n }\n\n protected override async _open() {\n const baseProtocols = [EDGE_WEBSOCKET_PROTOCOL_V0, EDGE_WEBSOCKET_PROTOCOL_V1];\n this._ws = new WebSocket(\n this._connectionInfo.url.toString(),\n this._connectionInfo.protocolHeader\n ? [...baseProtocols, this._connectionInfo.protocolHeader]\n : [...baseProtocols],\n );\n const muxer = new WebSocketMuxer(this._ws);\n this._wsMuxer = muxer;\n\n this._ws.onopen = () => {\n if (this.isOpen) {\n log('connected');\n this._callbacks.onConnected();\n this._scheduleHeartbeats();\n } else {\n log.verbose('connected after becoming inactive', { currentIdentity: this._identity });\n }\n };\n this._ws.onclose = (event) => {\n if (this.isOpen) {\n log.warn('disconnected while being open', { code: event.code, reason: event.reason });\n this._callbacks.onRestartRequired();\n muxer.destroy();\n }\n };\n this._ws.onerror = (event) => {\n if (this.isOpen) {\n log.warn('edge connection socket error', { error: event.error, info: event.message });\n this._callbacks.onRestartRequired();\n } else {\n log.verbose('error ignored on closed connection', { error: event.error });\n }\n };\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data\n */\n this._ws.onmessage = async (event) => {\n if (!this.isOpen) {\n log.verbose('message ignored on closed connection', { event: event.type });\n return;\n }\n if (event.data === '__pong__') {\n this._rescheduleHeartbeatTimeout();\n return;\n }\n const bytes = await toUint8Array(event.data);\n if (!this.isOpen) {\n return;\n }\n\n const message = this._ws?.protocol?.includes(EDGE_WEBSOCKET_PROTOCOL_V0)\n ? buf.fromBinary(MessageSchema, bytes)\n : muxer.receiveData(bytes);\n\n if (message) {\n log('received', { from: message.source, payload: protocol.getPayloadType(message) });\n this._callbacks.onMessage(message);\n }\n };\n }\n\n protected override async _close() {\n void this._inactivityTimeoutCtx?.dispose().catch(() => {});\n\n try {\n this._ws?.close();\n this._ws = undefined;\n this._wsMuxer?.destroy();\n this._wsMuxer = undefined;\n } catch (err) {\n if (err instanceof Error && err.message.includes('WebSocket is closed before the connection is established.')) {\n return;\n }\n log.warn('Error closing websocket', { err });\n }\n }\n\n private _scheduleHeartbeats() {\n invariant(this._ws);\n scheduleTaskInterval(\n this._ctx,\n async () => {\n // TODO(mykola): use RFC6455 ping/pong once implemented in the browser?\n // Cloudflare's worker responds to this `without interrupting hibernation`. https://developers.cloudflare.com/durable-objects/api/websockets/#setwebsocketautoresponse\n this._ws?.send('__ping__');\n },\n SIGNAL_KEEPALIVE_INTERVAL,\n );\n this._ws.send('__ping__');\n this._rescheduleHeartbeatTimeout();\n }\n\n private _rescheduleHeartbeatTimeout() {\n if (!this.isOpen) {\n return;\n }\n void this._inactivityTimeoutCtx?.dispose();\n this._inactivityTimeoutCtx = new Context();\n scheduleTask(\n this._inactivityTimeoutCtx,\n () => {\n if (this.isOpen) {\n log.warn('restart due to inactivity timeout');\n this._callbacks.onRestartRequired();\n }\n },\n SIGNAL_KEEPALIVE_TIMEOUT,\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_buf", "import_messenger_pb", "import_async", "import_invariant", "import_log", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "buf", "createRegistry", "typeRegistry", "toJson", "message", "MessageSchema", "registry", "err", "type", "getPayloadType", "getPayload", "invariant", "payload", "payloadTypename", "Error", "bufWkt", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "bufferToArray", "Blob", "Uint8Array", "arrayBuffer", "protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "AnySchema", "FLAG_SEGMENT_SEQ", "FLAG_SEGMENT_SEQ_TERMINATED", "CLOUDFLARE_MESSAGE_MAX_BYTES", "CLOUDFLARE_RPC_MAX_BYTES", "MAX_CHUNK_LENGTH", "MAX_BUFFERED_AMOUNT", "BUFFER_FULL_BACKOFF_TIMEOUT", "WebSocketMuxer", "_ws", "_inMessageAccumulator", "Map", "_outMessageChunks", "_outMessageChannelByService", "send", "binary", "toBinary", "channelId", "_resolveChannel", "byteLength", "log", "error", "length", "flags", "from", "concat", "terminatorSentTrigger", "Trigger", "messageChunks", "i", "chunk", "slice", "isLastChunk", "push", "trigger", "queuedMessages", "get", "set", "_sendChunkedMessages", "wait", "receiveData", "fromBinary", "chunkAccumulator", "delete", "destroy", "_sendTimeout", "clearTimeout", "channelChunks", "values", "forEach", "wake", "clear", "readyState", "WebSocket", "CLOSING", "CLOSED", "warn", "timeout", "emptyChannels", "messages", "entries", "bufferedAmount", "nextMessage", "shift", "size", "setTimeout", "id", "SIGNAL_KEEPALIVE_INTERVAL", "SIGNAL_KEEPALIVE_TIMEOUT", "EDGE_WEBSOCKET_PROTOCOL_V0", "EDGE_WEBSOCKET_PROTOCOL_V1", "EdgeWsConnection", "Resource", "_identity", "_connectionInfo", "_callbacks", "info", "open", "isOpen", "identity", "identityKey", "device", "peerKey", "_wsMuxer", "includes", "catch", "e", "_open", "baseProtocols", "url", "toString", "protocolHeader", "muxer", "onopen", "onConnected", "_scheduleHeartbeats", "verbose", "currentIdentity", "onclose", "event", "code", "reason", "onRestartRequired", "onerror", "onmessage", "_rescheduleHeartbeatTimeout", "bytes", "onMessage", "_close", "_inactivityTimeoutCtx", "dispose", "close", "scheduleTaskInterval", "_ctx", "Context", "scheduleTask", "logInfo"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/protocol.ts", "../../../src/defs.ts", "../../../src/edge-ws-muxer.ts", "../../../src/edge-ws-connection.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { buf, bufWkt } from '@dxos/protocols/buf';\nimport { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\nimport { bufferToArray } from '@dxos/util';\n\nexport type PeerData = buf.MessageInitShape<typeof PeerSchema>;\n\nexport const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;\n\n/**\n * NOTE: The type registry should be extended with all message types.\n */\nexport class Protocol {\n private readonly _typeRegistry: buf.Registry;\n\n constructor(types: buf.DescMessage[]) {\n this._typeRegistry = buf.createRegistry(...types);\n }\n\n get typeRegistry(): buf.Registry {\n return this._typeRegistry;\n }\n\n toJson(message: Message): any {\n try {\n return buf.toJson(MessageSchema, message, { registry: this.typeRegistry });\n } catch (err) {\n return { type: this.getPayloadType(message) };\n }\n }\n\n /**\n * Return the payload with the given type.\n */\n getPayload<Desc extends buf.DescMessage>(message: Message, type: Desc): buf.MessageShape<Desc> {\n invariant(message.payload);\n const payloadTypename = this.getPayloadType(message);\n if (type && type.typeName !== payloadTypename) {\n throw new Error(`Unexpected payload type: ${payloadTypename}; expected ${type.typeName}`);\n }\n\n invariant(bufWkt.anyIs(message.payload, type), `Unexpected payload type: ${payloadTypename}}`);\n const payload = bufWkt.anyUnpack(message.payload, this.typeRegistry) as buf.MessageShape<Desc>;\n invariant(payload, `Empty payload: ${payloadTypename}}`);\n return payload;\n }\n\n /**\n * Get the payload type.\n */\n getPayloadType(message: Message): string | undefined {\n if (!message.payload) {\n return undefined;\n }\n\n const [, type] = message.payload.typeUrl.split('/');\n return type;\n }\n\n /**\n * Create a packed message.\n */\n createMessage<Desc extends buf.DescMessage>(\n type: Desc,\n {\n source,\n target,\n payload,\n serviceId,\n }: {\n source?: PeerData;\n target?: PeerData[];\n payload?: buf.MessageInitShape<Desc>;\n serviceId?: string;\n },\n ) {\n return buf.create(MessageSchema, {\n timestamp: new Date().toISOString(),\n source,\n target,\n serviceId,\n payload: payload ? bufWkt.anyPack(type, buf.create(type, payload)) : undefined,\n });\n }\n}\n\n/**\n * Convert websocket data to Uint8Array.\n */\nexport const toUint8Array = async (data: any): Promise<Uint8Array> => {\n // Node.\n if (data instanceof Buffer) {\n return bufferToArray(data);\n }\n\n // Browser.\n if (data instanceof Blob) {\n return new Uint8Array(await (data as Blob).arrayBuffer());\n }\n\n throw new Error(`Unexpected datatype: ${data}`);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { bufWkt } from '@dxos/protocols/buf';\nimport { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { Protocol } from './protocol';\n\nexport const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\n\n/**\n * 0000 0001 - message contains a part of segmented message chunk sequence.\n * The next byte defines a channel id and the rest of the message contains a part of Message proto binary.\n * Messages from different channels might interleave.\n * When the flag is NOT set the rest of the message should be interpreted as the valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ = 1;\n/**\n * 0000 0010 - message terminates a segmented message chunk sequence.\n * All the chunks accumulated for the channel specified by the second byte can be concatenated\n * and interpreted as a valid Message proto binary.\n */\nconst FLAG_SEGMENT_SEQ_TERMINATED = 1 << 1;\n\n/**\n * https://developers.cloudflare.com/durable-objects/platform/limits/\n */\nexport const CLOUDFLARE_MESSAGE_MAX_BYTES = 1000 * 1000; // 1MB\nexport const CLOUDFLARE_RPC_MAX_BYTES = 32 * 1000 * 1000; // 32MB\n\nconst MAX_CHUNK_LENGTH = 16384;\nconst MAX_BUFFERED_AMOUNT = CLOUDFLARE_MESSAGE_MAX_BYTES;\nconst BUFFER_FULL_BACKOFF_TIMEOUT = 100;\n\nexport class WebSocketMuxer {\n private readonly _inMessageAccumulator = new Map<number, Buffer[]>();\n private readonly _outMessageChunks = new Map<number, MessageChunk[]>();\n private readonly _outMessageChannelByService = new Map<string, number>();\n\n private _sendTimeout: any | undefined;\n\n constructor(private readonly _ws: WebSocketCompat) {}\n\n /**\n * Resolves when all the message chunks get enqueued for sending.\n */\n public async send(message: Message): Promise<void> {\n const binary = buf.toBinary(MessageSchema, message);\n const channelId = this._resolveChannel(message);\n if (\n (channelId == null && binary.byteLength > CLOUDFLARE_MESSAGE_MAX_BYTES) ||\n binary.byteLength > CLOUDFLARE_RPC_MAX_BYTES\n ) {\n log.error('Large message dropped', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n channelId,\n });\n return;\n }\n\n if (channelId == null || binary.length < MAX_CHUNK_LENGTH) {\n const flags = Buffer.from([0]);\n this._ws.send(Buffer.concat([flags, binary]));\n return;\n }\n\n const terminatorSentTrigger = new Trigger();\n const messageChunks: MessageChunk[] = [];\n for (let i = 0; i < binary.length; i += MAX_CHUNK_LENGTH) {\n const chunk = binary.slice(i, i + MAX_CHUNK_LENGTH);\n const isLastChunk = i + MAX_CHUNK_LENGTH < binary.length;\n if (isLastChunk) {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ | FLAG_SEGMENT_SEQ_TERMINATED, channelId]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]), trigger: terminatorSentTrigger });\n } else {\n const flags = Buffer.from([FLAG_SEGMENT_SEQ]);\n messageChunks.push({ payload: Buffer.concat([flags, chunk]) });\n }\n }\n\n const queuedMessages = this._outMessageChunks.get(channelId);\n if (queuedMessages) {\n queuedMessages.push(...messageChunks);\n } else {\n this._outMessageChunks.set(channelId, messageChunks);\n }\n\n this._sendChunkedMessages();\n\n return terminatorSentTrigger.wait();\n }\n\n public receiveData(data: Uint8Array): Message | undefined {\n if ((data[0] & FLAG_SEGMENT_SEQ) === 0) {\n return buf.fromBinary(MessageSchema, data.slice(1));\n }\n\n const [flags, channelId, ...payload] = data;\n let chunkAccumulator = this._inMessageAccumulator.get(channelId);\n if (chunkAccumulator) {\n chunkAccumulator.push(Buffer.from(payload));\n } else {\n chunkAccumulator = [Buffer.from(payload)];\n this._inMessageAccumulator.set(channelId, chunkAccumulator);\n }\n\n if ((flags & FLAG_SEGMENT_SEQ_TERMINATED) === 0) {\n return undefined;\n }\n\n const message = buf.fromBinary(MessageSchema, Buffer.concat(chunkAccumulator));\n this._inMessageAccumulator.delete(channelId);\n return message;\n }\n\n public destroy() {\n if (this._sendTimeout) {\n clearTimeout(this._sendTimeout);\n this._sendTimeout = undefined;\n }\n for (const channelChunks of this._outMessageChunks.values()) {\n channelChunks.forEach((chunk) => chunk.trigger?.wake());\n }\n this._outMessageChunks.clear();\n this._inMessageAccumulator.clear();\n this._outMessageChannelByService.clear();\n }\n\n private _sendChunkedMessages() {\n if (this._sendTimeout) {\n return;\n }\n\n const send = () => {\n if (this._ws.readyState === WebSocket.CLOSING || this._ws.readyState === WebSocket.CLOSED) {\n log.warn('send called for closed websocket');\n this._sendTimeout = undefined;\n return;\n }\n\n let timeout = 0;\n const emptyChannels: number[] = [];\n for (const [channelId, messages] of this._outMessageChunks.entries()) {\n if (this._ws.bufferedAmount != null) {\n if (this._ws.bufferedAmount + MAX_CHUNK_LENGTH > MAX_BUFFERED_AMOUNT) {\n timeout = BUFFER_FULL_BACKOFF_TIMEOUT;\n break;\n }\n }\n\n const nextMessage = messages.shift();\n if (nextMessage) {\n this._ws.send(nextMessage.payload);\n nextMessage.trigger?.wake();\n } else {\n emptyChannels.push(channelId);\n }\n }\n\n emptyChannels.forEach((channelId) => this._outMessageChunks.delete(channelId));\n\n if (this._outMessageChunks.size > 0) {\n this._sendTimeout = setTimeout(send, timeout);\n } else {\n this._sendTimeout = undefined;\n }\n };\n this._sendTimeout = setTimeout(send);\n }\n\n private _resolveChannel(message: Message): number | undefined {\n if (!message.serviceId) {\n return undefined;\n }\n let id = this._outMessageChannelByService.get(message.serviceId);\n if (!id) {\n id = this._outMessageChannelByService.size + 1;\n this._outMessageChannelByService.set(message.serviceId, id);\n }\n return id;\n }\n}\n\ntype WebSocketCompat = {\n readonly readyState: number;\n /**\n * Not available in workerd.\n */\n bufferedAmount?: number;\n send(message: (ArrayBuffer | ArrayBufferView) | string): void;\n};\n\ntype MessageChunk = {\n payload: Buffer;\n /**\n * Wakes when the payload is enqueued by WebSocket.\n */\n trigger?: Trigger;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { scheduleTask, scheduleTaskInterval } from '@dxos/async';\nimport { Context, Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log, logInfo } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from './defs';\nimport { type EdgeIdentity } from './edge-identity';\nimport { CLOUDFLARE_MESSAGE_MAX_BYTES, WebSocketMuxer } from './edge-ws-muxer';\nimport { toUint8Array } from './protocol';\n\nconst SIGNAL_KEEPALIVE_INTERVAL = 4_000;\nconst SIGNAL_KEEPALIVE_TIMEOUT = 12_000;\n\nexport const EDGE_WEBSOCKET_PROTOCOL_V0 = 'edge-ws-v0';\n/**\n * Supports message segmentation and muxing.\n */\nexport const EDGE_WEBSOCKET_PROTOCOL_V1 = 'edge-ws-v1';\n\nexport type EdgeWsConnectionCallbacks = {\n onConnected: () => void;\n onMessage: (message: Message) => void;\n onRestartRequired: () => void;\n};\n\nexport class EdgeWsConnection extends Resource {\n private _inactivityTimeoutCtx: Context | undefined;\n private _ws: WebSocket | undefined;\n private _wsMuxer: WebSocketMuxer | undefined;\n\n constructor(\n private readonly _identity: EdgeIdentity,\n private readonly _connectionInfo: { url: URL; protocolHeader?: string },\n private readonly _callbacks: EdgeWsConnectionCallbacks,\n ) {\n super();\n }\n\n @logInfo\n public get info() {\n return {\n open: this.isOpen,\n identity: this._identity.identityKey,\n device: this._identity.peerKey,\n };\n }\n\n public send(message: Message) {\n invariant(this._ws);\n invariant(this._wsMuxer);\n log('sending...', { peerKey: this._identity.peerKey, payload: protocol.getPayloadType(message) });\n if (this._ws?.protocol.includes(EDGE_WEBSOCKET_PROTOCOL_V0)) {\n const binary = buf.toBinary(MessageSchema, message);\n if (binary.length > CLOUDFLARE_MESSAGE_MAX_BYTES) {\n log.error('Message dropped because it was too large (>1MB).', {\n byteLength: binary.byteLength,\n serviceId: message.serviceId,\n payload: protocol.getPayloadType(message),\n });\n return;\n }\n this._ws.send(binary);\n } else {\n this._wsMuxer.send(message).catch((e) => log.catch(e));\n }\n }\n\n protected override async _open() {\n const baseProtocols = [EDGE_WEBSOCKET_PROTOCOL_V0, EDGE_WEBSOCKET_PROTOCOL_V1];\n this._ws = new WebSocket(\n this._connectionInfo.url.toString(),\n this._connectionInfo.protocolHeader\n ? [...baseProtocols, this._connectionInfo.protocolHeader]\n : [...baseProtocols],\n );\n const muxer = new WebSocketMuxer(this._ws);\n this._wsMuxer = muxer;\n\n this._ws.onopen = () => {\n if (this.isOpen) {\n log('connected');\n this._callbacks.onConnected();\n this._scheduleHeartbeats();\n } else {\n log.verbose('connected after becoming inactive', { currentIdentity: this._identity });\n }\n };\n this._ws.onclose = (event) => {\n if (this.isOpen) {\n log.warn('disconnected while being open', { code: event.code, reason: event.reason });\n this._callbacks.onRestartRequired();\n muxer.destroy();\n }\n };\n this._ws.onerror = (event) => {\n if (this.isOpen) {\n log.warn('edge connection socket error', { error: event.error, info: event.message });\n this._callbacks.onRestartRequired();\n } else {\n log.verbose('error ignored on closed connection', { error: event.error });\n }\n };\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data\n */\n this._ws.onmessage = async (event) => {\n if (!this.isOpen) {\n log.verbose('message ignored on closed connection', { event: event.type });\n return;\n }\n if (event.data === '__pong__') {\n this._rescheduleHeartbeatTimeout();\n return;\n }\n const bytes = await toUint8Array(event.data);\n if (!this.isOpen) {\n return;\n }\n\n const message = this._ws?.protocol?.includes(EDGE_WEBSOCKET_PROTOCOL_V0)\n ? buf.fromBinary(MessageSchema, bytes)\n : muxer.receiveData(bytes);\n\n if (message) {\n log('received', { from: message.source, payload: protocol.getPayloadType(message) });\n this._callbacks.onMessage(message);\n }\n };\n }\n\n protected override async _close() {\n void this._inactivityTimeoutCtx?.dispose().catch(() => {});\n\n try {\n this._ws?.close();\n this._ws = undefined;\n this._wsMuxer?.destroy();\n this._wsMuxer = undefined;\n } catch (err) {\n if (err instanceof Error && err.message.includes('WebSocket is closed before the connection is established.')) {\n return;\n }\n log.warn('Error closing websocket', { err });\n }\n }\n\n private _scheduleHeartbeats() {\n invariant(this._ws);\n scheduleTaskInterval(\n this._ctx,\n async () => {\n // TODO(mykola): use RFC6455 ping/pong once implemented in the browser?\n // Cloudflare's worker responds to this `without interrupting hibernation`. https://developers.cloudflare.com/durable-objects/api/websockets/#setwebsocketautoresponse\n this._ws?.send('__ping__');\n },\n SIGNAL_KEEPALIVE_INTERVAL,\n );\n this._ws.send('__ping__');\n this._rescheduleHeartbeatTimeout();\n }\n\n private _rescheduleHeartbeatTimeout() {\n if (!this.isOpen) {\n return;\n }\n void this._inactivityTimeoutCtx?.dispose();\n this._inactivityTimeoutCtx = new Context();\n scheduleTask(\n this._inactivityTimeoutCtx,\n () => {\n if (this.isOpen) {\n log.warn('restart due to inactivity timeout');\n this._callbacks.onRestartRequired();\n }\n },\n SIGNAL_KEEPALIVE_TIMEOUT,\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["invariant", "buf", "bufWkt", "MessageSchema", "bufferToArray", "getTypename", "typeName", "Protocol", "constructor", "types", "_typeRegistry", "createRegistry", "typeRegistry", "toJson", "message", "registry", "err", "type", "getPayloadType", "getPayload", "payload", "payloadTypename", "Error", "anyIs", "anyUnpack", "undefined", "typeUrl", "split", "createMessage", "source", "target", "serviceId", "create", "timestamp", "Date", "toISOString", "anyPack", "toUint8Array", "data", "Buffer", "Blob", "Uint8Array", "arrayBuffer", "bufWkt", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "protocol", "Protocol", "SwarmRequestSchema", "SwarmResponseSchema", "TextMessageSchema", "bufWkt", "AnySchema", "Trigger", "log", "buf", "MessageSchema", "FLAG_SEGMENT_SEQ", "FLAG_SEGMENT_SEQ_TERMINATED", "CLOUDFLARE_MESSAGE_MAX_BYTES", "CLOUDFLARE_RPC_MAX_BYTES", "MAX_CHUNK_LENGTH", "MAX_BUFFERED_AMOUNT", "BUFFER_FULL_BACKOFF_TIMEOUT", "WebSocketMuxer", "constructor", "_ws", "_inMessageAccumulator", "Map", "_outMessageChunks", "_outMessageChannelByService", "send", "message", "binary", "buf", "toBinary", "MessageSchema", "channelId", "_resolveChannel", "byteLength", "log", "error", "serviceId", "payload", "protocol", "getPayloadType", "length", "flags", "Buffer", "from", "concat", "terminatorSentTrigger", "Trigger", "messageChunks", "i", "chunk", "slice", "isLastChunk", "push", "trigger", "queuedMessages", "get", "set", "_sendChunkedMessages", "wait", "receiveData", "data", "fromBinary", "chunkAccumulator", "undefined", "delete", "destroy", "_sendTimeout", "clearTimeout", "channelChunks", "values", "forEach", "wake", "clear", "readyState", "WebSocket", "CLOSING", "CLOSED", "warn", "timeout", "emptyChannels", "messages", "entries", "bufferedAmount", "nextMessage", "shift", "size", "setTimeout", "id", "WebSocket", "scheduleTask", "scheduleTaskInterval", "Context", "Resource", "invariant", "log", "logInfo", "buf", "MessageSchema", "SIGNAL_KEEPALIVE_INTERVAL", "SIGNAL_KEEPALIVE_TIMEOUT", "EDGE_WEBSOCKET_PROTOCOL_V0", "EDGE_WEBSOCKET_PROTOCOL_V1", "EdgeWsConnection", "Resource", "constructor", "_identity", "_connectionInfo", "_callbacks", "info", "open", "isOpen", "identity", "identityKey", "device", "peerKey", "send", "message", "invariant", "_ws", "_wsMuxer", "log", "payload", "protocol", "getPayloadType", "includes", "binary", "buf", "toBinary", "MessageSchema", "length", "CLOUDFLARE_MESSAGE_MAX_BYTES", "error", "byteLength", "serviceId", "catch", "e", "_open", "baseProtocols", "WebSocket", "url", "toString", "protocolHeader", "muxer", "WebSocketMuxer", "onopen", "onConnected", "_scheduleHeartbeats", "verbose", "currentIdentity", "onclose", "event", "warn", "code", "reason", "onRestartRequired", "destroy", "onerror", "onmessage", "type", "data", "_rescheduleHeartbeatTimeout", "bytes", "toUint8Array", "fromBinary", "receiveData", "from", "source", "onMessage", "_close", "_inactivityTimeoutCtx", "dispose", "close", "undefined", "err", "Error", "scheduleTaskInterval", "_ctx", "Context", "scheduleTask", "logInfo"]
|
|
7
|
-
}
|