@matterbridge/thread 3.9.3-dev-20260629-7c47082 → 3.9.3-dev-20260630-684e0d2

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,9 +12,11 @@ export declare class ThreadsManager {
12
12
  private interval;
13
13
  private intervalMs;
14
14
  private threads;
15
+ private terminateWorkers;
15
16
  constructor(intervalMs?: number);
16
17
  destroy(): void;
17
18
  private msgHandler;
19
+ private terminateExitedWorkers;
18
20
  private intervalHandler;
19
21
  runThread(name: string, workerData?: WorkerData, argv?: string[], env?: NodeJS.ProcessEnv, execArgv?: string[], pipedOutput?: boolean): Worker;
20
22
  runInMainThread(name: string, workerData?: WorkerData | null): Promise<boolean>;
@@ -5,6 +5,7 @@ import { Worker } from 'node:worker_threads';
5
5
  import { hasParameter } from '@matterbridge/utils/cli';
6
6
  import { getErrorMessage } from '@matterbridge/utils/error';
7
7
  import { logModuleLoaded } from '@matterbridge/utils/loader';
8
+ import { fireAndForget } from '@matterbridge/utils/wait';
8
9
  import { AnsiLogger, CYAN, db, debugStringify, ft, MAGENTA, wr } from 'node-ansi-logger';
9
10
  import { BroadcastServer } from './broadcastServer.js';
10
11
  logModuleLoaded('ThreadsManager');
@@ -26,6 +27,7 @@ export class ThreadsManager {
26
27
  { name: 'ArchiveCommand', path: 'workerArchiveCommand.js', type: 'worker' },
27
28
  { name: 'DockerVersion', path: 'workerDockerVersion.js', type: 'worker' },
28
29
  ];
30
+ terminateWorkers = new Set();
29
31
  constructor(intervalMs = 60_000) {
30
32
  this.debug = hasParameter('debug') || hasParameter('verbose') || hasParameter('debug-threads') || hasParameter('verbose-threads');
31
33
  this.verbose = hasParameter('verbose') || hasParameter('verbose-threads');
@@ -47,6 +49,7 @@ export class ThreadsManager {
47
49
  }
48
50
  destroy() {
49
51
  clearInterval(this.interval);
52
+ this.terminateExitedWorkers();
50
53
  this.server.off('broadcast_message', this.boundMsgHandler);
51
54
  this.server.close();
52
55
  if (this.verbose)
@@ -83,10 +86,26 @@ export class ThreadsManager {
83
86
  }
84
87
  }
85
88
  }
89
+ terminateExitedWorkers() {
90
+ if (this.terminateWorkers.size > 0) {
91
+ this.log.debug(`Terminating ${this.terminateWorkers.size} workers that have exited...`);
92
+ for (const worker of this.terminateWorkers) {
93
+ try {
94
+ this.log.debug(`Terminating worker with thread id ${worker.threadId}...`);
95
+ fireAndForget(worker.terminate(), this.log, `Failed to terminate worker with thread id ${worker.threadId}`);
96
+ }
97
+ catch (error) {
98
+ this.log.error(`Failed to terminate worker with thread id ${worker.threadId}: ${getErrorMessage(error)}`);
99
+ }
100
+ }
101
+ this.terminateWorkers.clear();
102
+ }
103
+ }
86
104
  intervalHandler() {
87
105
  for (const thread of this.threads) {
88
106
  this.log.debug(`Thread ${thread.name} running: ${thread.worker ? 'yes' : 'no'}, lastSeen: ${thread.lastSeen ? new Date(thread.lastSeen).toISOString() : 'never'}, runs: ${thread.runCount ?? 0}, errors: ${thread.errorCount ?? 0}`);
89
107
  }
108
+ this.terminateExitedWorkers();
90
109
  for (const thread of this.threads) {
91
110
  if (thread.worker && Date.now() - (thread.lastSeen ?? 0) > this.intervalMs) {
92
111
  const msg = { type: 'ping', threadId: thread.worker.threadId, threadName: thread.name };
@@ -128,6 +147,7 @@ export class ThreadsManager {
128
147
  threadInfo.worker = undefined;
129
148
  }
130
149
  this.log.debug(`Thread ${threadInfo.name} has exited at ${new Date(now).toISOString()}`);
150
+ this.terminateWorkers.delete(worker);
131
151
  });
132
152
  worker.on('message', (message) => {
133
153
  const now = Date.now();
@@ -148,6 +168,7 @@ export class ThreadsManager {
148
168
  if (!message.success) {
149
169
  threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
150
170
  }
171
+ this.terminateWorkers.add(worker);
151
172
  threadInfo.worker = undefined;
152
173
  this.log.debug(`Thread ${threadInfo.name} has exited at ${new Date(now).toISOString()} with thread id ${worker.threadId} after running for ${threadInfo.lastDuration} ms`);
153
174
  }
@@ -165,6 +186,7 @@ export class ThreadsManager {
165
186
  threadInfo.lastDuration = Math.max(0, now - (threadInfo.lastStarted ?? now));
166
187
  threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
167
188
  threadInfo.worker = undefined;
189
+ this.terminateWorkers.add(worker);
168
190
  this.log.error(`Thread ${threadInfo.name} encountered an error at ${new Date(now).toISOString()} after running for ${threadInfo.lastDuration} ms: ${getErrorMessage(error)}`);
169
191
  });
170
192
  this.log.debug(`Started thread ${threadInfo.name} from path ${path} type ${threadInfo.type} with thread id ${worker.threadId}`);
@@ -124,7 +124,6 @@ export class WorkerWrapper {
124
124
  }
125
125
  try {
126
126
  parentPort.close();
127
- process.exit(success ? 0 : 1);
128
127
  }
129
128
  catch (error) {
130
129
  this.log.error(`Worker ${this.name}:${threadId} failed to close parentPort: ${getErrorMessage(error)}`);
@@ -146,6 +145,7 @@ export class WorkerWrapper {
146
145
  this.destroy(false);
147
146
  }
148
147
  safeParentLog(level, message) {
148
+ this.log.error(`Worker ${this.name}: ${message}`);
149
149
  if (this.destroyed)
150
150
  return;
151
151
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/thread",
3
- "version": "3.9.3-dev-20260629-7c47082",
3
+ "version": "3.9.3-dev-20260630-684e0d2",
4
4
  "description": "Matterbridge thread library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -69,8 +69,8 @@
69
69
  "CHANGELOG.md"
70
70
  ],
71
71
  "dependencies": {
72
- "@matterbridge/types": "3.9.3-dev-20260629-7c47082",
73
- "@matterbridge/utils": "3.9.3-dev-20260629-7c47082",
72
+ "@matterbridge/types": "3.9.3-dev-20260630-684e0d2",
73
+ "@matterbridge/utils": "3.9.3-dev-20260630-684e0d2",
74
74
  "@zip.js/zip.js": "2.8.26",
75
75
  "node-ansi-logger": "3.3.0"
76
76
  }