@dxos/messaging 0.1.57 → 0.1.58-main.0e9c99e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +109 -27
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +105 -23
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/messenger.d.ts +9 -0
- package/dist/types/src/messenger.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/messenger.ts +77 -5
package/src/messenger.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { TimeoutError, scheduleExponentialBackoffTaskInterval, scheduleTask } from '@dxos/async';
|
|
5
|
+
import { TimeoutError, scheduleExponentialBackoffTaskInterval, scheduleTask, scheduleTaskInterval } from '@dxos/async';
|
|
6
6
|
import { Any } from '@dxos/codec-protobuf';
|
|
7
7
|
import { Context } from '@dxos/context';
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
9
|
import { PublicKey } from '@dxos/keys';
|
|
10
10
|
import { log } from '@dxos/log';
|
|
11
|
-
import { schema, trace } from '@dxos/protocols';
|
|
11
|
+
import { TimeoutError as ProtocolTimeoutError, schema, trace } from '@dxos/protocols';
|
|
12
12
|
import { ReliablePayload } from '@dxos/protocols/proto/dxos/mesh/messaging';
|
|
13
13
|
import { ComplexMap, ComplexSet } from '@dxos/util';
|
|
14
14
|
|
|
@@ -26,6 +26,11 @@ export interface MessengerOptions {
|
|
|
26
26
|
const ReliablePayload = schema.getCodecForType('dxos.mesh.messaging.ReliablePayload');
|
|
27
27
|
const Acknowledgement = schema.getCodecForType('dxos.mesh.messaging.Acknowledgement');
|
|
28
28
|
|
|
29
|
+
const ERROR_LIMIT = 5;
|
|
30
|
+
const NETWORK_REBOOT_DELAY = 3_000;
|
|
31
|
+
|
|
32
|
+
const RECEIVED_MESSAGES_GC_INTERVAL = 120_000;
|
|
33
|
+
|
|
29
34
|
/**
|
|
30
35
|
* Reliable messenger that works trough signal network.
|
|
31
36
|
*/
|
|
@@ -41,11 +46,18 @@ export class Messenger {
|
|
|
41
46
|
|
|
42
47
|
private readonly _onAckCallbacks = new ComplexMap<PublicKey, () => void>(PublicKey.hash);
|
|
43
48
|
|
|
44
|
-
private readonly _receivedMessages = new ComplexSet<PublicKey>(
|
|
49
|
+
private readonly _receivedMessages = new ComplexSet<PublicKey>(PublicKey.hash);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Keys scheduled to be cleared from _receivedMessages on the next iteration.
|
|
53
|
+
*/
|
|
54
|
+
private readonly _toClear = new ComplexSet<PublicKey>(PublicKey.hash);
|
|
45
55
|
|
|
46
56
|
private _ctx!: Context;
|
|
47
57
|
private _closed = true;
|
|
48
58
|
private readonly _retryDelay: number;
|
|
59
|
+
private _errorCount = 0;
|
|
60
|
+
private _rebooting = false;
|
|
49
61
|
|
|
50
62
|
constructor({ signalManager, retryDelay = 300 }: MessengerOptions) {
|
|
51
63
|
this._signalManager = signalManager;
|
|
@@ -69,6 +81,16 @@ export class Messenger {
|
|
|
69
81
|
await this._handleMessage(message);
|
|
70
82
|
}),
|
|
71
83
|
);
|
|
84
|
+
|
|
85
|
+
// Clear the map periodically.
|
|
86
|
+
scheduleTaskInterval(
|
|
87
|
+
this._ctx,
|
|
88
|
+
async () => {
|
|
89
|
+
this._performGc();
|
|
90
|
+
},
|
|
91
|
+
RECEIVED_MESSAGES_GC_INTERVAL,
|
|
92
|
+
);
|
|
93
|
+
|
|
72
94
|
this._closed = false;
|
|
73
95
|
log.trace('dxos.mesh.messenger.open', trace.end({ id: traceId }));
|
|
74
96
|
}
|
|
@@ -114,10 +136,16 @@ export class Messenger {
|
|
|
114
136
|
|
|
115
137
|
scheduleTask(
|
|
116
138
|
messageContext,
|
|
117
|
-
() => {
|
|
139
|
+
async () => {
|
|
118
140
|
log('message not delivered', { messageId: reliablePayload.messageId });
|
|
119
141
|
this._onAckCallbacks.delete(reliablePayload.messageId!);
|
|
120
|
-
|
|
142
|
+
await this.errorLimitCheck();
|
|
143
|
+
timeoutHit(
|
|
144
|
+
new ProtocolTimeoutError(
|
|
145
|
+
'signaling message not delivered',
|
|
146
|
+
new TimeoutError(MESSAGE_TIMEOUT, 'Message not delivered'),
|
|
147
|
+
),
|
|
148
|
+
);
|
|
121
149
|
void messageContext.dispose();
|
|
122
150
|
},
|
|
123
151
|
MESSAGE_TIMEOUT,
|
|
@@ -133,6 +161,33 @@ export class Messenger {
|
|
|
133
161
|
return promise;
|
|
134
162
|
}
|
|
135
163
|
|
|
164
|
+
private async errorLimitCheck() {
|
|
165
|
+
log(`checking error limit ${this._errorCount}`);
|
|
166
|
+
if (this._errorCount++ > ERROR_LIMIT) {
|
|
167
|
+
await this.rebootNetwork();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private async rebootNetwork() {
|
|
172
|
+
if (this._rebooting) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this._rebooting = true;
|
|
176
|
+
|
|
177
|
+
log('rebooting Messenger/SignalManager');
|
|
178
|
+
await this.close();
|
|
179
|
+
await this._signalManager.close();
|
|
180
|
+
log('pausing');
|
|
181
|
+
await new Promise((resolve) => setTimeout(resolve, NETWORK_REBOOT_DELAY));
|
|
182
|
+
log('done pausing');
|
|
183
|
+
await this.open();
|
|
184
|
+
await this._signalManager.open();
|
|
185
|
+
log('done rebooting');
|
|
186
|
+
|
|
187
|
+
this._errorCount = 0;
|
|
188
|
+
this._rebooting = false;
|
|
189
|
+
}
|
|
190
|
+
|
|
136
191
|
/**
|
|
137
192
|
* Subscribes onMessage function to messages that contains payload with payloadType.
|
|
138
193
|
* @param payloadType if not specified, onMessage will be subscribed to all types of messages.
|
|
@@ -279,6 +334,23 @@ export class Messenger {
|
|
|
279
334
|
}
|
|
280
335
|
}
|
|
281
336
|
}
|
|
337
|
+
|
|
338
|
+
private _performGc() {
|
|
339
|
+
const start = performance.now();
|
|
340
|
+
|
|
341
|
+
for (const key of this._toClear.keys()) {
|
|
342
|
+
this._receivedMessages.delete(key);
|
|
343
|
+
}
|
|
344
|
+
this._toClear.clear();
|
|
345
|
+
for (const key of this._receivedMessages.keys()) {
|
|
346
|
+
this._toClear.add(key);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const elapsed = performance.now() - start;
|
|
350
|
+
if (elapsed > 100) {
|
|
351
|
+
log.warn('GC took too long', { elapsed });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
282
354
|
}
|
|
283
355
|
|
|
284
356
|
export interface ListeningHandle {
|