@matterbridge/thread 3.10.14-dev-20261010-607ee18 → 3.10.14-dev-20261012-c6da540

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.
@@ -12,6 +12,7 @@ export declare class BroadcastServer extends EventEmitter<BroadcastServerEvents>
12
12
  private closed;
13
13
  private readonly debug;
14
14
  private readonly verbose;
15
+ private readonly diagnostic;
15
16
  constructor(name: WorkerSrcType, log: AnsiLogger, channel?: string);
16
17
  close(): void;
17
18
  private broadcastMessageHandler;
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter } from 'node:events';
2
2
  import { BroadcastChannel } from 'node:worker_threads';
3
- import { hasParameter } from '@matterbridge/utils/cli';
3
+ import { hasAnyParameter } from '@matterbridge/utils/cli';
4
+ import { writeDiagnostic } from '@matterbridge/utils/diagnostic';
4
5
  import { logError } from '@matterbridge/utils/error';
5
6
  import { logModuleLoaded } from '@matterbridge/utils/loader';
6
7
  import { CYAN, db, debugStringify, er } from 'node-ansi-logger';
@@ -11,8 +12,9 @@ export class BroadcastServer extends EventEmitter {
11
12
  channel;
12
13
  broadcastChannel;
13
14
  closed = false;
14
- debug = hasParameter('debug') || hasParameter('verbose') || hasParameter('debug-threads') || hasParameter('verbose-threads');
15
- verbose = hasParameter('verbose') || hasParameter('verbose-threads');
15
+ debug = hasAnyParameter('debug', 'verbose', 'debug-broadcast', 'verbose-broadcast');
16
+ verbose = hasAnyParameter('verbose', 'verbose-broadcast');
17
+ diagnostic = hasAnyParameter('diagnostic', 'diagnostic-broadcast');
16
18
  constructor(name, log, channel = 'broadcast-channel') {
17
19
  super();
18
20
  this.name = name;
@@ -158,6 +160,7 @@ export class BroadcastServer extends EventEmitter {
158
160
  return Promise.reject(new Error('Broadcast channel is closed'));
159
161
  }
160
162
  let timeoutId;
163
+ const start = performance.now();
161
164
  const requestMessage = {
162
165
  ...message,
163
166
  id: message.id ?? this.getUniqueId(),
@@ -173,6 +176,8 @@ export class BroadcastServer extends EventEmitter {
173
176
  this.off('broadcast_message', responseHandler);
174
177
  if (this.verbose)
175
178
  this.log.debug(`Fetch response: ${debugStringify(msg)}`);
179
+ if (this.diagnostic)
180
+ writeDiagnostic(`Broadcast:${this.name}`, `fetch ${requestMessage.type} from ${requestMessage.src} to ${requestMessage.dst} took ${(performance.now() - start).toFixed(2)} ms`);
176
181
  if ('error' in msg && typeof msg.error === 'string') {
177
182
  reject(new Error(`Fetch received error response ${msg.error} to message type ${requestMessage.type} id ${requestMessage.id} from ${requestMessage.src} to ${requestMessage.dst}`));
178
183
  }
@@ -27,8 +27,8 @@ export class ThreadsManager {
27
27
  { name: 'SpawnCommand', path: 'workerSpawnCommand.js', type: 'worker' },
28
28
  { name: 'ArchiveCommand', path: 'workerArchiveCommand.js', type: 'worker' },
29
29
  { name: 'DockerVersion', path: 'workerDockerVersion.js', type: 'worker' },
30
- { name: 'Backend', path: 'threadBackend.js', type: 'thread' },
31
- { name: 'RootNode', path: 'threadRootNode.js', type: 'thread', multiple: true },
30
+ { name: 'Backend', path: 'threadBackend.js', type: 'thread', startup: true, shutdown: true },
31
+ { name: 'RootNode', path: 'threadRootNode.js', type: 'thread', multiple: true, startup: true, shutdown: true },
32
32
  { name: 'Tracker', path: 'threadTracker.js', type: 'thread', multiple: true, startup: true, shutdown: true },
33
33
  ];
34
34
  terminateWorkers = new Set();
@@ -62,7 +62,7 @@ export class ThreadsManager {
62
62
  this.log.notice(`ThreadsManager destroyed. Broadcast server closed.`);
63
63
  }
64
64
  msgHandler(msg) {
65
- if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'manager')) {
65
+ if (this.server.isWorkerRequest(msg)) {
66
66
  if (this.verbose)
67
67
  this.log.debug(`Received broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
68
68
  switch (msg.type) {
@@ -141,12 +141,13 @@ export class ThreadsManager {
141
141
  this.terminateExitedWorkers();
142
142
  for (const thread of this.threads) {
143
143
  for (const info of [thread, ...(thread.instances ?? [])]) {
144
- if (info.worker && Date.now() - (info.lastSeen ?? 0) > this.intervalMs) {
144
+ if (info.worker) {
145
145
  const msg = { type: 'ping', threadId: info.worker.threadId, threadName: thread.name };
146
146
  info.worker.postMessage(msg);
147
+ this.log.debug(`Sent ping to thread ${thread.name} threadId ${info.worker.threadId}`);
147
148
  }
148
149
  if (info.worker && Date.now() - (info.lastSeen ?? 0) > this.intervalMs * 2) {
149
- this.log.warn(`Thread ${CYAN}${thread.name}${db} has not been seen for more than ${this.intervalMs * 2} ms. It may be unresponsive.`);
150
+ this.log.warn(`Thread ${CYAN}${thread.name}${wr} has not been seen for more than ${this.intervalMs * 2} ms. It may be unresponsive.`);
150
151
  }
151
152
  }
152
153
  }
@@ -205,7 +206,10 @@ export class ThreadsManager {
205
206
  this.log.debug(`Thread ${threadInfo.name} sent a message at ${new Date(now).toISOString()}: ${debugStringify(message)}`);
206
207
  if (message.type === 'init') {
207
208
  threadInfo.runCount = (threadInfo.runCount ?? 0) + 1;
208
- this.log.debug(`Thread ${threadInfo.name} is online started at ${new Date(now).toISOString()} with thread id ${worker.threadId}`);
209
+ this.log.debug(`Thread ${threadInfo.name} is initialized at ${new Date(now).toISOString()} with thread id ${worker.threadId}`);
210
+ }
211
+ else if (message.type === 'ready') {
212
+ this.log.debug(`Thread ${threadInfo.name} is ready at ${new Date(now).toISOString()} with thread id ${worker.threadId}`);
209
213
  if (threadInfo.startup) {
210
214
  const startupMessage = { type: 'startup', threadName: threadInfo.name, threadId: worker.threadId };
211
215
  worker.postMessage(startupMessage);
@@ -10,6 +10,8 @@ export interface ThreadsWrapperEvents {
10
10
  export declare class ThreadsWrapper extends EventEmitter<ThreadsWrapperEvents> {
11
11
  name: ThreadNames;
12
12
  entrypoint: (worker: ThreadsWrapper) => Promise<boolean>;
13
+ startup?: ((worker: ThreadsWrapper) => Promise<void>) | undefined;
14
+ shutdown?: ((worker: ThreadsWrapper) => Promise<void>) | undefined;
13
15
  debug: boolean;
14
16
  verbose: boolean;
15
17
  useTracker: boolean;
@@ -20,7 +22,7 @@ export declare class ThreadsWrapper extends EventEmitter<ThreadsWrapperEvents> {
20
22
  private destroyed;
21
23
  private readonly boundUnhandledRejectionHandler;
22
24
  private readonly boundUncaughtExceptionHandler;
23
- constructor(name: ThreadNames, entrypoint: (worker: ThreadsWrapper) => Promise<boolean>);
25
+ constructor(name: ThreadNames, entrypoint: (worker: ThreadsWrapper) => Promise<boolean>, startup?: ((worker: ThreadsWrapper) => Promise<void>) | undefined, shutdown?: ((worker: ThreadsWrapper) => Promise<void>) | undefined);
24
26
  destroy(success: boolean): void;
25
27
  private handleUnhandledRejection;
26
28
  private handleUncaughtException;
@@ -11,6 +11,8 @@ logModuleLoaded('ThreadsWrapper');
11
11
  export class ThreadsWrapper extends EventEmitter {
12
12
  name;
13
13
  entrypoint;
14
+ startup;
15
+ shutdown;
14
16
  debug = hasAnyParameter('debug', 'verbose', 'debug-threads', 'verbose-threads');
15
17
  verbose = hasAnyParameter('verbose', 'verbose-threads');
16
18
  useTracker = hasAnyParameter('tracker', 'tracker-threads');
@@ -25,10 +27,12 @@ export class ThreadsWrapper extends EventEmitter {
25
27
  boundUncaughtExceptionHandler = (error) => {
26
28
  this.handleUncaughtException(error);
27
29
  };
28
- constructor(name, entrypoint) {
30
+ constructor(name, entrypoint, startup, shutdown) {
29
31
  super();
30
32
  this.name = name;
31
33
  this.entrypoint = entrypoint;
34
+ this.startup = startup;
35
+ this.shutdown = shutdown;
32
36
  if (this.workerData) {
33
37
  this.debug = this.workerData.debug ?? this.debug;
34
38
  this.verbose = this.workerData.verbose ?? this.verbose;
@@ -43,7 +47,7 @@ export class ThreadsWrapper extends EventEmitter {
43
47
  if (this.useTracker) {
44
48
  void import('@matterbridge/utils/tracker')
45
49
  .then(({ Tracker }) => {
46
- this.tracker = new Tracker(`Thread${this.name}`, this.debug || this.useTracker, this.verbose, this.useTracker);
50
+ this.tracker = new Tracker(`Thread${this.name}`, this.debug, this.verbose, this.useTracker);
47
51
  this.tracker.start();
48
52
  return;
49
53
  })
@@ -68,10 +72,32 @@ export class ThreadsWrapper extends EventEmitter {
68
72
  this.parentLog(this.name, "debug", `Worker ${this.name}:${threadId} sent pong message type to parent: ${debugStringify(message)}`);
69
73
  break;
70
74
  case 'startup':
71
- setImmediate(() => this.emit('startup'));
75
+ setImmediate(() => {
76
+ void (async () => {
77
+ try {
78
+ if (startup)
79
+ await startup(this);
80
+ }
81
+ catch (err) {
82
+ inspectError(this.log, `Worker ${this.name} startup failed`, err);
83
+ }
84
+ })();
85
+ this.emit('startup');
86
+ });
72
87
  break;
73
88
  case 'shutdown':
74
- setImmediate(() => this.emit('shutdown'));
89
+ setImmediate(() => {
90
+ void (async () => {
91
+ try {
92
+ if (shutdown)
93
+ await shutdown(this);
94
+ }
95
+ catch (err) {
96
+ inspectError(this.log, `Worker ${this.name} shutdown failed`, err);
97
+ }
98
+ })();
99
+ this.emit('shutdown');
100
+ });
75
101
  break;
76
102
  default:
77
103
  this.parentLog(this.name, "warn", `Worker ${this.name}:${threadId} received unknown message type from parent: ${debugStringify(message)}`);
@@ -95,6 +121,7 @@ export class ThreadsWrapper extends EventEmitter {
95
121
  let success = false;
96
122
  try {
97
123
  success = await entrypoint(this);
124
+ this.parentPost({ type: 'ready', threadId, threadName: this.name, memoryUsage: process.memoryUsage(), success: true });
98
125
  }
99
126
  catch (err) {
100
127
  inspectError(this.log, `Worker ${this.name} entrypoint failed`, err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/thread",
3
- "version": "3.10.14-dev-20261010-607ee18",
3
+ "version": "3.10.14-dev-20261012-c6da540",
4
4
  "description": "Matterbridge thread library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -80,8 +80,8 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@matter/main": "0.17.9",
83
- "@matterbridge/types": "3.10.14-dev-20261010-607ee18",
84
- "@matterbridge/utils": "3.10.14-dev-20261010-607ee18",
83
+ "@matterbridge/types": "3.10.14-dev-20261012-c6da540",
84
+ "@matterbridge/utils": "3.10.14-dev-20261012-c6da540",
85
85
  "@zip.js/zip.js": "2.23.0",
86
86
  "node-ansi-logger": "3.3.1"
87
87
  }