@myko/core 4.8.0 → 4.10.0
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/client.d.ts +30 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +281 -96
- package/dist/generated/MykoMessage.d.ts +0 -5
- package/dist/generated/MykoMessage.d.ts.map +1 -1
- package/dist/generated/index.d.ts +191 -192
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/index.js +132 -133
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export declare enum ConnectionStatus {
|
|
|
29
29
|
/** Wire protocol for encoding messages */
|
|
30
30
|
export declare enum MykoProtocol {
|
|
31
31
|
JSON = "JSON",
|
|
32
|
-
|
|
32
|
+
CBOR = "CBOR"
|
|
33
33
|
}
|
|
34
34
|
type ConnectionLogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug' | 'verbose';
|
|
35
35
|
/** Query class interface */
|
|
@@ -107,6 +107,14 @@ export declare class MykoClient {
|
|
|
107
107
|
private reportErrors;
|
|
108
108
|
private pingResponses;
|
|
109
109
|
private commandIncoming;
|
|
110
|
+
private reportResponseRoutes;
|
|
111
|
+
private queryResponseRoutes;
|
|
112
|
+
private viewResponseRoutes;
|
|
113
|
+
private queryErrorRoutes;
|
|
114
|
+
private viewErrorRoutes;
|
|
115
|
+
private reportErrorRoutes;
|
|
116
|
+
private reportValueCallbacks;
|
|
117
|
+
private reportErrorCallbacks;
|
|
110
118
|
private connectionStatusSubject;
|
|
111
119
|
private currentServerSubject;
|
|
112
120
|
private activeQueries;
|
|
@@ -137,7 +145,7 @@ export declare class MykoClient {
|
|
|
137
145
|
constructor();
|
|
138
146
|
/** Set connection log verbosity at runtime. */
|
|
139
147
|
setConnectionLogLevel(level: ConnectionLogLevel): void;
|
|
140
|
-
/** Set the wire protocol (JSON or
|
|
148
|
+
/** Set the wire protocol (JSON or CBOR). Default is JSON. */
|
|
141
149
|
setProtocol(protocol: MykoProtocol): void;
|
|
142
150
|
/** Set a single server address, clearing any existing connections */
|
|
143
151
|
setAddress(address: string | null): void;
|
|
@@ -212,6 +220,20 @@ export declare class MykoClient {
|
|
|
212
220
|
windowInfo$: Observable<QueryWindowInfo>;
|
|
213
221
|
setWindow: (window: QueryWindow | null) => void;
|
|
214
222
|
};
|
|
223
|
+
/**
|
|
224
|
+
* Subscribe a single report with direct callbacks, bypassing RxJS entirely.
|
|
225
|
+
*
|
|
226
|
+
* `watchReport` returns an Observable wrapped in pipe(map, finalize,
|
|
227
|
+
* shareReplay, map) — each subscriber walks that operator chain, allocates
|
|
228
|
+
* a Subject per tx, and walks Subscriber chains on emission. This bypass
|
|
229
|
+
* stores callbacks in a flat Map and lets routeMessage call them directly,
|
|
230
|
+
* which matters when a workspace mounts hundreds of anchor subscriptions
|
|
231
|
+
* in a single Svelte microtask.
|
|
232
|
+
*
|
|
233
|
+
* Caller gets a dispose function. No deduplication — the caller owns the
|
|
234
|
+
* subscription lifetime.
|
|
235
|
+
*/
|
|
236
|
+
subscribeReport<R extends Report<unknown>>(report: R, onValue: (value: ReportResult<R>) => void, onError?: (error: Error) => void): () => void;
|
|
215
237
|
/** Watch a report with automatic deduplication */
|
|
216
238
|
watchReport<R extends Report<unknown>>(report: R): Observable<ReportResult<R>>;
|
|
217
239
|
/** Send an event to the server */
|
|
@@ -246,6 +268,12 @@ export declare class MykoClient {
|
|
|
246
268
|
private connectionLogLevel;
|
|
247
269
|
private static resolveDefaultConnectionLogLevel;
|
|
248
270
|
private shouldLogConnection;
|
|
271
|
+
/**
|
|
272
|
+
* Check whether a given event would be logged at the current verbosity.
|
|
273
|
+
* Use this to gate expensive details-object construction at hot call sites
|
|
274
|
+
* (e.g. per-response log calls during scene-load bursts).
|
|
275
|
+
*/
|
|
276
|
+
willLogConnection(event: string): boolean;
|
|
249
277
|
private logConnection;
|
|
250
278
|
}
|
|
251
279
|
export {};
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,SAAS,EAET,KAAK,MAAM,EACX,KAAK,WAAW,EAOjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAWL,UAAU,EAQX,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -5,15 +5,106 @@
|
|
|
5
5
|
* When the current server disconnects, instantly switches to another open connection.
|
|
6
6
|
*/
|
|
7
7
|
import { GetPeerServers, MykoEvent, } from './generated';
|
|
8
|
-
import {
|
|
8
|
+
import { Decoder, Encoder } from 'cbor-x';
|
|
9
9
|
import { bufferCount, bufferTime, catchError, combineLatest, filter, finalize, firstValueFrom, interval, map, merge, Observable, of, ReplaySubject, scan, shareReplay, Subject, switchMap, } from 'rxjs';
|
|
10
10
|
import { v4 as uuid } from 'uuid';
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
// cbor-x's defaults emit several non-standard extensions (the "records" structure
|
|
12
|
+
// compression, tag 259 for maps with non-string keys, typed-array tags) that other
|
|
13
|
+
// CBOR implementations — including the Rust server's `ciborium` decoder targeting
|
|
14
|
+
// `MykoMessage` / `serde_json::Value` — don't understand. Force plain RFC 8949
|
|
15
|
+
// CBOR so the wire is interchangeable.
|
|
16
|
+
const cborEncoder = new Encoder({
|
|
17
|
+
useRecords: false,
|
|
18
|
+
mapsAsObjects: true,
|
|
19
|
+
// useTag259ForMaps: false,
|
|
20
|
+
tagUint8Array: false,
|
|
21
|
+
});
|
|
22
|
+
const cborDecoder = new Decoder({
|
|
23
|
+
useRecords: false,
|
|
24
|
+
mapsAsObjects: true,
|
|
25
|
+
// useTag259ForMaps: false,
|
|
26
|
+
});
|
|
27
|
+
// Recursively strip `undefined` object values before CBOR encoding. cbor-x writes
|
|
28
|
+
// undefined as the standard CBOR simple-value 23 (0xf7), and Rust's serde decoder
|
|
29
|
+
// rejects that for fields like `Vec<T>` (no `null`-to-empty coercion). Omitting the
|
|
30
|
+
// key entirely lets the server's `#[serde(default)]` attributes fill in defaults,
|
|
31
|
+
// which matches how MessagePack used to behave with `encodeUndefinedAsNil: true`.
|
|
32
|
+
// Arrays preserve their length and pass undefined through as null (the only valid
|
|
33
|
+
// CBOR encoding for a missing positional value).
|
|
34
|
+
function stripUndefined(value) {
|
|
35
|
+
if (value === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
if (value === null)
|
|
38
|
+
return value;
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
const out = new Array(value.length);
|
|
41
|
+
for (let i = 0; i < value.length; i++) {
|
|
42
|
+
const v = value[i];
|
|
43
|
+
out[i] = v === undefined ? null : stripUndefined(v);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
if (typeof value === 'object') {
|
|
48
|
+
const obj = value;
|
|
49
|
+
const out = {};
|
|
50
|
+
for (const key in obj) {
|
|
51
|
+
const v = obj[key];
|
|
52
|
+
if (v === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
out[key] = stripUndefined(v);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
16
60
|
const EVENT_BATCH = 'ws:m:event-batch';
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
// WS message-throughput instrumentation
|
|
63
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
// Counterpart to the server's `ws_timing` module. Counts inbound/outbound
|
|
65
|
+
// messages by `event` kind into per-window buckets, logs a single summary
|
|
66
|
+
// line every WINDOW_MS so we can diagnose "server CPU idle but loads slow"
|
|
67
|
+
// — comparing client send/recv rates to the server's ws_timing log lines
|
|
68
|
+
// tells us whether time is in server-reply latency, client-send pacing, or
|
|
69
|
+
// network round-trip.
|
|
70
|
+
const WS_TIMING_WINDOW_MS = 250;
|
|
71
|
+
const wsTimingInbound = new Map();
|
|
72
|
+
const wsTimingOutbound = new Map();
|
|
73
|
+
let wsTimingTimer = null;
|
|
74
|
+
function recordWsInbound(kind) {
|
|
75
|
+
wsTimingInbound.set(kind, (wsTimingInbound.get(kind) ?? 0) + 1);
|
|
76
|
+
}
|
|
77
|
+
function recordWsOutbound(kind) {
|
|
78
|
+
wsTimingOutbound.set(kind, (wsTimingOutbound.get(kind) ?? 0) + 1);
|
|
79
|
+
}
|
|
80
|
+
/** Strip the `ws:m:` prefix and CamelCase the kind so it matches the
|
|
81
|
+
* server-side `message_kind` tag verbatim (e.g. "ws:m:report" → "Report",
|
|
82
|
+
* "ws:m:query-response" → "QueryResponse"). */
|
|
83
|
+
function eventKindShort(event) {
|
|
84
|
+
const stripped = event.startsWith('ws:m:') ? event.slice(5) : event;
|
|
85
|
+
return stripped
|
|
86
|
+
.split('-')
|
|
87
|
+
.map((part) => part.length > 0 ? part[0].toUpperCase() + part.slice(1) : part)
|
|
88
|
+
.join('');
|
|
89
|
+
}
|
|
90
|
+
function ensureWsTimingLogger() {
|
|
91
|
+
if (wsTimingTimer)
|
|
92
|
+
return;
|
|
93
|
+
wsTimingTimer = setInterval(() => {
|
|
94
|
+
if (wsTimingInbound.size === 0 && wsTimingOutbound.size === 0)
|
|
95
|
+
return;
|
|
96
|
+
const inEntries = [...wsTimingInbound.entries()].sort((a, b) => b[1] - a[1]);
|
|
97
|
+
const outEntries = [...wsTimingOutbound.entries()].sort((a, b) => b[1] - a[1]);
|
|
98
|
+
const inTotal = inEntries.reduce((s, [, n]) => s + n, 0);
|
|
99
|
+
const outTotal = outEntries.reduce((s, [, n]) => s + n, 0);
|
|
100
|
+
const inFmt = inEntries.map(([k, n]) => `${k}=${n}`).join(', ');
|
|
101
|
+
const outFmt = outEntries.map(([k, n]) => `${k}=${n}`).join(', ');
|
|
102
|
+
// eslint-disable-next-line no-console
|
|
103
|
+
console.info(`[ws_timing window=${WS_TIMING_WINDOW_MS}ms] in=${inTotal} [${inFmt}] out=${outTotal} [${outFmt}]`);
|
|
104
|
+
wsTimingInbound.clear();
|
|
105
|
+
wsTimingOutbound.clear();
|
|
106
|
+
}, WS_TIMING_WINDOW_MS);
|
|
107
|
+
}
|
|
17
108
|
function stableStringify(value) {
|
|
18
109
|
const seen = new WeakSet();
|
|
19
110
|
try {
|
|
@@ -49,7 +140,7 @@ export var ConnectionStatus;
|
|
|
49
140
|
export var MykoProtocol;
|
|
50
141
|
(function (MykoProtocol) {
|
|
51
142
|
MykoProtocol["JSON"] = "JSON";
|
|
52
|
-
MykoProtocol["
|
|
143
|
+
MykoProtocol["CBOR"] = "CBOR";
|
|
53
144
|
})(MykoProtocol || (MykoProtocol = {}));
|
|
54
145
|
function queryCacheKey(query, options) {
|
|
55
146
|
const queryPayload = stableStringify(query.query) ?? '__unstable_query__';
|
|
@@ -86,6 +177,21 @@ export class MykoClient {
|
|
|
86
177
|
reportErrors = new Subject();
|
|
87
178
|
pingResponses = new Subject();
|
|
88
179
|
commandIncoming = new Subject();
|
|
180
|
+
// Per-tx response routing. Replaces the previous pattern of every
|
|
181
|
+
// `watch{Report,Query,View}` subscription doing `filter(r => r.data.tx === tx)`
|
|
182
|
+
// on a shared Subject — that scaled as O(active_subscriptions × messages),
|
|
183
|
+
// costing measurable seconds during scene-load bursts. Direct dispatch is O(1).
|
|
184
|
+
reportResponseRoutes = new Map();
|
|
185
|
+
queryResponseRoutes = new Map();
|
|
186
|
+
viewResponseRoutes = new Map();
|
|
187
|
+
queryErrorRoutes = new Map();
|
|
188
|
+
viewErrorRoutes = new Map();
|
|
189
|
+
reportErrorRoutes = new Map();
|
|
190
|
+
// Lighter-weight direct-callback routing for `subscribeReport` — avoids
|
|
191
|
+
// allocating an RxJS Subject per anchor when the consumer just needs a
|
|
192
|
+
// single callback (which is the case for liveReport in the Svelte runtime).
|
|
193
|
+
reportValueCallbacks = new Map();
|
|
194
|
+
reportErrorCallbacks = new Map();
|
|
89
195
|
// State observables
|
|
90
196
|
connectionStatusSubject = new ReplaySubject(1);
|
|
91
197
|
currentServerSubject = new ReplaySubject(1);
|
|
@@ -116,7 +222,7 @@ export class MykoClient {
|
|
|
116
222
|
peerDiscoveryEnabled = true;
|
|
117
223
|
peerDiscoverySubscription = null;
|
|
118
224
|
useSecureWebSocket = false;
|
|
119
|
-
// Protocol defaults to JSON for maximum compatibility (no
|
|
225
|
+
// Protocol defaults to JSON for maximum compatibility (no CBOR tag handling, bigint issues, etc).
|
|
120
226
|
protocol = MykoProtocol.JSON;
|
|
121
227
|
constructor() {
|
|
122
228
|
this.setConnectionStatus(ConnectionStatus.Disconnected, 'init');
|
|
@@ -126,7 +232,7 @@ export class MykoClient {
|
|
|
126
232
|
setConnectionLogLevel(level) {
|
|
127
233
|
this.connectionLogLevelThreshold = level;
|
|
128
234
|
}
|
|
129
|
-
/** Set the wire protocol (JSON or
|
|
235
|
+
/** Set the wire protocol (JSON or CBOR). Default is JSON. */
|
|
130
236
|
setProtocol(protocol) {
|
|
131
237
|
this.protocol = protocol;
|
|
132
238
|
}
|
|
@@ -270,8 +376,8 @@ export class MykoClient {
|
|
|
270
376
|
const nowMs = Date.now();
|
|
271
377
|
// IMPORTANT: the Rust server expects `timestamp: i64`.
|
|
272
378
|
// - JSON cannot encode bigint, so use number in JSON mode.
|
|
273
|
-
// -
|
|
274
|
-
const timestamp = this.protocol === MykoProtocol.
|
|
379
|
+
// - CBOR can encode bigint as a tagged integer, so use bigint in CBOR mode.
|
|
380
|
+
const timestamp = this.protocol === MykoProtocol.CBOR ? BigInt(nowMs) : nowMs;
|
|
275
381
|
this.send({
|
|
276
382
|
event: MykoEvent.Ping,
|
|
277
383
|
data: { id, timestamp },
|
|
@@ -322,16 +428,19 @@ export class MykoClient {
|
|
|
322
428
|
activeQueries: this.activeQueries.size,
|
|
323
429
|
});
|
|
324
430
|
this.send({ event: MykoEvent.Query, data: wrappedQuery });
|
|
431
|
+
// Direct per-tx routing: see reportResponseRoutes/queryResponseRoutes for
|
|
432
|
+
// background. Each subscription registers its Subject in routeMessage's map
|
|
433
|
+
// so dispatch is O(1) instead of an O(active) filter walk per WS frame.
|
|
434
|
+
const responseRoute = new Subject();
|
|
435
|
+
const errorRoute = new Subject();
|
|
436
|
+
this.queryResponseRoutes.set(tx, responseRoute);
|
|
437
|
+
this.queryErrorRoutes.set(tx, errorRoute);
|
|
325
438
|
const responses$ = new Observable((subscriber) => {
|
|
326
|
-
const responseSub =
|
|
327
|
-
.pipe(filter((r) => r.data.tx === tx))
|
|
328
|
-
.subscribe({
|
|
439
|
+
const responseSub = responseRoute.subscribe({
|
|
329
440
|
next: (response) => subscriber.next(response),
|
|
330
441
|
error: (error) => subscriber.error(error),
|
|
331
442
|
});
|
|
332
|
-
const errorSub =
|
|
333
|
-
.pipe(filter((error) => error.data.tx === tx))
|
|
334
|
-
.subscribe((error) => {
|
|
443
|
+
const errorSub = errorRoute.subscribe((error) => {
|
|
335
444
|
subscriber.error(new Error(error.data.message));
|
|
336
445
|
});
|
|
337
446
|
return () => {
|
|
@@ -350,6 +459,10 @@ export class MykoClient {
|
|
|
350
459
|
this.activeQueryNames.delete(tx);
|
|
351
460
|
this.subscriptionStartMs.delete(tx);
|
|
352
461
|
this.firstResponseLogged.delete(tx);
|
|
462
|
+
this.queryResponseRoutes.delete(tx);
|
|
463
|
+
this.queryErrorRoutes.delete(tx);
|
|
464
|
+
responseRoute.complete();
|
|
465
|
+
errorRoute.complete();
|
|
353
466
|
this.send({ event: MykoEvent.QueryCancel, data: { tx } });
|
|
354
467
|
}));
|
|
355
468
|
return [tx, responses$];
|
|
@@ -410,16 +523,16 @@ export class MykoClient {
|
|
|
410
523
|
activeViews: this.activeViews.size,
|
|
411
524
|
});
|
|
412
525
|
this.send({ event: MykoEvent.View, data: wrappedView });
|
|
526
|
+
const responseRoute = new Subject();
|
|
527
|
+
const errorRoute = new Subject();
|
|
528
|
+
this.viewResponseRoutes.set(tx, responseRoute);
|
|
529
|
+
this.viewErrorRoutes.set(tx, errorRoute);
|
|
413
530
|
const responses$ = new Observable((subscriber) => {
|
|
414
|
-
const responseSub =
|
|
415
|
-
.pipe(filter((r) => r.data.tx === tx))
|
|
416
|
-
.subscribe({
|
|
531
|
+
const responseSub = responseRoute.subscribe({
|
|
417
532
|
next: (response) => subscriber.next(response),
|
|
418
533
|
error: (error) => subscriber.error(error),
|
|
419
534
|
});
|
|
420
|
-
const errorSub =
|
|
421
|
-
.pipe(filter((error) => error.data.tx === tx))
|
|
422
|
-
.subscribe((error) => {
|
|
535
|
+
const errorSub = errorRoute.subscribe((error) => {
|
|
423
536
|
subscriber.error(new Error(error.data.message));
|
|
424
537
|
});
|
|
425
538
|
return () => {
|
|
@@ -433,6 +546,10 @@ export class MykoClient {
|
|
|
433
546
|
viewName,
|
|
434
547
|
activeViewsBefore: this.activeViews.size,
|
|
435
548
|
});
|
|
549
|
+
this.viewResponseRoutes.delete(tx);
|
|
550
|
+
this.viewErrorRoutes.delete(tx);
|
|
551
|
+
responseRoute.complete();
|
|
552
|
+
errorRoute.complete();
|
|
436
553
|
this.activeViews.delete(tx);
|
|
437
554
|
this.activeViewNames.delete(tx);
|
|
438
555
|
this.subscriptionStartMs.delete(tx);
|
|
@@ -667,6 +784,59 @@ export class MykoClient {
|
|
|
667
784
|
setWindow: (window) => this.setViewWindow(tx, window),
|
|
668
785
|
};
|
|
669
786
|
}
|
|
787
|
+
/**
|
|
788
|
+
* Subscribe a single report with direct callbacks, bypassing RxJS entirely.
|
|
789
|
+
*
|
|
790
|
+
* `watchReport` returns an Observable wrapped in pipe(map, finalize,
|
|
791
|
+
* shareReplay, map) — each subscriber walks that operator chain, allocates
|
|
792
|
+
* a Subject per tx, and walks Subscriber chains on emission. This bypass
|
|
793
|
+
* stores callbacks in a flat Map and lets routeMessage call them directly,
|
|
794
|
+
* which matters when a workspace mounts hundreds of anchor subscriptions
|
|
795
|
+
* in a single Svelte microtask.
|
|
796
|
+
*
|
|
797
|
+
* Caller gets a dispose function. No deduplication — the caller owns the
|
|
798
|
+
* subscription lifetime.
|
|
799
|
+
*/
|
|
800
|
+
subscribeReport(report, onValue, onError) {
|
|
801
|
+
const tx = uuid();
|
|
802
|
+
const reportName = report.constructor?.name ??
|
|
803
|
+
report.reportId;
|
|
804
|
+
const wrappedReport = {
|
|
805
|
+
report: { ...report.report, tx },
|
|
806
|
+
reportId: report.reportId,
|
|
807
|
+
};
|
|
808
|
+
this.activeReports.set(tx, wrappedReport);
|
|
809
|
+
this.activeReportNames.set(tx, reportName);
|
|
810
|
+
if (this.willLogConnection('report_subscribe')) {
|
|
811
|
+
this.logConnection('report_subscribe', {
|
|
812
|
+
tx,
|
|
813
|
+
reportId: wrappedReport.reportId,
|
|
814
|
+
reportName,
|
|
815
|
+
report: report.report,
|
|
816
|
+
activeReports: this.activeReports.size,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
this.send({ event: MykoEvent.Report, data: wrappedReport });
|
|
820
|
+
this.reportValueCallbacks.set(tx, (r) => {
|
|
821
|
+
onValue(r.data.response);
|
|
822
|
+
});
|
|
823
|
+
if (onError) {
|
|
824
|
+
this.reportErrorCallbacks.set(tx, (r) => {
|
|
825
|
+
onError(new Error(r.data.message));
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
let disposed = false;
|
|
829
|
+
return () => {
|
|
830
|
+
if (disposed)
|
|
831
|
+
return;
|
|
832
|
+
disposed = true;
|
|
833
|
+
this.reportValueCallbacks.delete(tx);
|
|
834
|
+
this.reportErrorCallbacks.delete(tx);
|
|
835
|
+
this.activeReports.delete(tx);
|
|
836
|
+
this.activeReportNames.delete(tx);
|
|
837
|
+
this.send({ event: MykoEvent.ReportCancel, data: { tx } });
|
|
838
|
+
};
|
|
839
|
+
}
|
|
670
840
|
/** Watch a report with automatic deduplication */
|
|
671
841
|
watchReport(report) {
|
|
672
842
|
const cacheKey = reportCacheKey(report);
|
|
@@ -690,14 +860,9 @@ export class MykoClient {
|
|
|
690
860
|
activeReports: this.activeReports.size,
|
|
691
861
|
});
|
|
692
862
|
this.send({ event: MykoEvent.Report, data: wrappedReport });
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
reportId: wrappedReport.reportId,
|
|
697
|
-
reportName,
|
|
698
|
-
});
|
|
699
|
-
return r;
|
|
700
|
-
}), map((r) => r.data.response), finalize(() => {
|
|
863
|
+
const responseRoute = new Subject();
|
|
864
|
+
this.reportResponseRoutes.set(tx, responseRoute);
|
|
865
|
+
const shared$ = responseRoute.pipe(map((r) => r.data.response), finalize(() => {
|
|
701
866
|
this.logConnection('report_cancel', {
|
|
702
867
|
tx,
|
|
703
868
|
reportId: wrappedReport.reportId,
|
|
@@ -707,6 +872,8 @@ export class MykoClient {
|
|
|
707
872
|
this.sharedReports.delete(cacheKey);
|
|
708
873
|
this.activeReports.delete(tx);
|
|
709
874
|
this.activeReportNames.delete(tx);
|
|
875
|
+
this.reportResponseRoutes.delete(tx);
|
|
876
|
+
responseRoute.complete();
|
|
710
877
|
this.send({ event: MykoEvent.ReportCancel, data: { tx } });
|
|
711
878
|
}), shareReplay({ bufferSize: 1, refCount: true }),
|
|
712
879
|
// Defensive copy: prevent one subscriber's mutations from affecting others
|
|
@@ -873,7 +1040,7 @@ export class MykoClient {
|
|
|
873
1040
|
knownServers: this.getServers(),
|
|
874
1041
|
});
|
|
875
1042
|
const ws = new WebSocket(address);
|
|
876
|
-
ws.binaryType = 'arraybuffer'; // Receive binary messages as ArrayBuffer for
|
|
1043
|
+
ws.binaryType = 'arraybuffer'; // Receive binary messages as ArrayBuffer for CBOR
|
|
877
1044
|
const managed = {
|
|
878
1045
|
ws,
|
|
879
1046
|
address,
|
|
@@ -956,13 +1123,15 @@ export class MykoClient {
|
|
|
956
1123
|
message = JSON.parse(data);
|
|
957
1124
|
}
|
|
958
1125
|
else if (data instanceof ArrayBuffer) {
|
|
959
|
-
// Binary
|
|
960
|
-
message =
|
|
1126
|
+
// Binary CBOR message
|
|
1127
|
+
message = cborDecoder.decode(new Uint8Array(data));
|
|
961
1128
|
}
|
|
962
1129
|
else if (data instanceof Blob) {
|
|
963
1130
|
// Handle Blob asynchronously - convert to ArrayBuffer first
|
|
964
1131
|
data.arrayBuffer().then((buffer) => {
|
|
965
|
-
const decoded =
|
|
1132
|
+
const decoded = cborDecoder.decode(new Uint8Array(buffer));
|
|
1133
|
+
recordWsInbound(eventKindShort(decoded.event));
|
|
1134
|
+
ensureWsTimingLogger();
|
|
966
1135
|
this.routeMessage(decoded);
|
|
967
1136
|
});
|
|
968
1137
|
return;
|
|
@@ -970,6 +1139,8 @@ export class MykoClient {
|
|
|
970
1139
|
else {
|
|
971
1140
|
return;
|
|
972
1141
|
}
|
|
1142
|
+
recordWsInbound(eventKindShort(message.event));
|
|
1143
|
+
ensureWsTimingLogger();
|
|
973
1144
|
this.routeMessage(message);
|
|
974
1145
|
}
|
|
975
1146
|
catch {
|
|
@@ -979,72 +1150,69 @@ export class MykoClient {
|
|
|
979
1150
|
routeMessage(message) {
|
|
980
1151
|
switch (message.event) {
|
|
981
1152
|
case MykoEvent.QueryResponse:
|
|
982
|
-
this.
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
this.
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
this.
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
message.data.
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1153
|
+
if (this.willLogConnection('query_response')) {
|
|
1154
|
+
this.maybeLogFirstResponseTiming('query', message.data.tx, {
|
|
1155
|
+
queryId: this.activeQueries.get(message.data.tx)?.queryId,
|
|
1156
|
+
queryName: this.activeQueryNames.get(message.data.tx) ??
|
|
1157
|
+
this.activeQueries.get(message.data.tx)?.queryId ??
|
|
1158
|
+
'unknown',
|
|
1159
|
+
sequence: message.data.sequence,
|
|
1160
|
+
upserts: message.data.upserts.length,
|
|
1161
|
+
deletes: message.data.deletes.length,
|
|
1162
|
+
});
|
|
1163
|
+
this.logConnection('query_response', {
|
|
1164
|
+
tx: message.data.tx,
|
|
1165
|
+
queryId: this.activeQueries.get(message.data.tx)?.queryId,
|
|
1166
|
+
queryItemType: this.activeQueries.get(message.data.tx)?.queryItemType,
|
|
1167
|
+
queryName: this.activeQueryNames.get(message.data.tx) ??
|
|
1168
|
+
this.activeQueries.get(message.data.tx)?.queryId ??
|
|
1169
|
+
'unknown',
|
|
1170
|
+
sequence: message.data.sequence,
|
|
1171
|
+
upserts: message.data.upserts.length,
|
|
1172
|
+
deletes: message.data.deletes.length,
|
|
1173
|
+
changes: message.data.changes?.length ?? 0,
|
|
1174
|
+
totalCount: message.data.totalCount ??
|
|
1175
|
+
message.data.total_count ??
|
|
1176
|
+
null,
|
|
1177
|
+
window: message.data.window ?? null,
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
this.queryResponseRoutes.get(message.data.tx)?.next(message);
|
|
1008
1181
|
this.queryResponses.next(message);
|
|
1009
|
-
this.logConnection('query_publish_ms', {
|
|
1010
|
-
tx: message.data.tx,
|
|
1011
|
-
sequence: message.data.sequence,
|
|
1012
|
-
publishMs: Number((this.nowMs() - queryPublishStarted).toFixed(2)),
|
|
1013
|
-
});
|
|
1014
1182
|
break;
|
|
1015
|
-
case MykoEvent.ViewResponse:
|
|
1183
|
+
case MykoEvent.ViewResponse: {
|
|
1016
1184
|
// ViewResponse and QueryResponse share the same payload shape.
|
|
1017
1185
|
const viewMessage = message;
|
|
1018
|
-
this.
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
this.
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1186
|
+
if (this.willLogConnection('view_response')) {
|
|
1187
|
+
this.maybeLogFirstResponseTiming('view', viewMessage.data.tx, {
|
|
1188
|
+
viewId: this.activeViews.get(viewMessage.data.tx)?.viewId,
|
|
1189
|
+
viewName: this.activeViewNames.get(viewMessage.data.tx) ??
|
|
1190
|
+
this.activeViews.get(viewMessage.data.tx)?.viewId ??
|
|
1191
|
+
'unknown',
|
|
1192
|
+
sequence: viewMessage.data.sequence,
|
|
1193
|
+
upserts: viewMessage.data.upserts.length,
|
|
1194
|
+
deletes: viewMessage.data.deletes.length,
|
|
1195
|
+
});
|
|
1196
|
+
this.logConnection('view_response', {
|
|
1197
|
+
tx: viewMessage.data.tx,
|
|
1198
|
+
sequence: viewMessage.data.sequence,
|
|
1199
|
+
upserts: viewMessage.data.upserts.length,
|
|
1200
|
+
deletes: viewMessage.data.deletes.length,
|
|
1201
|
+
changes: viewMessage.data.changes?.length ?? 0,
|
|
1202
|
+
totalCount: viewMessage.data
|
|
1203
|
+
.totalCount ??
|
|
1204
|
+
viewMessage.data.total_count ??
|
|
1205
|
+
null,
|
|
1206
|
+
window: viewMessage.data.window ?? null,
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
this.viewResponseRoutes.get(viewMessage.data.tx)?.next(viewMessage);
|
|
1040
1210
|
this.queryResponses.next(viewMessage);
|
|
1041
|
-
this.logConnection('view_publish_ms', {
|
|
1042
|
-
tx: viewMessage.data.tx,
|
|
1043
|
-
sequence: viewMessage.data.sequence,
|
|
1044
|
-
publishMs: Number((this.nowMs() - viewPublishStarted).toFixed(2)),
|
|
1045
|
-
});
|
|
1046
1211
|
break;
|
|
1212
|
+
}
|
|
1047
1213
|
case MykoEvent.ReportResponse:
|
|
1214
|
+
this.reportValueCallbacks.get(message.data.tx)?.(message);
|
|
1215
|
+
this.reportResponseRoutes.get(message.data.tx)?.next(message);
|
|
1048
1216
|
this.reportResponses.next(message);
|
|
1049
1217
|
break;
|
|
1050
1218
|
case MykoEvent.CommandResponse:
|
|
@@ -1054,6 +1222,7 @@ export class MykoClient {
|
|
|
1054
1222
|
this.commandErrors.next(message);
|
|
1055
1223
|
break;
|
|
1056
1224
|
case MykoEvent.QueryError:
|
|
1225
|
+
this.queryErrorRoutes.get(message.data.tx)?.next(message);
|
|
1057
1226
|
this.queryErrors.next(message);
|
|
1058
1227
|
this.logConnection('query_error', {
|
|
1059
1228
|
tx: message.data.tx,
|
|
@@ -1066,6 +1235,7 @@ export class MykoClient {
|
|
|
1066
1235
|
});
|
|
1067
1236
|
break;
|
|
1068
1237
|
case MykoEvent.ViewError:
|
|
1238
|
+
this.viewErrorRoutes.get(message.data.tx)?.next(message);
|
|
1069
1239
|
this.queryErrors.next(message);
|
|
1070
1240
|
this.logConnection('view_error', {
|
|
1071
1241
|
tx: message.data.tx,
|
|
@@ -1078,6 +1248,8 @@ export class MykoClient {
|
|
|
1078
1248
|
});
|
|
1079
1249
|
break;
|
|
1080
1250
|
case MykoEvent.ReportError:
|
|
1251
|
+
this.reportErrorCallbacks.get(message.data.tx)?.(message);
|
|
1252
|
+
this.reportErrorRoutes.get(message.data.tx)?.next(message);
|
|
1081
1253
|
this.reportErrors.next(message);
|
|
1082
1254
|
this.logConnection('report_error', {
|
|
1083
1255
|
tx: message.data.tx,
|
|
@@ -1129,11 +1301,15 @@ export class MykoClient {
|
|
|
1129
1301
|
if (this.currentServer) {
|
|
1130
1302
|
const managed = this.sockets.get(this.currentServer);
|
|
1131
1303
|
if (managed?.ws.readyState === WebSocket.OPEN) {
|
|
1132
|
-
const encoded = this.protocol === MykoProtocol.
|
|
1133
|
-
?
|
|
1304
|
+
const encoded = this.protocol === MykoProtocol.CBOR
|
|
1305
|
+
? cborEncoder.encode(stripUndefined(message))
|
|
1134
1306
|
: JSON.stringify(message);
|
|
1135
1307
|
managed.ws.send(encoded);
|
|
1136
1308
|
this.upMsgCounter.next();
|
|
1309
|
+
// Tap for ws_timing summary. Use the short kind suffix (after
|
|
1310
|
+
// `ws:m:`) for a tighter log line.
|
|
1311
|
+
recordWsOutbound(eventKindShort(event));
|
|
1312
|
+
ensureWsTimingLogger();
|
|
1137
1313
|
return;
|
|
1138
1314
|
}
|
|
1139
1315
|
}
|
|
@@ -1292,6 +1468,15 @@ export class MykoClient {
|
|
|
1292
1468
|
};
|
|
1293
1469
|
return priority[level] <= priority[this.connectionLogLevelThreshold];
|
|
1294
1470
|
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Check whether a given event would be logged at the current verbosity.
|
|
1473
|
+
* Use this to gate expensive details-object construction at hot call sites
|
|
1474
|
+
* (e.g. per-response log calls during scene-load bursts).
|
|
1475
|
+
*/
|
|
1476
|
+
willLogConnection(event) {
|
|
1477
|
+
const level = this.connectionLogLevel(event);
|
|
1478
|
+
return this.shouldLogConnection(level);
|
|
1479
|
+
}
|
|
1295
1480
|
logConnection(event, details) {
|
|
1296
1481
|
const level = this.connectionLogLevel(event);
|
|
1297
1482
|
if (!this.shouldLogConnection(level))
|