@dxos/messaging 0.1.58-main.9be790d → 0.1.58-main.ae92ec9

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/src/messenger.ts CHANGED
@@ -2,14 +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
- import { TimeoutError as ProtocolTimeoutError } from '@dxos/errors';
9
8
  import { invariant } from '@dxos/invariant';
10
9
  import { PublicKey } from '@dxos/keys';
11
10
  import { log } from '@dxos/log';
12
- import { schema, trace } from '@dxos/protocols';
11
+ import { TimeoutError as ProtocolTimeoutError, schema, trace } from '@dxos/protocols';
13
12
  import { ReliablePayload } from '@dxos/protocols/proto/dxos/mesh/messaging';
14
13
  import { ComplexMap, ComplexSet } from '@dxos/util';
15
14
 
@@ -30,6 +29,8 @@ const Acknowledgement = schema.getCodecForType('dxos.mesh.messaging.Acknowledgem
30
29
  const ERROR_LIMIT = 5;
31
30
  const NETWORK_REBOOT_DELAY = 3_000;
32
31
 
32
+ const RECEIVED_MESSAGES_GC_INTERVAL = 120_000;
33
+
33
34
  /**
34
35
  * Reliable messenger that works trough signal network.
35
36
  */
@@ -45,7 +46,12 @@ export class Messenger {
45
46
 
46
47
  private readonly _onAckCallbacks = new ComplexMap<PublicKey, () => void>(PublicKey.hash);
47
48
 
48
- private readonly _receivedMessages = new ComplexSet<PublicKey>((key) => key.toHex());
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);
49
55
 
50
56
  private _ctx!: Context;
51
57
  private _closed = true;
@@ -75,6 +81,16 @@ export class Messenger {
75
81
  await this._handleMessage(message);
76
82
  }),
77
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
+
78
94
  this._closed = false;
79
95
  log.trace('dxos.mesh.messenger.open', trace.end({ id: traceId }));
80
96
  }
@@ -318,6 +334,23 @@ export class Messenger {
318
334
  }
319
335
  }
320
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
+ }
321
354
  }
322
355
 
323
356
  export interface ListeningHandle {
@@ -12,8 +12,8 @@ import { trace } from '@dxos/protocols';
12
12
  import { Message as SignalMessage, SignalState, SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
13
13
  import { ComplexMap, ComplexSet } from '@dxos/util';
14
14
 
15
- import { Message, SignalMethods } from '../signal-methods';
16
15
  import { SignalRPCClient } from './signal-rpc-client';
16
+ import { Message, SignalMethods } from '../signal-methods';
17
17
 
18
18
  const DEFAULT_RECONNECT_TIMEOUT = 100;
19
19
  const MAX_RECONNECT_TIMEOUT = 5000;
@@ -12,8 +12,8 @@ import { schema } from '@dxos/protocols';
12
12
  import { SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
13
13
  import { ComplexMap, ComplexSet } from '@dxos/util';
14
14
 
15
- import { CommandTrace, SignalStatus } from '../signal-client';
16
15
  import { SignalManager } from './signal-manager';
16
+ import { CommandTrace, SignalStatus } from '../signal-client';
17
17
 
18
18
  /**
19
19
  * Common signaling context that connects multiple MemorySignalManager instances.
@@ -59,10 +59,7 @@ export class MemorySignalManager implements SignalManager {
59
59
  // TODO(dmaretskyi): Replace with callback.
60
60
  private readonly _freezeTrigger = new Trigger().wake();
61
61
 
62
- // prettier-ignore
63
- constructor(
64
- private readonly _context: MemorySignalManagerContext
65
- ) {
62
+ constructor(private readonly _context: MemorySignalManagerContext) {
66
63
  this._ctx = new Context();
67
64
 
68
65
  this._ctx.onDispose(this._context.swarmEvent.on((data) => this.swarmEvent.emit(data)));
@@ -12,8 +12,8 @@ import { 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
- import { CommandTrace, SignalClient, SignalStatus } from '../signal-client';
16
15
  import { SignalManager } from './signal-manager';
16
+ import { CommandTrace, SignalClient, SignalStatus } from '../signal-client';
17
17
 
18
18
  /**
19
19
  * Manages connection to multiple Signal Servers over WebSocket
@@ -39,10 +39,7 @@ export class WebsocketSignalManager implements SignalManager {
39
39
 
40
40
  private readonly _instanceId = PublicKey.random().toHex();
41
41
 
42
- // prettier-ignore
43
- constructor(
44
- private readonly _hosts: Runtime.Services.Signal[]
45
- ) {
42
+ constructor(private readonly _hosts: Runtime.Services.Signal[]) {
46
43
  log('Created WebsocketSignalManager', { hosts: this._hosts });
47
44
  for (const host of this._hosts) {
48
45
  if (this._servers.has(host.server)) {
@@ -51,7 +48,7 @@ export class WebsocketSignalManager implements SignalManager {
51
48
  const server = new SignalClient(
52
49
  host.server,
53
50
  async (message) => this.onMessage.emit(message),
54
- async (data) => this.swarmEvent.emit(data)
51
+ async (data) => this.swarmEvent.emit(data),
55
52
  );
56
53
  server.statusChanged.on(() => this.statusChanged.emit(this.getStatus()));
57
54