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