@dxos/messaging 0.3.1-main.cf090ba → 0.3.1-main.d8f3335
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 +114 -94
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +112 -92
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/messenger.d.ts +0 -4
- package/dist/types/src/messenger.d.ts.map +1 -1
- package/dist/types/src/signal-manager/websocket-signal-manager.d.ts +3 -0
- package/dist/types/src/signal-manager/websocket-signal-manager.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/messenger.ts +1 -34
- package/src/signal-manager/websocket-signal-manager.ts +45 -7
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Event, synchronized } from '@dxos/async';
|
|
5
|
+
import { Event, sleep, synchronized } 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 { trace } from '@dxos/protocols';
|
|
11
|
+
import { RateLimitExceededError, trace } from '@dxos/protocols';
|
|
12
12
|
import { Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
13
13
|
import { SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
14
14
|
|
|
15
15
|
import { SignalManager } from './signal-manager';
|
|
16
16
|
import { CommandTrace, SignalClient, SignalStatus } from '../signal-client';
|
|
17
17
|
|
|
18
|
+
const MAX_SERVER_FAILURES = 5;
|
|
19
|
+
const WSS_SIGNAL_SERVER_REBOOT_DELAY = 3_000;
|
|
18
20
|
/**
|
|
19
21
|
* Manages connection to multiple Signal Servers over WebSocket
|
|
20
22
|
*/
|
|
@@ -24,6 +26,7 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
24
26
|
private _ctx!: Context;
|
|
25
27
|
private _opened = false;
|
|
26
28
|
|
|
29
|
+
readonly failureCount = new Map<string, number>();
|
|
27
30
|
readonly statusChanged = new Event<SignalStatus[]>();
|
|
28
31
|
readonly commandTrace = new Event<CommandTrace>();
|
|
29
32
|
readonly swarmEvent = new Event<{
|
|
@@ -53,6 +56,7 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
53
56
|
server.statusChanged.on(() => this.statusChanged.emit(this.getStatus()));
|
|
54
57
|
|
|
55
58
|
this._servers.set(host.server, server);
|
|
59
|
+
this.failureCount.set(host.server, 0);
|
|
56
60
|
server.commandTrace.on((trace) => this.commandTrace.emit(trace));
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -73,6 +77,7 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
73
77
|
log.trace('dxos.mesh.websocket-signal-manager.open', trace.end({ id: this._instanceId }));
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
@synchronized
|
|
76
81
|
async close() {
|
|
77
82
|
if (!this._opened) {
|
|
78
83
|
return;
|
|
@@ -84,6 +89,18 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
84
89
|
await Promise.all(Array.from(this._servers.values()).map((server) => server.close()));
|
|
85
90
|
}
|
|
86
91
|
|
|
92
|
+
async restartServer(serverName: string) {
|
|
93
|
+
log('Restarting server', { serverName });
|
|
94
|
+
invariant(this._opened, 'server already closed');
|
|
95
|
+
|
|
96
|
+
const server = this._servers.get(serverName);
|
|
97
|
+
invariant(server, 'server not found');
|
|
98
|
+
|
|
99
|
+
await server.close();
|
|
100
|
+
await sleep(WSS_SIGNAL_SERVER_REBOOT_DELAY);
|
|
101
|
+
await server.open();
|
|
102
|
+
}
|
|
103
|
+
|
|
87
104
|
getStatus(): SignalStatus[] {
|
|
88
105
|
return Array.from(this._servers.values()).map((server) => server.getStatus());
|
|
89
106
|
}
|
|
@@ -112,14 +129,33 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
112
129
|
recipient: PublicKey;
|
|
113
130
|
payload: Any;
|
|
114
131
|
}): Promise<void> {
|
|
115
|
-
log(`Signal ${recipient}`);
|
|
132
|
+
log(`Signal ${recipient.truncate()}`);
|
|
116
133
|
invariant(this._opened, 'Closed');
|
|
117
134
|
|
|
118
|
-
void this._forEachServer(async (server) => {
|
|
119
|
-
void server.sendMessage({ author, recipient, payload }).catch((err) =>
|
|
135
|
+
void this._forEachServer(async (server, serverName) => {
|
|
136
|
+
void server.sendMessage({ author, recipient, payload }).catch((err) => {
|
|
137
|
+
if (err instanceof RateLimitExceededError) {
|
|
138
|
+
log('WSS rate limit exceeded', { err });
|
|
139
|
+
} else {
|
|
140
|
+
log(`error sending to ${serverName}`, { err });
|
|
141
|
+
void this.checkServerFailure(serverName);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
120
144
|
});
|
|
121
145
|
}
|
|
122
146
|
|
|
147
|
+
@synchronized
|
|
148
|
+
async checkServerFailure(serverName: string) {
|
|
149
|
+
const failureCount = this.failureCount.get(serverName!) ?? 0;
|
|
150
|
+
if (failureCount > MAX_SERVER_FAILURES) {
|
|
151
|
+
log.warn(`Too many failures sending to ${serverName} (${failureCount} > ${MAX_SERVER_FAILURES}), restarting`);
|
|
152
|
+
await this.restartServer(serverName!);
|
|
153
|
+
this.failureCount.set(serverName!, 0);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.failureCount.set(serverName!, (this.failureCount.get(serverName!) ?? 0) + 1);
|
|
157
|
+
}
|
|
158
|
+
|
|
123
159
|
async subscribeMessages(peerId: PublicKey) {
|
|
124
160
|
log(`Subscribed for message stream peerId=${peerId}`);
|
|
125
161
|
invariant(this._opened, 'Closed');
|
|
@@ -140,7 +176,9 @@ export class WebsocketSignalManager implements SignalManager {
|
|
|
140
176
|
});
|
|
141
177
|
}
|
|
142
178
|
|
|
143
|
-
private async _forEachServer<ReturnType>(
|
|
144
|
-
|
|
179
|
+
private async _forEachServer<ReturnType>(
|
|
180
|
+
fn: (server: SignalClient, serverName: string) => Promise<ReturnType>,
|
|
181
|
+
): Promise<ReturnType[]> {
|
|
182
|
+
return Promise.all(Array.from(this._servers.entries()).map(([serverName, server]) => fn(server, serverName)));
|
|
145
183
|
}
|
|
146
184
|
}
|