@actuallab/rpc 12.1.100 → 12.2.21
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/index.cjs +1603 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +348 -25
- package/dist/index.d.ts +348 -25
- package/dist/index.js +1576 -169
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -22,6 +22,10 @@ var ARG_DELIMITER = "";
|
|
|
22
22
|
var FRAME_DELIMITER = "\n";
|
|
23
23
|
|
|
24
24
|
// src/rpc-serialization.ts
|
|
25
|
+
import {
|
|
26
|
+
Encoder,
|
|
27
|
+
Decoder
|
|
28
|
+
} from "@msgpack/msgpack";
|
|
25
29
|
function serializeMessage(message, args) {
|
|
26
30
|
const envelope = JSON.stringify(message);
|
|
27
31
|
if (args === void 0 || args.length === 0) {
|
|
@@ -51,13 +55,263 @@ function deserializeMessage(raw) {
|
|
|
51
55
|
try {
|
|
52
56
|
return JSON.parse(s);
|
|
53
57
|
} catch {
|
|
58
|
+
console.warn(
|
|
59
|
+
`[RpcSerialization] failed to parse arg as JSON: ${s.substring(0, 100)}`
|
|
60
|
+
);
|
|
54
61
|
return s;
|
|
55
62
|
}
|
|
56
63
|
});
|
|
57
64
|
return { message, args };
|
|
58
65
|
}
|
|
66
|
+
var textEncoder = new TextEncoder();
|
|
67
|
+
var textDecoder = new TextDecoder();
|
|
68
|
+
var INITIAL_ENCODER_BUFFER_SIZE = 32 * 1024;
|
|
69
|
+
var defaultBinaryEncoder = new Encoder(
|
|
70
|
+
void 0,
|
|
71
|
+
void 0,
|
|
72
|
+
void 0,
|
|
73
|
+
INITIAL_ENCODER_BUFFER_SIZE
|
|
74
|
+
);
|
|
75
|
+
var defaultBinaryDecoder = new Decoder();
|
|
76
|
+
function createBinaryEncoder() {
|
|
77
|
+
return new Encoder(
|
|
78
|
+
void 0,
|
|
79
|
+
void 0,
|
|
80
|
+
void 0,
|
|
81
|
+
INITIAL_ENCODER_BUFFER_SIZE
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
function varUintByteLen(value) {
|
|
85
|
+
if (value < 0) value = 0;
|
|
86
|
+
let n = 0;
|
|
87
|
+
do {
|
|
88
|
+
n++;
|
|
89
|
+
value >>>= 7;
|
|
90
|
+
} while (value > 0);
|
|
91
|
+
return n;
|
|
92
|
+
}
|
|
93
|
+
function writeVarUintInto(out, pos, value) {
|
|
94
|
+
if (value < 0) value = 0;
|
|
95
|
+
do {
|
|
96
|
+
let byte = value & 127;
|
|
97
|
+
value >>>= 7;
|
|
98
|
+
if (value > 0) byte |= 128;
|
|
99
|
+
out[pos++] = byte;
|
|
100
|
+
} while (value > 0);
|
|
101
|
+
return pos;
|
|
102
|
+
}
|
|
103
|
+
function readVarUint(data, offset) {
|
|
104
|
+
let value = 0, shift = 0, bytesRead = 0;
|
|
105
|
+
do {
|
|
106
|
+
if (offset + bytesRead >= data.length) break;
|
|
107
|
+
const byte = data[offset + bytesRead];
|
|
108
|
+
value |= (byte & 127) << shift;
|
|
109
|
+
bytesRead++;
|
|
110
|
+
if ((byte & 128) === 0) break;
|
|
111
|
+
shift += 7;
|
|
112
|
+
} while (shift < 35);
|
|
113
|
+
return { value: value >>> 0, bytesRead };
|
|
114
|
+
}
|
|
115
|
+
function concatUint8Arrays(arrays) {
|
|
116
|
+
let totalLength = 0;
|
|
117
|
+
for (const arr of arrays) totalLength += arr.length;
|
|
118
|
+
const result = new Uint8Array(totalLength);
|
|
119
|
+
let offset = 0;
|
|
120
|
+
for (const arr of arrays) {
|
|
121
|
+
result.set(arr, offset);
|
|
122
|
+
offset += arr.length;
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
function serializeBinaryMessage(message, args, encoder = defaultBinaryEncoder) {
|
|
127
|
+
let argsDataLen = 0;
|
|
128
|
+
let argBufs = null;
|
|
129
|
+
if (args && args.length > 0) {
|
|
130
|
+
argBufs = new Array(args.length);
|
|
131
|
+
for (let i = 0; i < args.length; i++) {
|
|
132
|
+
const buf = encoder.encode(args[i]);
|
|
133
|
+
argBufs[i] = buf;
|
|
134
|
+
argsDataLen += buf.length;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const callType = message.CallType ?? 0;
|
|
138
|
+
const relatedId = message.RelatedId ?? 0;
|
|
139
|
+
const methodBytes = textEncoder.encode(message.Method ?? "");
|
|
140
|
+
const relatedIdLen = varUintByteLen(relatedId);
|
|
141
|
+
const methodLenVarintLen = varUintByteLen(methodBytes.length);
|
|
142
|
+
const headerSize = 1 + relatedIdLen + methodLenVarintLen + methodBytes.length;
|
|
143
|
+
const totalSize = headerSize + 4 + argsDataLen;
|
|
144
|
+
const out = new Uint8Array(totalSize);
|
|
145
|
+
let pos = 0;
|
|
146
|
+
out[pos++] = callType << 5 & 224;
|
|
147
|
+
pos = writeVarUintInto(out, pos, relatedId);
|
|
148
|
+
pos = writeVarUintInto(out, pos, methodBytes.length);
|
|
149
|
+
out.set(methodBytes, pos);
|
|
150
|
+
pos += methodBytes.length;
|
|
151
|
+
out[pos++] = argsDataLen & 255;
|
|
152
|
+
out[pos++] = argsDataLen >>> 8 & 255;
|
|
153
|
+
out[pos++] = argsDataLen >>> 16 & 255;
|
|
154
|
+
out[pos++] = argsDataLen >>> 24 & 255;
|
|
155
|
+
if (argBufs !== null) {
|
|
156
|
+
for (const buf of argBufs) {
|
|
157
|
+
out.set(buf, pos);
|
|
158
|
+
pos += buf.length;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
function deserializeBinaryMessage(data, offset, decoder = defaultBinaryDecoder) {
|
|
164
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
165
|
+
let pos = offset;
|
|
166
|
+
const byte0 = data[pos++];
|
|
167
|
+
const callTypeId = byte0 >> 5 & 7;
|
|
168
|
+
const headerCount = byte0 & 31;
|
|
169
|
+
const relId = readVarUint(data, pos);
|
|
170
|
+
pos += relId.bytesRead;
|
|
171
|
+
const methodLen = readVarUint(data, pos);
|
|
172
|
+
pos += methodLen.bytesRead;
|
|
173
|
+
const methodBytes = data.subarray(pos, pos + methodLen.value);
|
|
174
|
+
const method = textDecoder.decode(methodBytes);
|
|
175
|
+
pos += methodLen.value;
|
|
176
|
+
const argDataLen = view.getInt32(pos, true);
|
|
177
|
+
pos += 4;
|
|
178
|
+
if (headerCount > 0) {
|
|
179
|
+
for (let h = 0; h < headerCount; h++) {
|
|
180
|
+
const keyLen = data[pos++];
|
|
181
|
+
pos += keyLen;
|
|
182
|
+
const valLen = readVarUint(data, pos);
|
|
183
|
+
pos += valLen.bytesRead + valLen.value;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const args = [];
|
|
187
|
+
const argEnd = pos + argDataLen;
|
|
188
|
+
if (argDataLen > 0) {
|
|
189
|
+
const argSlice = data.subarray(pos, argEnd);
|
|
190
|
+
for (const decoded of decoder.decodeMulti(argSlice)) {
|
|
191
|
+
args.push(decoded);
|
|
192
|
+
}
|
|
193
|
+
pos = argEnd;
|
|
194
|
+
}
|
|
195
|
+
const message = {
|
|
196
|
+
Method: method,
|
|
197
|
+
RelatedId: relId.value,
|
|
198
|
+
CallType: callTypeId
|
|
199
|
+
};
|
|
200
|
+
return { message, args, bytesRead: pos - offset };
|
|
201
|
+
}
|
|
202
|
+
function splitBinaryFrame(frame, decoder = defaultBinaryDecoder) {
|
|
203
|
+
const results = [];
|
|
204
|
+
let offset = 0;
|
|
205
|
+
while (offset < frame.length) {
|
|
206
|
+
const { message, args, bytesRead } = deserializeBinaryMessage(
|
|
207
|
+
frame,
|
|
208
|
+
offset,
|
|
209
|
+
decoder
|
|
210
|
+
);
|
|
211
|
+
if (bytesRead <= 0) break;
|
|
212
|
+
results.push({ message, args });
|
|
213
|
+
offset += bytesRead;
|
|
214
|
+
}
|
|
215
|
+
return results;
|
|
216
|
+
}
|
|
217
|
+
function serializeBinaryFrame(messages) {
|
|
218
|
+
return concatUint8Arrays(messages);
|
|
219
|
+
}
|
|
220
|
+
function serializeCompactBinaryMessage(message, args, registry, encoder = defaultBinaryEncoder) {
|
|
221
|
+
let argsDataLen = 0;
|
|
222
|
+
let argBufs = null;
|
|
223
|
+
if (args && args.length > 0) {
|
|
224
|
+
argBufs = new Array(args.length);
|
|
225
|
+
for (let i = 0; i < args.length; i++) {
|
|
226
|
+
const buf = encoder.encode(args[i]);
|
|
227
|
+
argBufs[i] = buf;
|
|
228
|
+
argsDataLen += buf.length;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const methodName = message.Method ?? "";
|
|
232
|
+
const methodHash = registry?.requireHash(methodName) ?? 0;
|
|
233
|
+
const callType = message.CallType ?? 0;
|
|
234
|
+
const relatedId = message.RelatedId ?? 0;
|
|
235
|
+
const relatedIdLen = varUintByteLen(relatedId);
|
|
236
|
+
const headerSize = 1 + relatedIdLen + 4;
|
|
237
|
+
const totalSize = headerSize + 4 + argsDataLen;
|
|
238
|
+
const out = new Uint8Array(totalSize);
|
|
239
|
+
let pos = 0;
|
|
240
|
+
out[pos++] = callType << 5 & 224;
|
|
241
|
+
pos = writeVarUintInto(out, pos, relatedId);
|
|
242
|
+
const hashU32 = methodHash >>> 0;
|
|
243
|
+
out[pos++] = hashU32 & 255;
|
|
244
|
+
out[pos++] = hashU32 >>> 8 & 255;
|
|
245
|
+
out[pos++] = hashU32 >>> 16 & 255;
|
|
246
|
+
out[pos++] = hashU32 >>> 24 & 255;
|
|
247
|
+
out[pos++] = argsDataLen & 255;
|
|
248
|
+
out[pos++] = argsDataLen >>> 8 & 255;
|
|
249
|
+
out[pos++] = argsDataLen >>> 16 & 255;
|
|
250
|
+
out[pos++] = argsDataLen >>> 24 & 255;
|
|
251
|
+
if (argBufs !== null) {
|
|
252
|
+
for (const buf of argBufs) {
|
|
253
|
+
out.set(buf, pos);
|
|
254
|
+
pos += buf.length;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
function deserializeCompactBinaryMessage(data, offset, registry, decoder = defaultBinaryDecoder) {
|
|
260
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
261
|
+
let pos = offset;
|
|
262
|
+
const byte0 = data[pos++];
|
|
263
|
+
const callTypeId = byte0 >> 5 & 7;
|
|
264
|
+
const headerCount = byte0 & 31;
|
|
265
|
+
const relId = readVarUint(data, pos);
|
|
266
|
+
pos += relId.bytesRead;
|
|
267
|
+
const methodHash = view.getUint32(pos, true);
|
|
268
|
+
pos += 4;
|
|
269
|
+
const method = registry?.getName(methodHash | 0) ?? `<hash:0x${methodHash.toString(16).padStart(8, "0")}>`;
|
|
270
|
+
const argDataLen = view.getInt32(pos, true);
|
|
271
|
+
pos += 4;
|
|
272
|
+
if (headerCount > 0) {
|
|
273
|
+
for (let h = 0; h < headerCount; h++) {
|
|
274
|
+
const keyLen = data[pos++];
|
|
275
|
+
pos += keyLen;
|
|
276
|
+
const valLen = readVarUint(data, pos);
|
|
277
|
+
pos += valLen.bytesRead + valLen.value;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const args = [];
|
|
281
|
+
const argEnd = pos + argDataLen;
|
|
282
|
+
if (argDataLen > 0) {
|
|
283
|
+
const argSlice = data.subarray(pos, argEnd);
|
|
284
|
+
for (const decoded of decoder.decodeMulti(argSlice)) {
|
|
285
|
+
args.push(decoded);
|
|
286
|
+
}
|
|
287
|
+
pos = argEnd;
|
|
288
|
+
}
|
|
289
|
+
const message = {
|
|
290
|
+
Method: method,
|
|
291
|
+
RelatedId: relId.value,
|
|
292
|
+
CallType: callTypeId
|
|
293
|
+
};
|
|
294
|
+
return { message, args, bytesRead: pos - offset };
|
|
295
|
+
}
|
|
296
|
+
function splitCompactBinaryFrame(frame, registry, decoder = defaultBinaryDecoder) {
|
|
297
|
+
const results = [];
|
|
298
|
+
let offset = 0;
|
|
299
|
+
while (offset < frame.length) {
|
|
300
|
+
const { message, args, bytesRead } = deserializeCompactBinaryMessage(
|
|
301
|
+
frame,
|
|
302
|
+
offset,
|
|
303
|
+
registry,
|
|
304
|
+
decoder
|
|
305
|
+
);
|
|
306
|
+
if (bytesRead <= 0) break;
|
|
307
|
+
results.push({ message, args });
|
|
308
|
+
offset += bytesRead;
|
|
309
|
+
}
|
|
310
|
+
return results;
|
|
311
|
+
}
|
|
59
312
|
|
|
60
313
|
// src/rpc-connection.ts
|
|
314
|
+
import { Decoder as Decoder2 } from "@msgpack/msgpack";
|
|
61
315
|
import { PromiseSource, EventHandlerSet } from "@actuallab/core";
|
|
62
316
|
var WebSocketState = {
|
|
63
317
|
CONNECTING: 0,
|
|
@@ -69,11 +323,36 @@ var RpcWebSocketConnection = class {
|
|
|
69
323
|
_ws;
|
|
70
324
|
_sendBuffer = [];
|
|
71
325
|
_connected = new PromiseSource();
|
|
326
|
+
/** Per-connection msgpack encoder — reused across outbound messages to
|
|
327
|
+
* amortise construction cost and to keep the internal write buffer at
|
|
328
|
+
* its largest observed size (avoids repeated `resizeBuffer` growth on
|
|
329
|
+
* large video frames). See serializeBinaryMessage() for details. */
|
|
330
|
+
_encoder = createBinaryEncoder();
|
|
331
|
+
/** Per-connection msgpack decoder — reused across inbound messages
|
|
332
|
+
* rather than reconstructing one for every `decodeMulti` call. */
|
|
333
|
+
_decoder = new Decoder2();
|
|
334
|
+
/** Exposed for callers who need to encode outbound binary messages
|
|
335
|
+
* through this connection (e.g. `serializeBinaryMessage`). Safe to
|
|
336
|
+
* pass to synchronous encode calls on the same event-loop turn. */
|
|
337
|
+
get encoder() {
|
|
338
|
+
return this._encoder;
|
|
339
|
+
}
|
|
340
|
+
get decoder() {
|
|
341
|
+
return this._decoder;
|
|
342
|
+
}
|
|
343
|
+
_format;
|
|
344
|
+
_methodRegistry;
|
|
345
|
+
binaryMode;
|
|
72
346
|
messageReceived = new EventHandlerSet();
|
|
73
347
|
closed = new EventHandlerSet();
|
|
74
348
|
error = new EventHandlerSet();
|
|
75
|
-
constructor(ws) {
|
|
349
|
+
constructor(ws, binaryMode = false, format, methodRegistry) {
|
|
76
350
|
this._ws = ws;
|
|
351
|
+
this.binaryMode = binaryMode;
|
|
352
|
+
this._format = format;
|
|
353
|
+
this._methodRegistry = methodRegistry;
|
|
354
|
+
if (binaryMode && ws.binaryType !== void 0)
|
|
355
|
+
ws.binaryType = "arraybuffer";
|
|
77
356
|
if (ws.readyState === WebSocketState.OPEN) {
|
|
78
357
|
this._connected.resolve();
|
|
79
358
|
this._flush();
|
|
@@ -83,10 +362,46 @@ var RpcWebSocketConnection = class {
|
|
|
83
362
|
this._flush();
|
|
84
363
|
};
|
|
85
364
|
ws.onmessage = (ev) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
365
|
+
if (ev.data instanceof Uint8Array || ev.data instanceof ArrayBuffer) {
|
|
366
|
+
const frame = ev.data instanceof Uint8Array ? ev.data : new Uint8Array(ev.data);
|
|
367
|
+
try {
|
|
368
|
+
const messages = this._splitBinary(frame);
|
|
369
|
+
for (const { message, args } of messages) {
|
|
370
|
+
this.messageReceived.trigger({
|
|
371
|
+
kind: "binary",
|
|
372
|
+
message,
|
|
373
|
+
args
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
} catch (e) {
|
|
377
|
+
this.error.trigger(e);
|
|
378
|
+
}
|
|
379
|
+
} else if (typeof Blob !== "undefined" && ev.data instanceof Blob && this.binaryMode) {
|
|
380
|
+
void ev.data.arrayBuffer().then((ab) => {
|
|
381
|
+
const frame = new Uint8Array(ab);
|
|
382
|
+
try {
|
|
383
|
+
const messages = this._splitBinary(frame);
|
|
384
|
+
for (const { message, args } of messages) {
|
|
385
|
+
this.messageReceived.trigger({
|
|
386
|
+
kind: "binary",
|
|
387
|
+
message,
|
|
388
|
+
args
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
} catch (e) {
|
|
392
|
+
this.error.trigger(e);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
} else {
|
|
396
|
+
const data = typeof ev.data === "string" ? ev.data : String(ev.data);
|
|
397
|
+
const messages = splitFrame(data);
|
|
398
|
+
for (const msg of messages) {
|
|
399
|
+
if (msg.length > 0)
|
|
400
|
+
this.messageReceived.trigger({
|
|
401
|
+
kind: "text",
|
|
402
|
+
raw: msg
|
|
403
|
+
});
|
|
404
|
+
}
|
|
90
405
|
}
|
|
91
406
|
};
|
|
92
407
|
ws.onclose = (ev) => {
|
|
@@ -103,27 +418,46 @@ var RpcWebSocketConnection = class {
|
|
|
103
418
|
return this._connected.promise;
|
|
104
419
|
}
|
|
105
420
|
send(serializedMessage) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
421
|
+
this._sendRaw(serializedMessage);
|
|
422
|
+
}
|
|
423
|
+
sendBinary(data) {
|
|
424
|
+
this._sendRaw(data);
|
|
425
|
+
}
|
|
426
|
+
sendTextBatch(messages) {
|
|
427
|
+
this._sendRaw(serializeFrame(messages));
|
|
428
|
+
}
|
|
429
|
+
sendBinaryBatch(messages) {
|
|
430
|
+
this._sendRaw(serializeBinaryFrame(messages));
|
|
113
431
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.
|
|
432
|
+
/** Split a binary frame using the format (compact-aware) or default splitter. */
|
|
433
|
+
_splitBinary(frame) {
|
|
434
|
+
if (this._format) {
|
|
435
|
+
return this._format.splitBinaryFrame(
|
|
436
|
+
frame,
|
|
437
|
+
this._decoder,
|
|
438
|
+
this._methodRegistry
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return splitBinaryFrame(frame, this._decoder);
|
|
117
442
|
}
|
|
118
443
|
close(code, reason) {
|
|
119
444
|
this._ws.close(code, reason);
|
|
120
445
|
}
|
|
446
|
+
_sendRaw(data) {
|
|
447
|
+
try {
|
|
448
|
+
if (this._ws.readyState === WebSocketState.OPEN) {
|
|
449
|
+
this._ws.send(data);
|
|
450
|
+
} else if (this._ws.readyState === WebSocketState.CONNECTING)
|
|
451
|
+
this._sendBuffer.push(data);
|
|
452
|
+
} catch {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
121
455
|
_flush() {
|
|
122
456
|
if (this._sendBuffer.length === 0) return;
|
|
123
|
-
const
|
|
457
|
+
const buffer = this._sendBuffer;
|
|
124
458
|
this._sendBuffer = [];
|
|
125
459
|
try {
|
|
126
|
-
this._ws.send(
|
|
460
|
+
for (const item of buffer) this._ws.send(item);
|
|
127
461
|
} catch {
|
|
128
462
|
}
|
|
129
463
|
}
|
|
@@ -134,6 +468,7 @@ import { EventHandlerSet as EventHandlerSet2 } from "@actuallab/core";
|
|
|
134
468
|
var RpcMessageChannelConnection = class {
|
|
135
469
|
_port;
|
|
136
470
|
_open = true;
|
|
471
|
+
binaryMode = false;
|
|
137
472
|
messageReceived = new EventHandlerSet2();
|
|
138
473
|
closed = new EventHandlerSet2();
|
|
139
474
|
whenConnected = Promise.resolve();
|
|
@@ -143,7 +478,8 @@ var RpcMessageChannelConnection = class {
|
|
|
143
478
|
port.onmessage = (ev) => {
|
|
144
479
|
const data = typeof ev.data === "string" ? ev.data : String(ev.data);
|
|
145
480
|
for (const msg of splitFrame(data))
|
|
146
|
-
if (msg.length > 0)
|
|
481
|
+
if (msg.length > 0)
|
|
482
|
+
this.messageReceived.trigger({ kind: "text", raw: msg });
|
|
147
483
|
};
|
|
148
484
|
}
|
|
149
485
|
get isOpen() {
|
|
@@ -156,6 +492,13 @@ var RpcMessageChannelConnection = class {
|
|
|
156
492
|
} catch {
|
|
157
493
|
}
|
|
158
494
|
}
|
|
495
|
+
sendBinary(data) {
|
|
496
|
+
if (!this._open) return;
|
|
497
|
+
try {
|
|
498
|
+
this._port.postMessage(data, [data.buffer]);
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
}
|
|
159
502
|
close(code, reason) {
|
|
160
503
|
if (!this._open) return;
|
|
161
504
|
this._open = false;
|
|
@@ -210,8 +553,8 @@ var RpcOutboundCall = class {
|
|
|
210
553
|
/** Whether to remove this call from the tracker on $sys.Ok. Default: true.
|
|
211
554
|
* Subclasses (e.g. compute calls) override to false to stay in tracker for invalidation. */
|
|
212
555
|
removeOnOk = true;
|
|
213
|
-
/** The serialized wire
|
|
214
|
-
|
|
556
|
+
/** The serialized wire data — stored for re-sending on reconnect. */
|
|
557
|
+
serializedWireData = "";
|
|
215
558
|
constructor(callId, method) {
|
|
216
559
|
this.callId = callId;
|
|
217
560
|
this.method = method;
|
|
@@ -301,6 +644,7 @@ var RpcInboundCallTracker = class {
|
|
|
301
644
|
};
|
|
302
645
|
|
|
303
646
|
// src/rpc-stream.ts
|
|
647
|
+
import Denque from "denque";
|
|
304
648
|
import { PromiseSource as PromiseSource3 } from "@actuallab/core";
|
|
305
649
|
|
|
306
650
|
// src/rpc-object.ts
|
|
@@ -308,25 +652,49 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
|
|
|
308
652
|
|
|
309
653
|
// src/rpc-stream.ts
|
|
310
654
|
function parseStreamRef(value) {
|
|
311
|
-
if (typeof value
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
655
|
+
if (typeof value === "string") {
|
|
656
|
+
const parts = value.split(",");
|
|
657
|
+
if (parts.length < 4 || parts.length > 6) return null;
|
|
658
|
+
const hostId = parts[0];
|
|
659
|
+
const localId = parseInt(parts[1], 10);
|
|
660
|
+
const ackPeriod = parseInt(parts[2], 10);
|
|
661
|
+
const ackAdvance = parseInt(parts[3], 10);
|
|
662
|
+
if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance))
|
|
663
|
+
return null;
|
|
664
|
+
const allowReconnect = parts.length < 5 || parts[4] !== "0";
|
|
665
|
+
const isRealTime = parts.length >= 6 && parts[5] === "1";
|
|
666
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
667
|
+
}
|
|
668
|
+
if (typeof value === "object" && value !== null) {
|
|
669
|
+
const obj = value;
|
|
670
|
+
const serializedId = obj.SerializedId;
|
|
671
|
+
if (!Array.isArray(serializedId) || serializedId.length < 2)
|
|
672
|
+
return null;
|
|
673
|
+
const rawHostId = serializedId[0];
|
|
674
|
+
const hostId = String(rawHostId);
|
|
675
|
+
const localId = Number(serializedId[1]);
|
|
676
|
+
const ackPeriod = Number(obj.AckPeriod ?? 256);
|
|
677
|
+
const ackAdvance = Number(obj.AckAdvance ?? 128);
|
|
678
|
+
const allowReconnect = obj.AllowReconnect !== false;
|
|
679
|
+
const isRealTime = obj.IsRealTime === true;
|
|
680
|
+
return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
|
|
681
|
+
}
|
|
682
|
+
return null;
|
|
321
683
|
}
|
|
322
|
-
var RpcStream = class {
|
|
684
|
+
var RpcStream = class _RpcStream {
|
|
323
685
|
id;
|
|
324
686
|
kind = RpcObjectKind.Remote;
|
|
325
687
|
allowReconnect;
|
|
326
688
|
peer;
|
|
327
689
|
ackPeriod;
|
|
328
690
|
ackAdvance;
|
|
329
|
-
|
|
691
|
+
// Double-ended queue so consumption via `shift()` is O(1) and the
|
|
692
|
+
// backing store frees memory as items are drained. The previous
|
|
693
|
+
// `T[]` buffer kept every item for the life of the stream because
|
|
694
|
+
// the iterator tracked a read index instead of shifting — fine for
|
|
695
|
+
// short runs but a slow leak in the browser where a video call can
|
|
696
|
+
// last an hour.
|
|
697
|
+
_buffer = new Denque();
|
|
330
698
|
_nextExpectedIndex = 0;
|
|
331
699
|
_consumerWaiting = null;
|
|
332
700
|
_completed = false;
|
|
@@ -346,6 +714,17 @@ var RpcStream = class {
|
|
|
346
714
|
onItem(index, item) {
|
|
347
715
|
if (this._disposed || this._completed) return;
|
|
348
716
|
if (index > this._nextExpectedIndex) {
|
|
717
|
+
console.warn(
|
|
718
|
+
`[RpcStream] item index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
|
|
719
|
+
);
|
|
720
|
+
if (!this.allowReconnect) {
|
|
721
|
+
this._completed = true;
|
|
722
|
+
this._completionError = new Error(
|
|
723
|
+
`Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
|
|
724
|
+
);
|
|
725
|
+
this._notifyConsumer();
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
349
728
|
this._sendAck(this._nextExpectedIndex, true);
|
|
350
729
|
return;
|
|
351
730
|
}
|
|
@@ -362,6 +741,17 @@ var RpcStream = class {
|
|
|
362
741
|
onBatch(index, items) {
|
|
363
742
|
if (this._disposed || this._completed) return;
|
|
364
743
|
if (index > this._nextExpectedIndex) {
|
|
744
|
+
console.warn(
|
|
745
|
+
`[RpcStream] batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
|
|
746
|
+
);
|
|
747
|
+
if (!this.allowReconnect) {
|
|
748
|
+
this._completed = true;
|
|
749
|
+
this._completionError = new Error(
|
|
750
|
+
`Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
|
|
751
|
+
);
|
|
752
|
+
this._notifyConsumer();
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
365
755
|
this._sendAck(this._nextExpectedIndex, true);
|
|
366
756
|
return;
|
|
367
757
|
}
|
|
@@ -397,10 +787,9 @@ var RpcStream = class {
|
|
|
397
787
|
}
|
|
398
788
|
// -- AsyncIterable --
|
|
399
789
|
[Symbol.asyncIterator]() {
|
|
400
|
-
if (this._iterating)
|
|
790
|
+
if (this._iterating)
|
|
791
|
+
throw new Error("RpcStream can only be iterated once.");
|
|
401
792
|
this._iterating = true;
|
|
402
|
-
let bufferIndex = 0;
|
|
403
|
-
let consumedIndex = 0;
|
|
404
793
|
const self = this;
|
|
405
794
|
return {
|
|
406
795
|
async next() {
|
|
@@ -409,10 +798,8 @@ var RpcStream = class {
|
|
|
409
798
|
self._sendAck(0, true);
|
|
410
799
|
}
|
|
411
800
|
while (true) {
|
|
412
|
-
if (
|
|
413
|
-
const value = self._buffer
|
|
414
|
-
bufferIndex++;
|
|
415
|
-
consumedIndex++;
|
|
801
|
+
if (!self._buffer.isEmpty()) {
|
|
802
|
+
const value = self._buffer.shift();
|
|
416
803
|
return { value, done: false };
|
|
417
804
|
}
|
|
418
805
|
if (self._completed) {
|
|
@@ -451,17 +838,30 @@ var RpcStream = class {
|
|
|
451
838
|
this._sendAck(nextIndex, false);
|
|
452
839
|
}
|
|
453
840
|
}
|
|
454
|
-
|
|
841
|
+
static _emptyGuid = "00000000-0000-0000-0000-000000000000";
|
|
842
|
+
_sendAck(nextIndex, mustReset) {
|
|
455
843
|
this._ackSentUpTo = nextIndex;
|
|
456
844
|
const conn = this.peer.connection;
|
|
457
845
|
if (conn) {
|
|
458
|
-
|
|
846
|
+
const hostId = mustReset ? this.id.hostId : _RpcStream._emptyGuid;
|
|
847
|
+
this.peer.hub.systemCallSender.ack(
|
|
848
|
+
conn,
|
|
849
|
+
this.peer.format,
|
|
850
|
+
this.id.localId,
|
|
851
|
+
nextIndex,
|
|
852
|
+
hostId
|
|
853
|
+
);
|
|
459
854
|
}
|
|
460
855
|
}
|
|
461
856
|
_sendAckEnd() {
|
|
462
857
|
const conn = this.peer.connection;
|
|
463
858
|
if (conn) {
|
|
464
|
-
this.peer.hub.systemCallSender.ackEnd(
|
|
859
|
+
this.peer.hub.systemCallSender.ackEnd(
|
|
860
|
+
conn,
|
|
861
|
+
this.peer.format,
|
|
862
|
+
this.id.localId,
|
|
863
|
+
this.id.hostId
|
|
864
|
+
);
|
|
465
865
|
}
|
|
466
866
|
}
|
|
467
867
|
};
|
|
@@ -483,6 +883,8 @@ function resolveStreamRefs(value, peer) {
|
|
|
483
883
|
return value;
|
|
484
884
|
}
|
|
485
885
|
if (typeof value === "object") {
|
|
886
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer)
|
|
887
|
+
return value;
|
|
486
888
|
for (const key of Object.keys(value)) {
|
|
487
889
|
value[key] = resolveStreamRefs(
|
|
488
890
|
value[key],
|
|
@@ -528,21 +930,39 @@ var RpcSystemCallHandler = class {
|
|
|
528
930
|
}
|
|
529
931
|
case RpcSystemCalls.item: {
|
|
530
932
|
const stream = peer.remoteObjects.get(relatedId);
|
|
531
|
-
if (stream)
|
|
933
|
+
if (!stream) {
|
|
934
|
+
console.warn(
|
|
935
|
+
`[RpcSysHandler] $sys.I: no stream for relatedId=${relatedId}`
|
|
936
|
+
);
|
|
937
|
+
} else {
|
|
938
|
+
stream.onItem(
|
|
939
|
+
args[0],
|
|
940
|
+
resolveStreamRefs(args[1], peer)
|
|
941
|
+
);
|
|
942
|
+
}
|
|
532
943
|
break;
|
|
533
944
|
}
|
|
534
945
|
case RpcSystemCalls.batch: {
|
|
535
946
|
const stream = peer.remoteObjects.get(relatedId);
|
|
536
|
-
if (stream) {
|
|
947
|
+
if (!stream) {
|
|
948
|
+
console.warn(
|
|
949
|
+
`[RpcSysHandler] $sys.B: no stream for relatedId=${relatedId}`
|
|
950
|
+
);
|
|
951
|
+
} else if (Array.isArray(args[1])) {
|
|
537
952
|
const items = args[1];
|
|
538
|
-
for (let i = 0; i < items.length; i++)
|
|
953
|
+
for (let i = 0; i < items.length; i++)
|
|
954
|
+
items[i] = resolveStreamRefs(items[i], peer);
|
|
539
955
|
stream.onBatch(args[0], items);
|
|
540
956
|
}
|
|
541
957
|
break;
|
|
542
958
|
}
|
|
543
959
|
case RpcSystemCalls.end: {
|
|
544
960
|
const stream = peer.remoteObjects.get(relatedId);
|
|
545
|
-
if (stream) {
|
|
961
|
+
if (!stream) {
|
|
962
|
+
console.warn(
|
|
963
|
+
`[RpcSysHandler] $sys.End: no stream for relatedId=${relatedId}`
|
|
964
|
+
);
|
|
965
|
+
} else {
|
|
546
966
|
const errorInfo = args[1];
|
|
547
967
|
const msg = errorInfo?.Message ?? errorInfo?.message;
|
|
548
968
|
const error = msg ? new Error(msg) : null;
|
|
@@ -560,76 +980,142 @@ var RpcSystemCallHandler = class {
|
|
|
560
980
|
sender?.onAckEnd(args[0]);
|
|
561
981
|
break;
|
|
562
982
|
}
|
|
983
|
+
default: {
|
|
984
|
+
if (method === "$sys.Disconnect" || method?.startsWith("$sys.Disconnect")) {
|
|
985
|
+
const ids = args[0];
|
|
986
|
+
if (Array.isArray(ids)) {
|
|
987
|
+
for (const id of ids) {
|
|
988
|
+
const remoteObj = peer.remoteObjects.get(id);
|
|
989
|
+
if (remoteObj && typeof remoteObj.disconnect === "function") {
|
|
990
|
+
remoteObj.disconnect();
|
|
991
|
+
}
|
|
992
|
+
const sharedObj = peer.sharedObjects.get(id);
|
|
993
|
+
if (sharedObj && typeof sharedObj.disconnect === "function") {
|
|
994
|
+
sharedObj.disconnect();
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
563
1001
|
}
|
|
564
1002
|
}
|
|
565
1003
|
};
|
|
566
1004
|
|
|
567
1005
|
// src/rpc-system-call-sender.ts
|
|
568
|
-
var RpcSystemCallSender = class {
|
|
569
|
-
|
|
570
|
-
|
|
1006
|
+
var RpcSystemCallSender = class _RpcSystemCallSender {
|
|
1007
|
+
// Reusable envelopes — one per hot-path method.
|
|
1008
|
+
_itemEnv = {
|
|
1009
|
+
Method: RpcSystemCalls.item,
|
|
1010
|
+
RelatedId: 0
|
|
1011
|
+
};
|
|
1012
|
+
_batchEnv = {
|
|
1013
|
+
Method: RpcSystemCalls.batch,
|
|
1014
|
+
RelatedId: 0
|
|
1015
|
+
};
|
|
1016
|
+
_endEnv = {
|
|
1017
|
+
Method: RpcSystemCalls.end,
|
|
1018
|
+
RelatedId: 0
|
|
1019
|
+
};
|
|
1020
|
+
_ackEnv = {
|
|
1021
|
+
Method: RpcSystemCalls.ack,
|
|
1022
|
+
RelatedId: 0
|
|
1023
|
+
};
|
|
1024
|
+
_ackEndEnv = {
|
|
1025
|
+
Method: RpcSystemCalls.ackEnd,
|
|
1026
|
+
RelatedId: 0
|
|
1027
|
+
};
|
|
1028
|
+
// Reusable arg arrays.
|
|
1029
|
+
_itemArgs = [0, null];
|
|
1030
|
+
_batchArgs = [0, null];
|
|
1031
|
+
_endArgs = [0, { TypeRef: "", Message: "" }];
|
|
1032
|
+
_ackArgs = [0, ""];
|
|
1033
|
+
_ackEndArgs = [""];
|
|
1034
|
+
static NO_ERROR = Object.freeze({ TypeRef: "", Message: "" });
|
|
1035
|
+
registry;
|
|
1036
|
+
_send(conn, format, envelope, args) {
|
|
1037
|
+
const wireData = format.serializeMessage(
|
|
1038
|
+
envelope,
|
|
1039
|
+
args,
|
|
1040
|
+
conn.encoder,
|
|
1041
|
+
this.registry
|
|
1042
|
+
);
|
|
1043
|
+
if (typeof wireData === "string") {
|
|
1044
|
+
conn.send(wireData);
|
|
1045
|
+
} else {
|
|
1046
|
+
conn.sendBinary(wireData);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
handshake(conn, format, peerId, hubId, index) {
|
|
1050
|
+
const handshakeArg = format.isBinary ? [peerId, null, hubId, 2, index] : {
|
|
571
1051
|
RemotePeerId: peerId,
|
|
572
1052
|
RemoteApiVersionSet: null,
|
|
573
1053
|
RemoteHubId: hubId,
|
|
574
1054
|
ProtocolVersion: 2,
|
|
575
1055
|
Index: index
|
|
576
|
-
}
|
|
577
|
-
conn.
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
1056
|
+
};
|
|
1057
|
+
this._send(conn, format, { Method: RpcSystemCalls.handshake }, [
|
|
1058
|
+
handshakeArg
|
|
1059
|
+
]);
|
|
1060
|
+
}
|
|
1061
|
+
ok(conn, format, relatedId, result) {
|
|
1062
|
+
this._send(
|
|
1063
|
+
conn,
|
|
1064
|
+
format,
|
|
1065
|
+
{ Method: RpcSystemCalls.ok, RelatedId: relatedId },
|
|
1066
|
+
[result]
|
|
1067
|
+
);
|
|
582
1068
|
}
|
|
583
|
-
error(conn, relatedId, error) {
|
|
1069
|
+
error(conn, format, relatedId, error) {
|
|
584
1070
|
const message = error instanceof Error ? error.message : String(error);
|
|
585
|
-
|
|
1071
|
+
this._send(
|
|
1072
|
+
conn,
|
|
1073
|
+
format,
|
|
586
1074
|
{ Method: RpcSystemCalls.error, RelatedId: relatedId },
|
|
587
1075
|
[{ Message: message }]
|
|
588
1076
|
);
|
|
589
|
-
conn.send(msg);
|
|
590
|
-
}
|
|
591
|
-
cancel(conn, relatedId) {
|
|
592
|
-
const msg = serializeMessage({ Method: RpcSystemCalls.cancel, RelatedId: relatedId });
|
|
593
|
-
conn.send(msg);
|
|
594
|
-
}
|
|
595
|
-
keepAlive(conn, activeCallIds) {
|
|
596
|
-
const msg = serializeMessage({ Method: RpcSystemCalls.keepAlive }, [activeCallIds]);
|
|
597
|
-
conn.send(msg);
|
|
598
|
-
}
|
|
599
|
-
item(conn, localId, index, item) {
|
|
600
|
-
const msg = serializeMessage(
|
|
601
|
-
{ Method: RpcSystemCalls.item, RelatedId: localId },
|
|
602
|
-
[index, item]
|
|
603
|
-
);
|
|
604
|
-
conn.send(msg);
|
|
605
|
-
}
|
|
606
|
-
batch(conn, localId, index, items) {
|
|
607
|
-
const msg = serializeMessage(
|
|
608
|
-
{ Method: RpcSystemCalls.batch, RelatedId: localId },
|
|
609
|
-
[index, items]
|
|
610
|
-
);
|
|
611
|
-
conn.send(msg);
|
|
612
|
-
}
|
|
613
|
-
end(conn, localId, index, error = null) {
|
|
614
|
-
const msg = serializeMessage(
|
|
615
|
-
{ Method: RpcSystemCalls.end, RelatedId: localId },
|
|
616
|
-
[index, error]
|
|
617
|
-
);
|
|
618
|
-
conn.send(msg);
|
|
619
1077
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
);
|
|
625
|
-
conn.send(msg);
|
|
1078
|
+
cancel(conn, format, relatedId) {
|
|
1079
|
+
this._send(conn, format, {
|
|
1080
|
+
Method: RpcSystemCalls.cancel,
|
|
1081
|
+
RelatedId: relatedId
|
|
1082
|
+
});
|
|
626
1083
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
1084
|
+
keepAlive(conn, format, activeCallIds) {
|
|
1085
|
+
this._send(conn, format, { Method: RpcSystemCalls.keepAlive }, [
|
|
1086
|
+
activeCallIds
|
|
1087
|
+
]);
|
|
1088
|
+
}
|
|
1089
|
+
item(conn, format, localId, index, item) {
|
|
1090
|
+
this._itemEnv.RelatedId = localId;
|
|
1091
|
+
this._itemArgs[0] = index;
|
|
1092
|
+
this._itemArgs[1] = item;
|
|
1093
|
+
this._send(conn, format, this._itemEnv, this._itemArgs);
|
|
1094
|
+
this._itemArgs[1] = null;
|
|
1095
|
+
}
|
|
1096
|
+
batch(conn, format, localId, index, items) {
|
|
1097
|
+
this._batchEnv.RelatedId = localId;
|
|
1098
|
+
this._batchArgs[0] = index;
|
|
1099
|
+
this._batchArgs[1] = items;
|
|
1100
|
+
this._send(conn, format, this._batchEnv, this._batchArgs);
|
|
1101
|
+
this._batchArgs[1] = null;
|
|
1102
|
+
}
|
|
1103
|
+
end(conn, format, localId, index, error = _RpcSystemCallSender.NO_ERROR) {
|
|
1104
|
+
this._endEnv.RelatedId = localId;
|
|
1105
|
+
this._endArgs[0] = index;
|
|
1106
|
+
this._endArgs[1] = error;
|
|
1107
|
+
this._send(conn, format, this._endEnv, this._endArgs);
|
|
1108
|
+
}
|
|
1109
|
+
ack(conn, format, localId, nextIndex, hostId) {
|
|
1110
|
+
this._ackEnv.RelatedId = localId;
|
|
1111
|
+
this._ackArgs[0] = nextIndex;
|
|
1112
|
+
this._ackArgs[1] = hostId;
|
|
1113
|
+
this._send(conn, format, this._ackEnv, this._ackArgs);
|
|
1114
|
+
}
|
|
1115
|
+
ackEnd(conn, format, localId, hostId) {
|
|
1116
|
+
this._ackEndEnv.RelatedId = localId;
|
|
1117
|
+
this._ackEndArgs[0] = hostId;
|
|
1118
|
+
this._send(conn, format, this._ackEndEnv, this._ackEndArgs);
|
|
633
1119
|
}
|
|
634
1120
|
};
|
|
635
1121
|
|
|
@@ -641,29 +1127,42 @@ var RpcStreamSender = class {
|
|
|
641
1127
|
id;
|
|
642
1128
|
kind = RpcObjectKind.Local;
|
|
643
1129
|
allowReconnect;
|
|
1130
|
+
isRealTime;
|
|
1131
|
+
canSkipTo;
|
|
644
1132
|
peer;
|
|
645
1133
|
ackPeriod;
|
|
646
1134
|
ackAdvance;
|
|
647
1135
|
_nextIndex = 0;
|
|
648
1136
|
_ended = false;
|
|
649
1137
|
_started = new PromiseSource4();
|
|
650
|
-
|
|
1138
|
+
_lastAckedIndex = 0;
|
|
1139
|
+
_ackWaiting = null;
|
|
1140
|
+
constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true, isRealTime = false, canSkipTo = () => true) {
|
|
651
1141
|
const localId = peer.sharedObjects.nextId();
|
|
652
1142
|
this.id = { hostId: peer.hub.hubId, localId };
|
|
653
1143
|
this.allowReconnect = allowReconnect;
|
|
1144
|
+
this.isRealTime = isRealTime;
|
|
1145
|
+
this.canSkipTo = canSkipTo;
|
|
654
1146
|
this.peer = peer;
|
|
655
1147
|
this.ackPeriod = ackPeriod;
|
|
656
1148
|
this.ackAdvance = ackAdvance;
|
|
657
1149
|
}
|
|
658
1150
|
/** Returns the stream reference string for the $sys.Ok response. */
|
|
659
1151
|
toRef() {
|
|
660
|
-
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"}`;
|
|
1152
|
+
return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"},${this.isRealTime ? "1" : "0"}`;
|
|
661
1153
|
}
|
|
662
1154
|
/** Called by system call handler when $sys.Ack is received from the client. */
|
|
663
|
-
onAck(
|
|
1155
|
+
onAck(nextIndex, _hostId) {
|
|
664
1156
|
if (!this._started.isCompleted) {
|
|
665
1157
|
this._started.resolve();
|
|
666
1158
|
}
|
|
1159
|
+
if (nextIndex > this._lastAckedIndex) {
|
|
1160
|
+
this._lastAckedIndex = nextIndex;
|
|
1161
|
+
}
|
|
1162
|
+
if (this._ackWaiting) {
|
|
1163
|
+
this._ackWaiting.resolve();
|
|
1164
|
+
this._ackWaiting = null;
|
|
1165
|
+
}
|
|
667
1166
|
}
|
|
668
1167
|
/** Called by system call handler when $sys.AckEnd is received from the client. */
|
|
669
1168
|
onAckEnd(_hostId) {
|
|
@@ -675,7 +1174,13 @@ var RpcStreamSender = class {
|
|
|
675
1174
|
if (this._ended) return;
|
|
676
1175
|
const conn = this.peer.connection;
|
|
677
1176
|
if (!conn) return;
|
|
678
|
-
this.peer.hub.systemCallSender.item(
|
|
1177
|
+
this.peer.hub.systemCallSender.item(
|
|
1178
|
+
conn,
|
|
1179
|
+
this.peer.format,
|
|
1180
|
+
this.id.localId,
|
|
1181
|
+
this._nextIndex,
|
|
1182
|
+
item
|
|
1183
|
+
);
|
|
679
1184
|
this._nextIndex++;
|
|
680
1185
|
}
|
|
681
1186
|
/** Send a batch of items to the client. */
|
|
@@ -683,7 +1188,13 @@ var RpcStreamSender = class {
|
|
|
683
1188
|
if (this._ended || items.length === 0) return;
|
|
684
1189
|
const conn = this.peer.connection;
|
|
685
1190
|
if (!conn) return;
|
|
686
|
-
this.peer.hub.systemCallSender.batch(
|
|
1191
|
+
this.peer.hub.systemCallSender.batch(
|
|
1192
|
+
conn,
|
|
1193
|
+
this.peer.format,
|
|
1194
|
+
this.id.localId,
|
|
1195
|
+
this._nextIndex,
|
|
1196
|
+
items
|
|
1197
|
+
);
|
|
687
1198
|
this._nextIndex += items.length;
|
|
688
1199
|
}
|
|
689
1200
|
/** Signal stream completion to the client. */
|
|
@@ -692,19 +1203,63 @@ var RpcStreamSender = class {
|
|
|
692
1203
|
this._ended = true;
|
|
693
1204
|
const conn = this.peer.connection;
|
|
694
1205
|
if (!conn) return;
|
|
695
|
-
const errorInfo = error ? { Message: error.message } :
|
|
696
|
-
this.peer.hub.systemCallSender.end(
|
|
1206
|
+
const errorInfo = error ? { TypeRef: "System.Exception", Message: error.message } : { TypeRef: "", Message: "" };
|
|
1207
|
+
this.peer.hub.systemCallSender.end(
|
|
1208
|
+
conn,
|
|
1209
|
+
this.peer.format,
|
|
1210
|
+
this.id.localId,
|
|
1211
|
+
this._nextIndex,
|
|
1212
|
+
errorInfo
|
|
1213
|
+
);
|
|
697
1214
|
}
|
|
698
1215
|
/**
|
|
699
1216
|
* Consume an AsyncIterable and send all items to the client.
|
|
700
1217
|
* Waits for the client's initial Ack before starting to pump items.
|
|
1218
|
+
*
|
|
1219
|
+
* When `isRealTime` is true, applies flow control based on `ackAdvance`:
|
|
1220
|
+
* if the sender is `ackAdvance` items ahead of the last ACK, it enters
|
|
1221
|
+
* skip mode — draining the source and discarding items until it finds
|
|
1222
|
+
* one where `canSkipTo` returns true.
|
|
701
1223
|
*/
|
|
702
1224
|
async writeFrom(source) {
|
|
703
1225
|
await this._started.promise;
|
|
1226
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
704
1227
|
try {
|
|
705
|
-
|
|
1228
|
+
while (true) {
|
|
1229
|
+
const next = await iterator.next();
|
|
1230
|
+
if (next.done || this._ended) break;
|
|
1231
|
+
const item = next.value;
|
|
1232
|
+
if (this._nextIndex < this._lastAckedIndex + this.ackAdvance) {
|
|
1233
|
+
this.sendItem(item);
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
if (!this.isRealTime) {
|
|
1237
|
+
await this._waitForAckBudget();
|
|
1238
|
+
if (this._ended) return;
|
|
1239
|
+
this.sendItem(item);
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
let latestSkipTarget = this.canSkipTo(item) ? item : void 0;
|
|
1243
|
+
let sourceExhausted = false;
|
|
1244
|
+
while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
|
|
1245
|
+
if (this._ended) return;
|
|
1246
|
+
const n = await iterator.next();
|
|
1247
|
+
if (n.done) {
|
|
1248
|
+
sourceExhausted = true;
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
if (this.canSkipTo(n.value)) {
|
|
1252
|
+
latestSkipTarget = n.value;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
706
1255
|
if (this._ended) return;
|
|
707
|
-
|
|
1256
|
+
if (latestSkipTarget !== void 0) {
|
|
1257
|
+
this.sendItem(latestSkipTarget);
|
|
1258
|
+
}
|
|
1259
|
+
if (sourceExhausted) {
|
|
1260
|
+
if (!this._ended) this.sendEnd();
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
708
1263
|
}
|
|
709
1264
|
if (!this._ended) {
|
|
710
1265
|
this.sendEnd();
|
|
@@ -715,6 +1270,14 @@ var RpcStreamSender = class {
|
|
|
715
1270
|
}
|
|
716
1271
|
}
|
|
717
1272
|
}
|
|
1273
|
+
/** Wait until _nextIndex < _lastAckedIndex + ackAdvance. */
|
|
1274
|
+
async _waitForAckBudget() {
|
|
1275
|
+
while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
|
|
1276
|
+
if (this._ended) return;
|
|
1277
|
+
this._ackWaiting = new PromiseSource4();
|
|
1278
|
+
await this._ackWaiting.promise;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
718
1281
|
// -- IRpcObject --
|
|
719
1282
|
reconnect() {
|
|
720
1283
|
}
|
|
@@ -736,6 +1299,9 @@ var RpcRemoteObjectTracker = class {
|
|
|
736
1299
|
get(localId) {
|
|
737
1300
|
return this._objects.get(localId);
|
|
738
1301
|
}
|
|
1302
|
+
keys() {
|
|
1303
|
+
return this._objects.keys();
|
|
1304
|
+
}
|
|
739
1305
|
unregister(obj) {
|
|
740
1306
|
this._objects.delete(obj.id.localId);
|
|
741
1307
|
}
|
|
@@ -747,10 +1313,8 @@ var RpcRemoteObjectTracker = class {
|
|
|
747
1313
|
}
|
|
748
1314
|
reconnectAll() {
|
|
749
1315
|
for (const obj of this._objects.values()) {
|
|
750
|
-
if (obj.allowReconnect)
|
|
751
|
-
|
|
752
|
-
else
|
|
753
|
-
obj.disconnect();
|
|
1316
|
+
if (obj.allowReconnect) obj.reconnect();
|
|
1317
|
+
else obj.disconnect();
|
|
754
1318
|
}
|
|
755
1319
|
}
|
|
756
1320
|
};
|
|
@@ -768,6 +1332,9 @@ var RpcSharedObjectTracker = class {
|
|
|
768
1332
|
get(localId) {
|
|
769
1333
|
return this._objects.get(localId);
|
|
770
1334
|
}
|
|
1335
|
+
keys() {
|
|
1336
|
+
return this._objects.keys();
|
|
1337
|
+
}
|
|
771
1338
|
unregister(obj) {
|
|
772
1339
|
this._objects.delete(obj.id.localId);
|
|
773
1340
|
}
|
|
@@ -791,8 +1358,132 @@ var RpcClientPeerReconnectDelayer = class extends RetryDelayer {
|
|
|
791
1358
|
}
|
|
792
1359
|
};
|
|
793
1360
|
|
|
1361
|
+
// src/rpc-serialization-format.ts
|
|
1362
|
+
import { Decoder as Decoder3 } from "@msgpack/msgpack";
|
|
1363
|
+
var RpcSerializationFormat = class _RpcSerializationFormat {
|
|
1364
|
+
/** Create a reusable binary encoder for this format. Returns undefined for text formats. */
|
|
1365
|
+
createEncoder() {
|
|
1366
|
+
return void 0;
|
|
1367
|
+
}
|
|
1368
|
+
/** Create a reusable binary decoder for this format. Returns undefined for text formats. */
|
|
1369
|
+
createDecoder() {
|
|
1370
|
+
return void 0;
|
|
1371
|
+
}
|
|
1372
|
+
// --- Static registry ---
|
|
1373
|
+
static _all = /* @__PURE__ */ new Map();
|
|
1374
|
+
static register(format) {
|
|
1375
|
+
_RpcSerializationFormat._all.set(format.key, format);
|
|
1376
|
+
}
|
|
1377
|
+
static get(key) {
|
|
1378
|
+
const format = _RpcSerializationFormat._all.get(key);
|
|
1379
|
+
if (!format)
|
|
1380
|
+
throw new Error(`Unknown RPC serialization format: "${key}"`);
|
|
1381
|
+
return format;
|
|
1382
|
+
}
|
|
1383
|
+
static tryGet(key) {
|
|
1384
|
+
return _RpcSerializationFormat._all.get(key);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
var RpcJsonSerializationFormat = class extends RpcSerializationFormat {
|
|
1388
|
+
key;
|
|
1389
|
+
isBinary = false;
|
|
1390
|
+
isCompact = false;
|
|
1391
|
+
constructor(key) {
|
|
1392
|
+
super();
|
|
1393
|
+
this.key = key;
|
|
1394
|
+
}
|
|
1395
|
+
serializeMessage(message, args) {
|
|
1396
|
+
return serializeMessage(message, args);
|
|
1397
|
+
}
|
|
1398
|
+
deserializeTextMessage(raw) {
|
|
1399
|
+
return deserializeMessage(raw);
|
|
1400
|
+
}
|
|
1401
|
+
splitBinaryFrame() {
|
|
1402
|
+
throw new Error("Text format does not support binary frames");
|
|
1403
|
+
}
|
|
1404
|
+
serializeBinaryFrame() {
|
|
1405
|
+
throw new Error("Text format does not support binary frames");
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
var RpcMessagePackSerializationFormat = class extends RpcSerializationFormat {
|
|
1409
|
+
key;
|
|
1410
|
+
isBinary = true;
|
|
1411
|
+
isCompact = false;
|
|
1412
|
+
constructor(key) {
|
|
1413
|
+
super();
|
|
1414
|
+
this.key = key;
|
|
1415
|
+
}
|
|
1416
|
+
serializeMessage(message, args, encoder) {
|
|
1417
|
+
return serializeBinaryMessage(message, args, encoder);
|
|
1418
|
+
}
|
|
1419
|
+
deserializeTextMessage(raw) {
|
|
1420
|
+
return deserializeMessage(raw);
|
|
1421
|
+
}
|
|
1422
|
+
splitBinaryFrame(frame, decoder) {
|
|
1423
|
+
return splitBinaryFrame(frame, decoder);
|
|
1424
|
+
}
|
|
1425
|
+
serializeBinaryFrame(messages) {
|
|
1426
|
+
return serializeBinaryFrame(messages);
|
|
1427
|
+
}
|
|
1428
|
+
createEncoder() {
|
|
1429
|
+
return createBinaryEncoder();
|
|
1430
|
+
}
|
|
1431
|
+
createDecoder() {
|
|
1432
|
+
return new Decoder3();
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
var RpcMessagePackCompactSerializationFormat = class extends RpcSerializationFormat {
|
|
1436
|
+
key;
|
|
1437
|
+
isBinary = true;
|
|
1438
|
+
isCompact = true;
|
|
1439
|
+
constructor(key) {
|
|
1440
|
+
super();
|
|
1441
|
+
this.key = key;
|
|
1442
|
+
}
|
|
1443
|
+
serializeMessage(message, args, encoder, registry) {
|
|
1444
|
+
return serializeCompactBinaryMessage(
|
|
1445
|
+
message,
|
|
1446
|
+
args,
|
|
1447
|
+
registry,
|
|
1448
|
+
encoder
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
deserializeTextMessage(raw) {
|
|
1452
|
+
return deserializeMessage(raw);
|
|
1453
|
+
}
|
|
1454
|
+
splitBinaryFrame(frame, decoder, registry) {
|
|
1455
|
+
return splitCompactBinaryFrame(frame, registry, decoder);
|
|
1456
|
+
}
|
|
1457
|
+
serializeBinaryFrame(messages) {
|
|
1458
|
+
return serializeBinaryFrame(messages);
|
|
1459
|
+
}
|
|
1460
|
+
createEncoder() {
|
|
1461
|
+
return createBinaryEncoder();
|
|
1462
|
+
}
|
|
1463
|
+
createDecoder() {
|
|
1464
|
+
return new Decoder3();
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5"));
|
|
1468
|
+
RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5np"));
|
|
1469
|
+
RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5"));
|
|
1470
|
+
RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5np"));
|
|
1471
|
+
RpcSerializationFormat.register(
|
|
1472
|
+
new RpcMessagePackSerializationFormat("msgpack6")
|
|
1473
|
+
);
|
|
1474
|
+
RpcSerializationFormat.register(
|
|
1475
|
+
new RpcMessagePackSerializationFormat("mempack6")
|
|
1476
|
+
);
|
|
1477
|
+
RpcSerializationFormat.register(
|
|
1478
|
+
new RpcMessagePackCompactSerializationFormat("msgpack6c")
|
|
1479
|
+
);
|
|
1480
|
+
RpcSerializationFormat.register(
|
|
1481
|
+
new RpcMessagePackCompactSerializationFormat("mempack6c")
|
|
1482
|
+
);
|
|
1483
|
+
|
|
794
1484
|
// src/rpc-peer.ts
|
|
795
1485
|
var DEFAULT_SERIALIZATION_FORMAT = "json5np";
|
|
1486
|
+
var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
|
|
796
1487
|
var defaultConnectionUrlResolver = (peer) => {
|
|
797
1488
|
const sep = peer.ref.includes("?") ? "&" : "?";
|
|
798
1489
|
return peer.ref + sep + `clientId=${peer.clientId}&f=${peer.serializationFormat}`;
|
|
@@ -838,17 +1529,27 @@ var RpcPeer = class {
|
|
|
838
1529
|
this._startKeepAlive();
|
|
839
1530
|
});
|
|
840
1531
|
}
|
|
1532
|
+
/** The serialization format used by this peer. Override in subclasses. */
|
|
1533
|
+
get format() {
|
|
1534
|
+
return RpcSerializationFormat.get("json5np");
|
|
1535
|
+
}
|
|
841
1536
|
call(method, args, options) {
|
|
842
1537
|
const callId = this.outbound.nextId();
|
|
843
1538
|
const outboundCall = options?.outboundCallFactory ? options.outboundCallFactory(callId, method) : new RpcOutboundCall(callId, method);
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
1539
|
+
const envelope = {
|
|
1540
|
+
Method: method,
|
|
1541
|
+
RelatedId: callId,
|
|
1542
|
+
CallType: options?.callTypeId ?? 0
|
|
1543
|
+
};
|
|
1544
|
+
outboundCall.serializedWireData = this.format.serializeMessage(
|
|
1545
|
+
envelope,
|
|
1546
|
+
args,
|
|
1547
|
+
this._connection?.encoder,
|
|
1548
|
+
this._hub.registry
|
|
847
1549
|
);
|
|
848
|
-
outboundCall.serializedMessage = msg;
|
|
849
1550
|
if (this._connection !== void 0) {
|
|
850
1551
|
this.outbound.register(outboundCall);
|
|
851
|
-
this.
|
|
1552
|
+
this._sendWireData(outboundCall.serializedWireData);
|
|
852
1553
|
} else {
|
|
853
1554
|
this._pendingSends.push(outboundCall);
|
|
854
1555
|
}
|
|
@@ -862,12 +1563,16 @@ var RpcPeer = class {
|
|
|
862
1563
|
outboundCall.result.reject(new Error("Call cancelled."));
|
|
863
1564
|
outboundCall.onDisconnect();
|
|
864
1565
|
if (peer._connection !== void 0)
|
|
865
|
-
hub.systemCallSender.cancel(peer._connection, callId);
|
|
1566
|
+
hub.systemCallSender.cancel(peer._connection, peer.format, callId);
|
|
866
1567
|
} else {
|
|
867
|
-
const idx = peer._pendingSends.findIndex(
|
|
1568
|
+
const idx = peer._pendingSends.findIndex(
|
|
1569
|
+
(c) => c.callId === callId
|
|
1570
|
+
);
|
|
868
1571
|
if (idx !== -1) {
|
|
869
1572
|
peer._pendingSends.splice(idx, 1);
|
|
870
|
-
outboundCall.result.reject(
|
|
1573
|
+
outboundCall.result.reject(
|
|
1574
|
+
new Error("Call cancelled.")
|
|
1575
|
+
);
|
|
871
1576
|
outboundCall.onDisconnect();
|
|
872
1577
|
}
|
|
873
1578
|
}
|
|
@@ -879,8 +1584,14 @@ var RpcPeer = class {
|
|
|
879
1584
|
}
|
|
880
1585
|
callNoWait(method, args) {
|
|
881
1586
|
if (this._connection === void 0) return;
|
|
882
|
-
const
|
|
883
|
-
this.
|
|
1587
|
+
const envelope = { Method: method, RelatedId: 0 };
|
|
1588
|
+
const wireData = this.format.serializeMessage(
|
|
1589
|
+
envelope,
|
|
1590
|
+
args,
|
|
1591
|
+
this._connection.encoder,
|
|
1592
|
+
this._hub.registry
|
|
1593
|
+
);
|
|
1594
|
+
this._sendWireData(wireData);
|
|
884
1595
|
}
|
|
885
1596
|
close() {
|
|
886
1597
|
this._stopKeepAlive();
|
|
@@ -899,23 +1610,41 @@ var RpcPeer = class {
|
|
|
899
1610
|
}
|
|
900
1611
|
/** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
|
|
901
1612
|
_flushPendingSends() {
|
|
902
|
-
if (this._pendingSends.length === 0 || this._connection === void 0)
|
|
1613
|
+
if (this._pendingSends.length === 0 || this._connection === void 0)
|
|
1614
|
+
return;
|
|
903
1615
|
for (const call of this._pendingSends) {
|
|
904
1616
|
this.outbound.register(call);
|
|
905
|
-
this.
|
|
1617
|
+
this._sendWireData(call.serializedWireData);
|
|
906
1618
|
}
|
|
907
1619
|
this._pendingSends.length = 0;
|
|
908
1620
|
}
|
|
1621
|
+
/** Send pre-serialized wire data through the current connection. */
|
|
1622
|
+
_sendWireData(data) {
|
|
1623
|
+
if (this._connection === void 0) return;
|
|
1624
|
+
if (typeof data === "string") {
|
|
1625
|
+
this._connection.send(data);
|
|
1626
|
+
} else {
|
|
1627
|
+
this._connection.sendBinary(data);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
909
1630
|
/** Override in subclasses to handle the remote peer's handshake response. */
|
|
910
1631
|
_onHandshakeReceived(_handshake) {
|
|
911
1632
|
}
|
|
912
|
-
_handleMessage(
|
|
913
|
-
|
|
1633
|
+
_handleMessage(received) {
|
|
1634
|
+
let message;
|
|
1635
|
+
let args;
|
|
1636
|
+
if (received.kind === "binary") {
|
|
1637
|
+
message = received.message;
|
|
1638
|
+
args = received.args;
|
|
1639
|
+
} else {
|
|
1640
|
+
const parsed = deserializeMessage(received.raw);
|
|
1641
|
+
message = parsed.message;
|
|
1642
|
+
args = parsed.args;
|
|
1643
|
+
}
|
|
914
1644
|
const method = message.Method ?? "";
|
|
915
1645
|
if (method === RpcSystemCalls.handshake) {
|
|
916
1646
|
const handshake = args[0];
|
|
917
|
-
if (handshake !== void 0)
|
|
918
|
-
this._onHandshakeReceived(handshake);
|
|
1647
|
+
if (handshake !== void 0) this._onHandshakeReceived(handshake);
|
|
919
1648
|
return;
|
|
920
1649
|
}
|
|
921
1650
|
if (method.startsWith("$sys")) {
|
|
@@ -937,19 +1666,42 @@ var RpcPeer = class {
|
|
|
937
1666
|
if (serviceHost !== void 0) {
|
|
938
1667
|
void (async () => {
|
|
939
1668
|
try {
|
|
940
|
-
const context = this._connection !== void 0 ? {
|
|
941
|
-
|
|
1669
|
+
const context = this._connection !== void 0 ? {
|
|
1670
|
+
__rpcDispatch: true,
|
|
1671
|
+
callId: relatedId,
|
|
1672
|
+
connection: this._connection
|
|
1673
|
+
} : void 0;
|
|
1674
|
+
const result = await serviceHost.dispatch(
|
|
1675
|
+
method,
|
|
1676
|
+
args,
|
|
1677
|
+
context
|
|
1678
|
+
);
|
|
942
1679
|
if (methodDef?.stream === true && this._connection !== void 0) {
|
|
943
1680
|
const sender = new RpcStreamSender(this);
|
|
944
1681
|
this.sharedObjects.register(sender);
|
|
945
|
-
this._hub.systemCallSender.ok(
|
|
1682
|
+
this._hub.systemCallSender.ok(
|
|
1683
|
+
this._connection,
|
|
1684
|
+
this.format,
|
|
1685
|
+
relatedId,
|
|
1686
|
+
sender.toRef()
|
|
1687
|
+
);
|
|
946
1688
|
void sender.writeFrom(result);
|
|
947
1689
|
} else if (!isNoWait && this._connection !== void 0) {
|
|
948
|
-
this._hub.systemCallSender.ok(
|
|
1690
|
+
this._hub.systemCallSender.ok(
|
|
1691
|
+
this._connection,
|
|
1692
|
+
this.format,
|
|
1693
|
+
relatedId,
|
|
1694
|
+
result
|
|
1695
|
+
);
|
|
949
1696
|
}
|
|
950
1697
|
} catch (e) {
|
|
951
1698
|
if (!isNoWait && this._connection !== void 0) {
|
|
952
|
-
this._hub.systemCallSender.error(
|
|
1699
|
+
this._hub.systemCallSender.error(
|
|
1700
|
+
this._connection,
|
|
1701
|
+
this.format,
|
|
1702
|
+
relatedId,
|
|
1703
|
+
e
|
|
1704
|
+
);
|
|
953
1705
|
}
|
|
954
1706
|
} finally {
|
|
955
1707
|
if (!isNoWait) {
|
|
@@ -962,7 +1714,9 @@ var RpcPeer = class {
|
|
|
962
1714
|
_startKeepAlive() {
|
|
963
1715
|
this._keepAliveTimer = setInterval(() => {
|
|
964
1716
|
if (this._connection !== void 0) {
|
|
965
|
-
this._hub.systemCallSender.keepAlive(this._connection, this.
|
|
1717
|
+
this._hub.systemCallSender.keepAlive(this._connection, this.format, [
|
|
1718
|
+
...this.remoteObjects.keys()
|
|
1719
|
+
]);
|
|
966
1720
|
}
|
|
967
1721
|
}, 15e3);
|
|
968
1722
|
}
|
|
@@ -998,6 +1752,8 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
998
1752
|
/** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
|
|
999
1753
|
connectionUrlResolver = defaultConnectionUrlResolver;
|
|
1000
1754
|
peerChanged = new EventHandlerSet3();
|
|
1755
|
+
/** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
|
|
1756
|
+
unsupportedFormat = new EventHandlerSet3();
|
|
1001
1757
|
reconnectDelayer = new RpcClientPeerReconnectDelayer();
|
|
1002
1758
|
reconnectsAtChanged = new EventHandlerSet3();
|
|
1003
1759
|
get reconnectsAt() {
|
|
@@ -1008,10 +1764,15 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
1008
1764
|
this._reconnectsAt = value;
|
|
1009
1765
|
this.reconnectsAtChanged.trigger();
|
|
1010
1766
|
}
|
|
1767
|
+
_format;
|
|
1011
1768
|
constructor(hub, url, serializationFormat) {
|
|
1012
1769
|
super(url, hub);
|
|
1013
1770
|
this.clientId = guidToBase64Url(this.id);
|
|
1014
1771
|
this.serializationFormat = serializationFormat ?? DEFAULT_SERIALIZATION_FORMAT;
|
|
1772
|
+
this._format = RpcSerializationFormat.get(this.serializationFormat);
|
|
1773
|
+
}
|
|
1774
|
+
get format() {
|
|
1775
|
+
return this._format;
|
|
1015
1776
|
}
|
|
1016
1777
|
get connectionKind() {
|
|
1017
1778
|
return this._connectionKind;
|
|
@@ -1025,18 +1786,39 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
1025
1786
|
async run(wsFactory) {
|
|
1026
1787
|
const connUrl = this.connectionUrlResolver(this);
|
|
1027
1788
|
while (!this._disposed) {
|
|
1789
|
+
let lastCloseCode = 0;
|
|
1790
|
+
let lastCloseReason = "";
|
|
1028
1791
|
try {
|
|
1029
1792
|
const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
|
|
1030
|
-
const conn = new RpcWebSocketConnection(
|
|
1793
|
+
const conn = new RpcWebSocketConnection(
|
|
1794
|
+
ws,
|
|
1795
|
+
this.format.isBinary,
|
|
1796
|
+
this.format,
|
|
1797
|
+
this._hub.registry
|
|
1798
|
+
);
|
|
1031
1799
|
this._connectionKind = 1 /* Connecting */;
|
|
1800
|
+
conn.closed.add((ev) => {
|
|
1801
|
+
lastCloseCode = ev.code;
|
|
1802
|
+
lastCloseReason = ev.reason;
|
|
1803
|
+
});
|
|
1032
1804
|
this._pendingHandshake = new PromiseSource5();
|
|
1033
1805
|
this.setupConnection(conn);
|
|
1034
1806
|
this._connection = void 0;
|
|
1035
|
-
const closedRejection = new Promise(
|
|
1807
|
+
const closedRejection = new Promise(
|
|
1808
|
+
(_, reject) => conn.closed.add(
|
|
1809
|
+
() => reject(new Error("Connection failed"))
|
|
1810
|
+
)
|
|
1811
|
+
);
|
|
1036
1812
|
closedRejection.catch(() => {
|
|
1037
1813
|
});
|
|
1038
1814
|
await Promise.race([conn.whenConnected, closedRejection]);
|
|
1039
|
-
this._hub.systemCallSender.handshake(
|
|
1815
|
+
this._hub.systemCallSender.handshake(
|
|
1816
|
+
conn,
|
|
1817
|
+
this.format,
|
|
1818
|
+
this.id,
|
|
1819
|
+
this._hub.hubId,
|
|
1820
|
+
++this._handshakeIndex
|
|
1821
|
+
);
|
|
1040
1822
|
const remoteHandshake = await Promise.race([
|
|
1041
1823
|
this._pendingHandshake.promise,
|
|
1042
1824
|
closedRejection
|
|
@@ -1061,6 +1843,11 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
1061
1843
|
}
|
|
1062
1844
|
this._connectionKind = 0 /* Disconnected */;
|
|
1063
1845
|
if (this._disposed) break;
|
|
1846
|
+
if (lastCloseCode === RPC_CLOSE_CODE_UNSUPPORTED_FORMAT) {
|
|
1847
|
+
this.unsupportedFormat.trigger({ reason: lastCloseReason });
|
|
1848
|
+
this._disposed = true;
|
|
1849
|
+
break;
|
|
1850
|
+
}
|
|
1064
1851
|
this._tryIndex++;
|
|
1065
1852
|
const delay = this.reconnectDelayer.getDelay(this._tryIndex);
|
|
1066
1853
|
if (delay.isLimitExceeded) {
|
|
@@ -1084,7 +1871,6 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
1084
1871
|
* Regular in-flight calls are re-sent transparently. */
|
|
1085
1872
|
_reconnect(_isPeerChanged) {
|
|
1086
1873
|
if (this._connection === void 0) return;
|
|
1087
|
-
const conn = this._connection;
|
|
1088
1874
|
if (_isPeerChanged) {
|
|
1089
1875
|
this.remoteObjects.disconnectAll();
|
|
1090
1876
|
} else {
|
|
@@ -1096,7 +1882,7 @@ var RpcClientPeer = class extends RpcPeer {
|
|
|
1096
1882
|
call.onDisconnect();
|
|
1097
1883
|
this.outbound.remove(call.callId);
|
|
1098
1884
|
} else {
|
|
1099
|
-
|
|
1885
|
+
this._sendWireData(call.serializedWireData);
|
|
1100
1886
|
}
|
|
1101
1887
|
}
|
|
1102
1888
|
this._flushPendingSends();
|
|
@@ -1119,7 +1905,13 @@ var RpcServerPeer = class extends RpcPeer {
|
|
|
1119
1905
|
}
|
|
1120
1906
|
_onHandshakeReceived(_handshake) {
|
|
1121
1907
|
if (this._connection !== void 0) {
|
|
1122
|
-
this._hub.systemCallSender.handshake(
|
|
1908
|
+
this._hub.systemCallSender.handshake(
|
|
1909
|
+
this._connection,
|
|
1910
|
+
this.format,
|
|
1911
|
+
this.id,
|
|
1912
|
+
this._hub.hubId,
|
|
1913
|
+
0
|
|
1914
|
+
);
|
|
1123
1915
|
}
|
|
1124
1916
|
}
|
|
1125
1917
|
};
|
|
@@ -1147,12 +1939,16 @@ var RpcServiceHost = class {
|
|
|
1147
1939
|
for (const methodDef of def.methods.values()) {
|
|
1148
1940
|
const fn = impl[methodDef.name];
|
|
1149
1941
|
if (!fn) continue;
|
|
1150
|
-
this._methods.set(wireMethodName(methodDef), {
|
|
1942
|
+
this._methods.set(wireMethodName(methodDef), {
|
|
1943
|
+
def: methodDef,
|
|
1944
|
+
fn
|
|
1945
|
+
});
|
|
1151
1946
|
}
|
|
1152
1947
|
}
|
|
1153
1948
|
async dispatch(wireMethod, args, context) {
|
|
1154
1949
|
const entry = this._methods.get(wireMethod);
|
|
1155
|
-
if (entry === void 0)
|
|
1950
|
+
if (entry === void 0)
|
|
1951
|
+
throw new Error(`Method not found: ${wireMethod}`);
|
|
1156
1952
|
if (context !== void 0 && entry.def.callTypeId !== 0) {
|
|
1157
1953
|
return await entry.fn(...args, context);
|
|
1158
1954
|
}
|
|
@@ -1191,6 +1987,539 @@ function rpcMethod(options) {
|
|
|
1191
1987
|
};
|
|
1192
1988
|
}
|
|
1193
1989
|
|
|
1990
|
+
// src/rpc-xxhash3.ts
|
|
1991
|
+
var U64_MASK = 0xffffffffffffffffn;
|
|
1992
|
+
var U32_MASK = 0xffffffffn;
|
|
1993
|
+
var PRIME32_1 = 2654435761;
|
|
1994
|
+
var PRIME32_2 = 2246822519;
|
|
1995
|
+
var PRIME32_3 = 3266489917;
|
|
1996
|
+
var PRIME64_1 = 0x9e3779b185ebca87n;
|
|
1997
|
+
var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
|
|
1998
|
+
var PRIME64_3 = 0x165667b19e3779f9n;
|
|
1999
|
+
var PRIME64_4 = 0x85ebca77c2b2ae63n;
|
|
2000
|
+
var PRIME64_5 = 0x27d4eb2f165667c5n;
|
|
2001
|
+
var XXH3_SECRET_SIZE_MIN = 136;
|
|
2002
|
+
var XXH_SECRET_DEFAULT_SIZE = 192;
|
|
2003
|
+
var STRIPE_LEN = 64;
|
|
2004
|
+
var XXH_SECRET_CONSUME_RATE = 8;
|
|
2005
|
+
var ACC_NB = STRIPE_LEN / 8;
|
|
2006
|
+
var XXH3_MIDSIZE_MAX = 240;
|
|
2007
|
+
var XXH3_MIDSIZE_STARTOFFSET = 3;
|
|
2008
|
+
var XXH3_MIDSIZE_LASTOFFSET = 17;
|
|
2009
|
+
var XXH_SECRET_LASTACC_START = 7;
|
|
2010
|
+
var XXH_SECRET_MERGEACCS_START = 11;
|
|
2011
|
+
var RRMXMX = 0x9fb21c651e98df25n;
|
|
2012
|
+
var DEFAULT_SECRET = new Uint8Array([
|
|
2013
|
+
184,
|
|
2014
|
+
254,
|
|
2015
|
+
108,
|
|
2016
|
+
57,
|
|
2017
|
+
35,
|
|
2018
|
+
164,
|
|
2019
|
+
75,
|
|
2020
|
+
190,
|
|
2021
|
+
124,
|
|
2022
|
+
1,
|
|
2023
|
+
129,
|
|
2024
|
+
44,
|
|
2025
|
+
247,
|
|
2026
|
+
33,
|
|
2027
|
+
173,
|
|
2028
|
+
28,
|
|
2029
|
+
222,
|
|
2030
|
+
212,
|
|
2031
|
+
109,
|
|
2032
|
+
233,
|
|
2033
|
+
131,
|
|
2034
|
+
144,
|
|
2035
|
+
151,
|
|
2036
|
+
219,
|
|
2037
|
+
114,
|
|
2038
|
+
64,
|
|
2039
|
+
164,
|
|
2040
|
+
164,
|
|
2041
|
+
183,
|
|
2042
|
+
179,
|
|
2043
|
+
103,
|
|
2044
|
+
31,
|
|
2045
|
+
203,
|
|
2046
|
+
121,
|
|
2047
|
+
230,
|
|
2048
|
+
78,
|
|
2049
|
+
204,
|
|
2050
|
+
192,
|
|
2051
|
+
229,
|
|
2052
|
+
120,
|
|
2053
|
+
130,
|
|
2054
|
+
90,
|
|
2055
|
+
208,
|
|
2056
|
+
125,
|
|
2057
|
+
204,
|
|
2058
|
+
255,
|
|
2059
|
+
114,
|
|
2060
|
+
33,
|
|
2061
|
+
184,
|
|
2062
|
+
8,
|
|
2063
|
+
70,
|
|
2064
|
+
116,
|
|
2065
|
+
247,
|
|
2066
|
+
67,
|
|
2067
|
+
36,
|
|
2068
|
+
142,
|
|
2069
|
+
224,
|
|
2070
|
+
53,
|
|
2071
|
+
144,
|
|
2072
|
+
230,
|
|
2073
|
+
129,
|
|
2074
|
+
58,
|
|
2075
|
+
38,
|
|
2076
|
+
76,
|
|
2077
|
+
60,
|
|
2078
|
+
40,
|
|
2079
|
+
82,
|
|
2080
|
+
187,
|
|
2081
|
+
145,
|
|
2082
|
+
195,
|
|
2083
|
+
0,
|
|
2084
|
+
203,
|
|
2085
|
+
136,
|
|
2086
|
+
208,
|
|
2087
|
+
101,
|
|
2088
|
+
139,
|
|
2089
|
+
27,
|
|
2090
|
+
83,
|
|
2091
|
+
46,
|
|
2092
|
+
163,
|
|
2093
|
+
113,
|
|
2094
|
+
100,
|
|
2095
|
+
72,
|
|
2096
|
+
151,
|
|
2097
|
+
162,
|
|
2098
|
+
13,
|
|
2099
|
+
249,
|
|
2100
|
+
78,
|
|
2101
|
+
56,
|
|
2102
|
+
25,
|
|
2103
|
+
239,
|
|
2104
|
+
70,
|
|
2105
|
+
169,
|
|
2106
|
+
222,
|
|
2107
|
+
172,
|
|
2108
|
+
216,
|
|
2109
|
+
168,
|
|
2110
|
+
250,
|
|
2111
|
+
118,
|
|
2112
|
+
63,
|
|
2113
|
+
227,
|
|
2114
|
+
156,
|
|
2115
|
+
52,
|
|
2116
|
+
63,
|
|
2117
|
+
249,
|
|
2118
|
+
220,
|
|
2119
|
+
187,
|
|
2120
|
+
199,
|
|
2121
|
+
199,
|
|
2122
|
+
11,
|
|
2123
|
+
79,
|
|
2124
|
+
29,
|
|
2125
|
+
138,
|
|
2126
|
+
81,
|
|
2127
|
+
224,
|
|
2128
|
+
75,
|
|
2129
|
+
205,
|
|
2130
|
+
180,
|
|
2131
|
+
89,
|
|
2132
|
+
49,
|
|
2133
|
+
200,
|
|
2134
|
+
159,
|
|
2135
|
+
126,
|
|
2136
|
+
201,
|
|
2137
|
+
217,
|
|
2138
|
+
120,
|
|
2139
|
+
115,
|
|
2140
|
+
100,
|
|
2141
|
+
234,
|
|
2142
|
+
197,
|
|
2143
|
+
172,
|
|
2144
|
+
131,
|
|
2145
|
+
52,
|
|
2146
|
+
211,
|
|
2147
|
+
235,
|
|
2148
|
+
195,
|
|
2149
|
+
197,
|
|
2150
|
+
129,
|
|
2151
|
+
160,
|
|
2152
|
+
255,
|
|
2153
|
+
250,
|
|
2154
|
+
19,
|
|
2155
|
+
99,
|
|
2156
|
+
235,
|
|
2157
|
+
23,
|
|
2158
|
+
13,
|
|
2159
|
+
221,
|
|
2160
|
+
81,
|
|
2161
|
+
183,
|
|
2162
|
+
240,
|
|
2163
|
+
218,
|
|
2164
|
+
73,
|
|
2165
|
+
211,
|
|
2166
|
+
22,
|
|
2167
|
+
85,
|
|
2168
|
+
38,
|
|
2169
|
+
41,
|
|
2170
|
+
212,
|
|
2171
|
+
104,
|
|
2172
|
+
158,
|
|
2173
|
+
43,
|
|
2174
|
+
22,
|
|
2175
|
+
190,
|
|
2176
|
+
88,
|
|
2177
|
+
125,
|
|
2178
|
+
71,
|
|
2179
|
+
161,
|
|
2180
|
+
252,
|
|
2181
|
+
143,
|
|
2182
|
+
248,
|
|
2183
|
+
184,
|
|
2184
|
+
209,
|
|
2185
|
+
122,
|
|
2186
|
+
208,
|
|
2187
|
+
49,
|
|
2188
|
+
206,
|
|
2189
|
+
69,
|
|
2190
|
+
203,
|
|
2191
|
+
58,
|
|
2192
|
+
143,
|
|
2193
|
+
149,
|
|
2194
|
+
22,
|
|
2195
|
+
4,
|
|
2196
|
+
40,
|
|
2197
|
+
175,
|
|
2198
|
+
215,
|
|
2199
|
+
251,
|
|
2200
|
+
202,
|
|
2201
|
+
187,
|
|
2202
|
+
75,
|
|
2203
|
+
64,
|
|
2204
|
+
126
|
|
2205
|
+
]);
|
|
2206
|
+
function u64(x) {
|
|
2207
|
+
return x & U64_MASK;
|
|
2208
|
+
}
|
|
2209
|
+
function read32LE(buf, off) {
|
|
2210
|
+
return (buf[off] | buf[off + 1] << 8 | buf[off + 2] << 16 | buf[off + 3] << 24) >>> 0;
|
|
2211
|
+
}
|
|
2212
|
+
function read64LE(buf, off) {
|
|
2213
|
+
return BigInt(buf[off]) | BigInt(buf[off + 1]) << 8n | BigInt(buf[off + 2]) << 16n | BigInt(buf[off + 3]) << 24n | BigInt(buf[off + 4]) << 32n | BigInt(buf[off + 5]) << 40n | BigInt(buf[off + 6]) << 48n | BigInt(buf[off + 7]) << 56n;
|
|
2214
|
+
}
|
|
2215
|
+
function write64LE(buf, off, value) {
|
|
2216
|
+
let x = u64(value);
|
|
2217
|
+
for (let i = 0; i < 8; i++) {
|
|
2218
|
+
buf[off + i] = Number(x & 0xffn);
|
|
2219
|
+
x >>= 8n;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
function swap32(x) {
|
|
2223
|
+
return (x << 24 & 4278190080 | x << 8 & 16711680 | x >>> 8 & 65280 | x >>> 24 & 255) >>> 0;
|
|
2224
|
+
}
|
|
2225
|
+
function swap64(x) {
|
|
2226
|
+
x = u64(x);
|
|
2227
|
+
return x << 56n & 0xff00000000000000n | x << 40n & 0x00ff000000000000n | x << 24n & 0x0000ff0000000000n | x << 8n & 0x000000ff00000000n | x >> 8n & 0x00000000ff000000n | x >> 24n & 0x0000000000ff0000n | x >> 40n & 0x000000000000ff00n | x >> 56n & 0x00000000000000ffn;
|
|
2228
|
+
}
|
|
2229
|
+
function rotl64(x, amount) {
|
|
2230
|
+
const r = BigInt(amount & 63);
|
|
2231
|
+
return u64(x << r | x >> 64n - r);
|
|
2232
|
+
}
|
|
2233
|
+
function mul128Fold64(lhs, rhs) {
|
|
2234
|
+
const product = u64(lhs) * u64(rhs);
|
|
2235
|
+
return u64(product) ^ u64(product >> 64n);
|
|
2236
|
+
}
|
|
2237
|
+
function xxh64Avalanche(hash) {
|
|
2238
|
+
let h = u64(hash);
|
|
2239
|
+
h ^= h >> 33n;
|
|
2240
|
+
h = u64(h * PRIME64_2);
|
|
2241
|
+
h ^= h >> 29n;
|
|
2242
|
+
h = u64(h * PRIME64_3);
|
|
2243
|
+
h ^= h >> 32n;
|
|
2244
|
+
return u64(h);
|
|
2245
|
+
}
|
|
2246
|
+
function xxh3Avalanche(hash) {
|
|
2247
|
+
let h = u64(hash);
|
|
2248
|
+
h ^= h >> 37n;
|
|
2249
|
+
h = u64(h * 0x165667919e3779f9n);
|
|
2250
|
+
h ^= h >> 32n;
|
|
2251
|
+
return u64(h);
|
|
2252
|
+
}
|
|
2253
|
+
function len0(secret, seed) {
|
|
2254
|
+
const acc = u64(seed ^ read64LE(secret, 56) ^ read64LE(secret, 64));
|
|
2255
|
+
return xxh64Avalanche(acc);
|
|
2256
|
+
}
|
|
2257
|
+
function len1to3(input, length, secret, seed) {
|
|
2258
|
+
const byte1 = input[0];
|
|
2259
|
+
const byte2 = length > 1 ? input[1] : input[0];
|
|
2260
|
+
const byte3 = input[length - 1];
|
|
2261
|
+
const combined = (byte1 << 16 | byte2 << 24 | byte3 | length << 8) >>> 0;
|
|
2262
|
+
const bitflip = u64(
|
|
2263
|
+
BigInt((read32LE(secret, 0) ^ read32LE(secret, 4)) >>> 0) + seed
|
|
2264
|
+
);
|
|
2265
|
+
const value64 = u64(BigInt(combined) ^ bitflip);
|
|
2266
|
+
return xxh64Avalanche(value64);
|
|
2267
|
+
}
|
|
2268
|
+
function len4to8(input, length, secret, seed) {
|
|
2269
|
+
const inputHi = read32LE(input, 0);
|
|
2270
|
+
const inputLo = read32LE(input, length - 4);
|
|
2271
|
+
const input64 = BigInt(inputLo) | BigInt(inputHi) << 32n;
|
|
2272
|
+
let acc = read64LE(secret, 8) ^ read64LE(secret, 16);
|
|
2273
|
+
seed ^= BigInt(swap32(Number(seed & U32_MASK))) << 32n;
|
|
2274
|
+
acc = u64(acc - seed);
|
|
2275
|
+
acc ^= input64;
|
|
2276
|
+
acc ^= rotl64(acc, 49) ^ rotl64(acc, 24);
|
|
2277
|
+
acc = u64(acc * RRMXMX);
|
|
2278
|
+
acc ^= (acc >> 35n) + BigInt(length);
|
|
2279
|
+
acc = u64(acc * RRMXMX);
|
|
2280
|
+
acc ^= acc >> 28n;
|
|
2281
|
+
return u64(acc);
|
|
2282
|
+
}
|
|
2283
|
+
function len9to16(input, length, secret, seed) {
|
|
2284
|
+
let inputLo = read64LE(secret, 24) ^ read64LE(secret, 32);
|
|
2285
|
+
let inputHi = read64LE(secret, 40) ^ read64LE(secret, 48);
|
|
2286
|
+
let acc = BigInt(length);
|
|
2287
|
+
inputLo = u64(inputLo + seed);
|
|
2288
|
+
inputHi = u64(inputHi - seed);
|
|
2289
|
+
inputLo ^= read64LE(input, 0);
|
|
2290
|
+
inputHi ^= read64LE(input, length - 8);
|
|
2291
|
+
acc = u64(acc + swap64(inputLo));
|
|
2292
|
+
acc = u64(acc + inputHi);
|
|
2293
|
+
acc = u64(acc + mul128Fold64(inputLo, inputHi));
|
|
2294
|
+
return xxh3Avalanche(acc);
|
|
2295
|
+
}
|
|
2296
|
+
function mix16B(input, inputOff, secret, secretOff, seed) {
|
|
2297
|
+
let lhs = seed;
|
|
2298
|
+
let rhs = u64(0n - seed);
|
|
2299
|
+
lhs = u64(lhs + read64LE(secret, secretOff));
|
|
2300
|
+
rhs = u64(rhs + read64LE(secret, secretOff + 8));
|
|
2301
|
+
lhs ^= read64LE(input, inputOff);
|
|
2302
|
+
rhs ^= read64LE(input, inputOff + 8);
|
|
2303
|
+
return mul128Fold64(lhs, rhs);
|
|
2304
|
+
}
|
|
2305
|
+
function len17to128(input, length, secret, seed) {
|
|
2306
|
+
let i = Math.floor((length - 1) / 32);
|
|
2307
|
+
let acc = u64(BigInt(length) * PRIME64_1);
|
|
2308
|
+
for (; i >= 0; i--) {
|
|
2309
|
+
acc = u64(acc + mix16B(input, 16 * i, secret, 32 * i, seed));
|
|
2310
|
+
acc = u64(
|
|
2311
|
+
acc + mix16B(
|
|
2312
|
+
input,
|
|
2313
|
+
length - 16 * (i + 1),
|
|
2314
|
+
secret,
|
|
2315
|
+
32 * i + 16,
|
|
2316
|
+
seed
|
|
2317
|
+
)
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
return xxh3Avalanche(acc);
|
|
2321
|
+
}
|
|
2322
|
+
function len129to240(input, length, secret, seed) {
|
|
2323
|
+
let acc = u64(BigInt(length) * PRIME64_1);
|
|
2324
|
+
const nbRounds = Math.floor(length / 16);
|
|
2325
|
+
for (let i = 0; i < 8; i++) {
|
|
2326
|
+
acc = u64(acc + mix16B(input, 16 * i, secret, 16 * i, seed));
|
|
2327
|
+
}
|
|
2328
|
+
acc = xxh3Avalanche(acc);
|
|
2329
|
+
for (let i = 8; i < nbRounds; i++) {
|
|
2330
|
+
acc = u64(
|
|
2331
|
+
acc + mix16B(
|
|
2332
|
+
input,
|
|
2333
|
+
16 * i,
|
|
2334
|
+
secret,
|
|
2335
|
+
16 * (i - 8) + XXH3_MIDSIZE_STARTOFFSET,
|
|
2336
|
+
seed
|
|
2337
|
+
)
|
|
2338
|
+
);
|
|
2339
|
+
}
|
|
2340
|
+
acc = u64(
|
|
2341
|
+
acc + mix16B(
|
|
2342
|
+
input,
|
|
2343
|
+
length - 16,
|
|
2344
|
+
secret,
|
|
2345
|
+
XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET,
|
|
2346
|
+
seed
|
|
2347
|
+
)
|
|
2348
|
+
);
|
|
2349
|
+
return xxh3Avalanche(acc);
|
|
2350
|
+
}
|
|
2351
|
+
function hashShort(input, length, secret, seed) {
|
|
2352
|
+
if (length <= 16) {
|
|
2353
|
+
if (length > 8) return len9to16(input, length, secret, seed);
|
|
2354
|
+
if (length >= 4) return len4to8(input, length, secret, seed);
|
|
2355
|
+
if (length !== 0) return len1to3(input, length, secret, seed);
|
|
2356
|
+
return len0(secret, seed);
|
|
2357
|
+
}
|
|
2358
|
+
if (length <= 128) return len17to128(input, length, secret, seed);
|
|
2359
|
+
return len129to240(input, length, secret, seed);
|
|
2360
|
+
}
|
|
2361
|
+
function accumulate512(acc, input, inputOff, secret, secretOff) {
|
|
2362
|
+
for (let i = 0; i < ACC_NB; i++) {
|
|
2363
|
+
const dataVal = read64LE(input, inputOff + 8 * i);
|
|
2364
|
+
const dataKey = dataVal ^ read64LE(secret, secretOff + 8 * i);
|
|
2365
|
+
acc[i ^ 1] = u64(acc[i ^ 1] + dataVal);
|
|
2366
|
+
const low32 = dataKey & U32_MASK;
|
|
2367
|
+
const high32 = dataKey >> 32n;
|
|
2368
|
+
acc[i] = u64(acc[i] + low32 * high32);
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
function scrambleAcc(acc, secret, secretOff) {
|
|
2372
|
+
for (let i = 0; i < ACC_NB; i++) {
|
|
2373
|
+
let x = acc[i];
|
|
2374
|
+
x ^= x >> 47n;
|
|
2375
|
+
x ^= read64LE(secret, secretOff + 8 * i);
|
|
2376
|
+
x = u64(x * BigInt(PRIME32_1));
|
|
2377
|
+
acc[i] = x;
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
function accumulateLoop(acc, input, inputOff, secret, secretOff, nbStripes) {
|
|
2381
|
+
for (let n = 0; n < nbStripes; n++) {
|
|
2382
|
+
accumulate512(
|
|
2383
|
+
acc,
|
|
2384
|
+
input,
|
|
2385
|
+
inputOff + n * STRIPE_LEN,
|
|
2386
|
+
secret,
|
|
2387
|
+
secretOff + 8 * n
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
function mix2Accs(acc, accOff, secret, secretOff) {
|
|
2392
|
+
return mul128Fold64(
|
|
2393
|
+
acc[accOff] ^ read64LE(secret, secretOff),
|
|
2394
|
+
acc[accOff + 1] ^ read64LE(secret, secretOff + 8)
|
|
2395
|
+
);
|
|
2396
|
+
}
|
|
2397
|
+
function mergeAccs(acc, key, keyOff, start) {
|
|
2398
|
+
let result = start;
|
|
2399
|
+
for (let i = 0; i < 4; i++) {
|
|
2400
|
+
result = u64(result + mix2Accs(acc, 2 * i, key, keyOff + 16 * i));
|
|
2401
|
+
}
|
|
2402
|
+
return xxh3Avalanche(result);
|
|
2403
|
+
}
|
|
2404
|
+
function hashLong(input, length, secret, secretSize) {
|
|
2405
|
+
const nbRounds = Math.floor(
|
|
2406
|
+
(secretSize - STRIPE_LEN) / XXH_SECRET_CONSUME_RATE
|
|
2407
|
+
);
|
|
2408
|
+
const blockLen = STRIPE_LEN * nbRounds;
|
|
2409
|
+
const nbBlocks = Math.floor((length - 1) / blockLen);
|
|
2410
|
+
const nbStripes = Math.floor(
|
|
2411
|
+
(length - 1 - blockLen * nbBlocks) / STRIPE_LEN
|
|
2412
|
+
);
|
|
2413
|
+
const acc = [
|
|
2414
|
+
BigInt(PRIME32_3),
|
|
2415
|
+
PRIME64_1,
|
|
2416
|
+
PRIME64_2,
|
|
2417
|
+
PRIME64_3,
|
|
2418
|
+
PRIME64_4,
|
|
2419
|
+
BigInt(PRIME32_2),
|
|
2420
|
+
PRIME64_5,
|
|
2421
|
+
BigInt(PRIME32_1)
|
|
2422
|
+
];
|
|
2423
|
+
for (let n = 0; n < nbBlocks; n++) {
|
|
2424
|
+
accumulateLoop(acc, input, n * blockLen, secret, 0, nbRounds);
|
|
2425
|
+
scrambleAcc(acc, secret, secretSize - STRIPE_LEN);
|
|
2426
|
+
}
|
|
2427
|
+
accumulateLoop(acc, input, nbBlocks * blockLen, secret, 0, nbStripes);
|
|
2428
|
+
accumulate512(
|
|
2429
|
+
acc,
|
|
2430
|
+
input,
|
|
2431
|
+
length - STRIPE_LEN,
|
|
2432
|
+
secret,
|
|
2433
|
+
secretSize - STRIPE_LEN - XXH_SECRET_LASTACC_START
|
|
2434
|
+
);
|
|
2435
|
+
return mergeAccs(
|
|
2436
|
+
acc,
|
|
2437
|
+
secret,
|
|
2438
|
+
XXH_SECRET_MERGEACCS_START,
|
|
2439
|
+
u64(BigInt(length) * PRIME64_1)
|
|
2440
|
+
);
|
|
2441
|
+
}
|
|
2442
|
+
function hashLongWithSeed(input, length, seed) {
|
|
2443
|
+
const secret = new Uint8Array(XXH_SECRET_DEFAULT_SIZE);
|
|
2444
|
+
for (let i = 0; i < XXH_SECRET_DEFAULT_SIZE / 16; i++) {
|
|
2445
|
+
const off = 16 * i;
|
|
2446
|
+
write64LE(secret, off, u64(read64LE(DEFAULT_SECRET, off) + seed));
|
|
2447
|
+
write64LE(
|
|
2448
|
+
secret,
|
|
2449
|
+
off + 8,
|
|
2450
|
+
u64(read64LE(DEFAULT_SECRET, off + 8) - seed)
|
|
2451
|
+
);
|
|
2452
|
+
}
|
|
2453
|
+
return hashLong(input, length, secret, secret.length);
|
|
2454
|
+
}
|
|
2455
|
+
var textEncoder2 = new TextEncoder();
|
|
2456
|
+
function xxh3_64(input, seed = 0n) {
|
|
2457
|
+
const len = input.length;
|
|
2458
|
+
if (len <= XXH3_MIDSIZE_MAX) {
|
|
2459
|
+
return hashShort(input, len, DEFAULT_SECRET, u64(seed));
|
|
2460
|
+
}
|
|
2461
|
+
return hashLongWithSeed(input, len, u64(seed));
|
|
2462
|
+
}
|
|
2463
|
+
function xxh3_64str(input, seed = 0n) {
|
|
2464
|
+
return xxh3_64(textEncoder2.encode(input), seed);
|
|
2465
|
+
}
|
|
2466
|
+
function computeMethodHash(methodName) {
|
|
2467
|
+
const utf8 = textEncoder2.encode(methodName);
|
|
2468
|
+
const prefixValue = Math.imul(67211, utf8.length) >>> 0;
|
|
2469
|
+
const prefixed = new Uint8Array(4 + utf8.length);
|
|
2470
|
+
prefixed[0] = prefixValue & 255;
|
|
2471
|
+
prefixed[1] = prefixValue >>> 8 & 255;
|
|
2472
|
+
prefixed[2] = prefixValue >>> 16 & 255;
|
|
2473
|
+
prefixed[3] = prefixValue >>> 24 & 255;
|
|
2474
|
+
prefixed.set(utf8, 4);
|
|
2475
|
+
const hash64 = xxh3_64(prefixed);
|
|
2476
|
+
return Number(hash64 & 0xffffffffn) | 0;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
// src/rpc-method-registry.ts
|
|
2480
|
+
var RpcMethodRegistry = class {
|
|
2481
|
+
_nameToHash = /* @__PURE__ */ new Map();
|
|
2482
|
+
_hashToName = /* @__PURE__ */ new Map();
|
|
2483
|
+
/** Register a method name and compute its hash. */
|
|
2484
|
+
register(methodName) {
|
|
2485
|
+
if (this._nameToHash.has(methodName)) return;
|
|
2486
|
+
const hash = computeMethodHash(methodName);
|
|
2487
|
+
const existing = this._hashToName.get(hash);
|
|
2488
|
+
if (existing !== void 0 && existing !== methodName) {
|
|
2489
|
+
console.warn(
|
|
2490
|
+
`[RpcMethodRegistry] hash collision: "${methodName}" and "${existing}" both hash to ${hash}`
|
|
2491
|
+
);
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
this._nameToHash.set(methodName, hash);
|
|
2495
|
+
this._hashToName.set(hash, methodName);
|
|
2496
|
+
}
|
|
2497
|
+
/** Register all wire method names from a service definition. */
|
|
2498
|
+
registerService(serviceName, methods) {
|
|
2499
|
+
for (const [, def] of methods) {
|
|
2500
|
+
const wireName = `${serviceName}.${def.name}:${def.wireArgCount}`;
|
|
2501
|
+
this.register(wireName);
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
/** Get the hash for a method name. Computes on demand if not registered. */
|
|
2505
|
+
getHash(methodName) {
|
|
2506
|
+
let hash = this._nameToHash.get(methodName);
|
|
2507
|
+
if (hash === void 0) {
|
|
2508
|
+
this.register(methodName);
|
|
2509
|
+
hash = this._nameToHash.get(methodName);
|
|
2510
|
+
}
|
|
2511
|
+
return hash;
|
|
2512
|
+
}
|
|
2513
|
+
/** Get the method name for a hash. Returns undefined if not registered. */
|
|
2514
|
+
getName(hash) {
|
|
2515
|
+
return this._hashToName.get(hash);
|
|
2516
|
+
}
|
|
2517
|
+
/** Get the hash for a method name, throwing if not registered. */
|
|
2518
|
+
requireHash(methodName) {
|
|
2519
|
+
return this.getHash(methodName);
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
|
|
1194
2523
|
// src/rpc-hub.ts
|
|
1195
2524
|
var RpcHub = class {
|
|
1196
2525
|
hubId;
|
|
@@ -1198,9 +2527,16 @@ var RpcHub = class {
|
|
|
1198
2527
|
serviceHost;
|
|
1199
2528
|
systemCallSender = new RpcSystemCallSender();
|
|
1200
2529
|
systemCallHandler = new RpcSystemCallHandler();
|
|
2530
|
+
/** Method registry for compact format hash ↔ name resolution.
|
|
2531
|
+
* Created lazily, populated by addService/addClient. */
|
|
2532
|
+
registry = new RpcMethodRegistry();
|
|
1201
2533
|
constructor(hubId) {
|
|
1202
2534
|
this.hubId = hubId ?? crypto.randomUUID();
|
|
1203
2535
|
this.serviceHost = new RpcServiceHost();
|
|
2536
|
+
this.systemCallSender.registry = this.registry;
|
|
2537
|
+
for (const methodName of Object.values(RpcSystemCalls)) {
|
|
2538
|
+
this.registry.register(methodName);
|
|
2539
|
+
}
|
|
1204
2540
|
}
|
|
1205
2541
|
addPeer(peer) {
|
|
1206
2542
|
this.peers.set(peer.ref, peer);
|
|
@@ -1238,10 +2574,12 @@ var RpcHub = class {
|
|
|
1238
2574
|
wrappedImpl[methodDef.name] = methodDef.callTypeId !== 0 ? this._wrapServerMethod(methodDef, fn, impl) : fn;
|
|
1239
2575
|
}
|
|
1240
2576
|
this.serviceHost.register(def, wrappedImpl);
|
|
2577
|
+
this.registry.registerService(def.name, def.methods);
|
|
1241
2578
|
}
|
|
1242
2579
|
/** Create a typed client proxy for a service on a remote peer. */
|
|
1243
2580
|
addClient(peer, defOrContract) {
|
|
1244
2581
|
const def = this._resolveServiceDef(defOrContract);
|
|
2582
|
+
this.registry.registerService(def.name, def.methods);
|
|
1245
2583
|
const overloads = /* @__PURE__ */ new Map();
|
|
1246
2584
|
for (const methodDef of def.methods.values()) {
|
|
1247
2585
|
let byArgCount = overloads.get(methodDef.name);
|
|
@@ -1249,7 +2587,10 @@ var RpcHub = class {
|
|
|
1249
2587
|
byArgCount = /* @__PURE__ */ new Map();
|
|
1250
2588
|
overloads.set(methodDef.name, byArgCount);
|
|
1251
2589
|
}
|
|
1252
|
-
byArgCount.set(
|
|
2590
|
+
byArgCount.set(
|
|
2591
|
+
methodDef.argCount,
|
|
2592
|
+
this._createClientMethod(peer, methodDef)
|
|
2593
|
+
);
|
|
1253
2594
|
}
|
|
1254
2595
|
const methods = /* @__PURE__ */ new Map();
|
|
1255
2596
|
for (const [name, byArgCount] of overloads) {
|
|
@@ -1258,7 +2599,10 @@ var RpcHub = class {
|
|
|
1258
2599
|
} else {
|
|
1259
2600
|
methods.set(name, (...args) => {
|
|
1260
2601
|
const fn = byArgCount.get(args.length);
|
|
1261
|
-
if (!fn)
|
|
2602
|
+
if (!fn)
|
|
2603
|
+
throw new Error(
|
|
2604
|
+
`No overload of ${name} accepts ${args.length} arguments`
|
|
2605
|
+
);
|
|
1262
2606
|
return fn(...args);
|
|
1263
2607
|
});
|
|
1264
2608
|
}
|
|
@@ -1274,7 +2618,8 @@ var RpcHub = class {
|
|
|
1274
2618
|
/** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
|
|
1275
2619
|
_buildServiceDef(cls) {
|
|
1276
2620
|
const svcMeta = getServiceMeta(cls);
|
|
1277
|
-
if (svcMeta === void 0)
|
|
2621
|
+
if (svcMeta === void 0)
|
|
2622
|
+
throw new Error("Contract class missing @rpcService metadata");
|
|
1278
2623
|
const methodsMeta = getMethodsMeta(cls) ?? {};
|
|
1279
2624
|
const methods = /* @__PURE__ */ new Map();
|
|
1280
2625
|
for (const [name, meta] of Object.entries(methodsMeta)) {
|
|
@@ -1317,7 +2662,10 @@ var RpcHub = class {
|
|
|
1317
2662
|
const outboundCall = peer.call(wireName, callArgs);
|
|
1318
2663
|
const result = await outboundCall.result.promise;
|
|
1319
2664
|
const ref = parseStreamRef(result);
|
|
1320
|
-
if (!ref)
|
|
2665
|
+
if (!ref)
|
|
2666
|
+
throw new Error(
|
|
2667
|
+
`Expected stream reference, got: ${JSON.stringify(result)}`
|
|
2668
|
+
);
|
|
1321
2669
|
const stream = new RpcStream(ref, peer);
|
|
1322
2670
|
peer.remoteObjects.register(stream);
|
|
1323
2671
|
return stream;
|
|
@@ -1356,7 +2704,10 @@ function createRpcClient(peer, serviceDef) {
|
|
|
1356
2704
|
}
|
|
1357
2705
|
methods.set(name, (...args) => {
|
|
1358
2706
|
const fn = fns.get(args.length);
|
|
1359
|
-
if (!fn)
|
|
2707
|
+
if (!fn)
|
|
2708
|
+
throw new Error(
|
|
2709
|
+
`No overload of ${name} accepts ${args.length} arguments`
|
|
2710
|
+
);
|
|
1360
2711
|
return fn(...args);
|
|
1361
2712
|
});
|
|
1362
2713
|
}
|
|
@@ -1401,12 +2752,10 @@ function getStateDescription(state, useLastError = false) {
|
|
|
1401
2752
|
case 1 /* JustDisconnected */:
|
|
1402
2753
|
return "Just disconnected, reconnecting...";
|
|
1403
2754
|
case 2 /* Disconnected */:
|
|
1404
|
-
if (state.reconnectsIn > 0)
|
|
1405
|
-
break;
|
|
2755
|
+
if (state.reconnectsIn > 0) break;
|
|
1406
2756
|
return "Reconnecting...";
|
|
1407
2757
|
}
|
|
1408
|
-
if (state.lastError == null || !useLastError)
|
|
1409
|
-
return "Disconnected.";
|
|
2758
|
+
if (state.lastError == null || !useLastError) return "Disconnected.";
|
|
1410
2759
|
let message = state.lastError.message.trim();
|
|
1411
2760
|
if (!(message.endsWith(".") || message.endsWith("!") || message.endsWith("?")))
|
|
1412
2761
|
message += ".";
|
|
@@ -1437,7 +2786,9 @@ var RpcPeerStateMonitor = class {
|
|
|
1437
2786
|
_onDisconnected = (ev) => {
|
|
1438
2787
|
const wasConnected = this._rawConnected;
|
|
1439
2788
|
this._rawConnected = false;
|
|
1440
|
-
this._lastError = new Error(
|
|
2789
|
+
this._lastError = new Error(
|
|
2790
|
+
`Connection closed: ${ev.reason} (code ${ev.code})`
|
|
2791
|
+
);
|
|
1441
2792
|
if (wasConnected) {
|
|
1442
2793
|
this._disconnectedAt = Date.now();
|
|
1443
2794
|
}
|
|
@@ -1454,16 +2805,26 @@ var RpcPeerStateMonitor = class {
|
|
|
1454
2805
|
this._rawConnected = peer.isConnected;
|
|
1455
2806
|
if (this._rawConnected) {
|
|
1456
2807
|
this._connectedAt = Date.now();
|
|
1457
|
-
this._state = {
|
|
2808
|
+
this._state = {
|
|
2809
|
+
kind: 3 /* JustConnected */,
|
|
2810
|
+
reconnectsIn: 0
|
|
2811
|
+
};
|
|
1458
2812
|
} else {
|
|
1459
2813
|
this._disconnectedAt = Date.now();
|
|
1460
|
-
this._state = {
|
|
2814
|
+
this._state = {
|
|
2815
|
+
kind: 1 /* JustDisconnected */,
|
|
2816
|
+
reconnectsIn: 0
|
|
2817
|
+
};
|
|
1461
2818
|
}
|
|
1462
2819
|
peer.connected.add(this._onConnected);
|
|
1463
2820
|
peer.disconnected.add(this._onDisconnected);
|
|
1464
2821
|
peer.reconnectsAtChanged.add(this._onReconnectsAtChanged);
|
|
1465
|
-
peer.reconnectDelayer.cancelDelaysChanged.add(
|
|
1466
|
-
|
|
2822
|
+
peer.reconnectDelayer.cancelDelaysChanged.add(
|
|
2823
|
+
this._onCancelDelaysChanged
|
|
2824
|
+
);
|
|
2825
|
+
this._scheduleRecompute(
|
|
2826
|
+
this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
|
|
2827
|
+
);
|
|
1467
2828
|
}
|
|
1468
2829
|
get state() {
|
|
1469
2830
|
return this._state;
|
|
@@ -1476,7 +2837,9 @@ var RpcPeerStateMonitor = class {
|
|
|
1476
2837
|
this.peer.connected.remove(this._onConnected);
|
|
1477
2838
|
this.peer.disconnected.remove(this._onDisconnected);
|
|
1478
2839
|
this.peer.reconnectsAtChanged.remove(this._onReconnectsAtChanged);
|
|
1479
|
-
this.peer.reconnectDelayer.cancelDelaysChanged.remove(
|
|
2840
|
+
this.peer.reconnectDelayer.cancelDelaysChanged.remove(
|
|
2841
|
+
this._onCancelDelaysChanged
|
|
2842
|
+
);
|
|
1480
2843
|
}
|
|
1481
2844
|
_recompute() {
|
|
1482
2845
|
if (this._timer !== void 0) {
|
|
@@ -1488,24 +2851,46 @@ var RpcPeerStateMonitor = class {
|
|
|
1488
2851
|
if (this._rawConnected) {
|
|
1489
2852
|
const connectedFor = now - this._connectedAt;
|
|
1490
2853
|
if (connectedFor < JustConnectedPeriodMs) {
|
|
1491
|
-
newState = {
|
|
2854
|
+
newState = {
|
|
2855
|
+
kind: 3 /* JustConnected */,
|
|
2856
|
+
reconnectsIn: 0
|
|
2857
|
+
};
|
|
1492
2858
|
this._scheduleRecompute(JustConnectedPeriodMs - connectedFor);
|
|
1493
2859
|
} else {
|
|
1494
|
-
newState = {
|
|
2860
|
+
newState = {
|
|
2861
|
+
kind: 0 /* Connected */,
|
|
2862
|
+
reconnectsIn: 0
|
|
2863
|
+
};
|
|
1495
2864
|
}
|
|
1496
2865
|
} else {
|
|
1497
2866
|
const disconnectedFor = now - this._disconnectedAt;
|
|
1498
2867
|
if (disconnectedFor < JustDisconnectedPeriodMs) {
|
|
1499
|
-
newState = {
|
|
1500
|
-
|
|
2868
|
+
newState = {
|
|
2869
|
+
kind: 1 /* JustDisconnected */,
|
|
2870
|
+
lastError: this._lastError,
|
|
2871
|
+
reconnectsIn: 0
|
|
2872
|
+
};
|
|
2873
|
+
this._scheduleRecompute(
|
|
2874
|
+
JustDisconnectedPeriodMs - disconnectedFor
|
|
2875
|
+
);
|
|
1501
2876
|
} else {
|
|
1502
2877
|
const reconnectsAt = this.peer.reconnectsAt;
|
|
1503
2878
|
const reconnectsIn = reconnectsAt > 0 ? Math.max(0, reconnectsAt - now) : 0;
|
|
1504
2879
|
if (reconnectsIn < MinReconnectsInMs) {
|
|
1505
|
-
newState = {
|
|
2880
|
+
newState = {
|
|
2881
|
+
kind: 2 /* Disconnected */,
|
|
2882
|
+
lastError: this._lastError,
|
|
2883
|
+
reconnectsIn: 0
|
|
2884
|
+
};
|
|
1506
2885
|
} else {
|
|
1507
|
-
newState = {
|
|
1508
|
-
|
|
2886
|
+
newState = {
|
|
2887
|
+
kind: 2 /* Disconnected */,
|
|
2888
|
+
lastError: this._lastError,
|
|
2889
|
+
reconnectsIn
|
|
2890
|
+
};
|
|
2891
|
+
this._scheduleRecompute(
|
|
2892
|
+
Math.min(1e3, reconnectsIn - MinReconnectsInMs)
|
|
2893
|
+
);
|
|
1509
2894
|
}
|
|
1510
2895
|
}
|
|
1511
2896
|
}
|
|
@@ -1520,10 +2905,13 @@ var RpcPeerStateMonitor = class {
|
|
|
1520
2905
|
}
|
|
1521
2906
|
_scheduleRecompute(delayMs) {
|
|
1522
2907
|
if (this._timer !== void 0) clearTimeout(this._timer);
|
|
1523
|
-
this._timer = setTimeout(
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
2908
|
+
this._timer = setTimeout(
|
|
2909
|
+
() => {
|
|
2910
|
+
this._timer = void 0;
|
|
2911
|
+
this._recompute();
|
|
2912
|
+
},
|
|
2913
|
+
Math.max(0, delayMs)
|
|
2914
|
+
);
|
|
1527
2915
|
}
|
|
1528
2916
|
};
|
|
1529
2917
|
export {
|
|
@@ -1531,13 +2919,18 @@ export {
|
|
|
1531
2919
|
DEFAULT_SERIALIZATION_FORMAT,
|
|
1532
2920
|
ENVELOPE_DELIMITER,
|
|
1533
2921
|
FRAME_DELIMITER,
|
|
2922
|
+
RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
|
|
1534
2923
|
RpcCallTypeId,
|
|
1535
2924
|
RpcClientPeer,
|
|
1536
2925
|
RpcClientPeerReconnectDelayer,
|
|
1537
2926
|
RpcHub,
|
|
1538
2927
|
RpcInboundCall,
|
|
1539
2928
|
RpcInboundCallTracker,
|
|
2929
|
+
RpcJsonSerializationFormat,
|
|
1540
2930
|
RpcMessageChannelConnection,
|
|
2931
|
+
RpcMessagePackCompactSerializationFormat,
|
|
2932
|
+
RpcMessagePackSerializationFormat,
|
|
2933
|
+
RpcMethodRegistry,
|
|
1541
2934
|
RpcObjectKind,
|
|
1542
2935
|
RpcOutboundCall,
|
|
1543
2936
|
RpcOutboundCallTracker,
|
|
@@ -1546,6 +2939,7 @@ export {
|
|
|
1546
2939
|
RpcPeerStateKind,
|
|
1547
2940
|
RpcPeerStateMonitor,
|
|
1548
2941
|
RpcRemoteObjectTracker,
|
|
2942
|
+
RpcSerializationFormat,
|
|
1549
2943
|
RpcServerPeer,
|
|
1550
2944
|
RpcServiceHost,
|
|
1551
2945
|
RpcSharedObjectTracker,
|
|
@@ -1557,10 +2951,16 @@ export {
|
|
|
1557
2951
|
RpcType,
|
|
1558
2952
|
RpcWebSocketConnection,
|
|
1559
2953
|
WebSocketState,
|
|
2954
|
+
computeMethodHash,
|
|
2955
|
+
createBinaryEncoder,
|
|
1560
2956
|
createMessageChannelPair,
|
|
1561
2957
|
createRpcClient,
|
|
2958
|
+
defaultBinaryDecoder,
|
|
2959
|
+
defaultBinaryEncoder,
|
|
1562
2960
|
defaultConnectionUrlResolver,
|
|
1563
2961
|
defineRpcService,
|
|
2962
|
+
deserializeBinaryMessage,
|
|
2963
|
+
deserializeCompactBinaryMessage,
|
|
1564
2964
|
deserializeMessage,
|
|
1565
2965
|
getMethodsMeta,
|
|
1566
2966
|
getServiceMeta,
|
|
@@ -1571,9 +2971,16 @@ export {
|
|
|
1571
2971
|
resolveStreamRefs,
|
|
1572
2972
|
rpcMethod,
|
|
1573
2973
|
rpcService,
|
|
2974
|
+
serializeBinaryFrame,
|
|
2975
|
+
serializeBinaryMessage,
|
|
2976
|
+
serializeCompactBinaryMessage,
|
|
1574
2977
|
serializeFrame,
|
|
1575
2978
|
serializeMessage,
|
|
2979
|
+
splitBinaryFrame,
|
|
2980
|
+
splitCompactBinaryFrame,
|
|
1576
2981
|
splitFrame,
|
|
1577
|
-
wireMethodName
|
|
2982
|
+
wireMethodName,
|
|
2983
|
+
xxh3_64,
|
|
2984
|
+
xxh3_64str
|
|
1578
2985
|
};
|
|
1579
2986
|
//# sourceMappingURL=index.js.map
|