@matterbridge/thread 3.9.3-dev-20260627-5d60de5 → 3.9.3-dev-20260628-fa05360

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.
@@ -145,22 +145,26 @@ export class ThreadsManager {
145
145
  else if (message.type === 'exit') {
146
146
  threadInfo.lastStopped = now;
147
147
  threadInfo.lastDuration = Math.max(0, now - (threadInfo.lastStarted ?? now));
148
+ if (!message.success) {
149
+ threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
150
+ }
148
151
  threadInfo.worker = undefined;
149
152
  this.log.debug(`Thread ${threadInfo.name} has exited at ${new Date(now).toISOString()} with thread id ${worker.threadId} after running for ${threadInfo.lastDuration} ms`);
150
153
  }
151
154
  });
152
155
  worker.on('messageerror', () => {
153
156
  const now = Date.now();
157
+ threadInfo.lastSeen = now;
154
158
  threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
155
159
  this.log.error(`Thread ${threadInfo.name} encountered a message error at ${new Date(now).toISOString()}`);
156
160
  });
157
161
  worker.once('error', (error) => {
158
162
  const now = Date.now();
159
- threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
163
+ threadInfo.lastSeen = now;
160
164
  threadInfo.lastStopped = now;
161
165
  threadInfo.lastDuration = Math.max(0, now - (threadInfo.lastStarted ?? now));
166
+ threadInfo.errorCount = (threadInfo.errorCount ?? 0) + 1;
162
167
  threadInfo.worker = undefined;
163
- threadInfo.lastSeen = now;
164
168
  this.log.error(`Thread ${threadInfo.name} encountered an error at ${new Date(now).toISOString()} after running for ${threadInfo.lastDuration} ms: ${getErrorMessage(error)}`);
165
169
  });
166
170
  this.log.debug(`Started thread ${threadInfo.name} from path ${path} type ${threadInfo.type} with thread id ${worker.threadId}`);
@@ -12,8 +12,14 @@ export declare class WorkerWrapper {
12
12
  server: BroadcastServer;
13
13
  workerData: WorkerData | null;
14
14
  tracker: Tracker | undefined;
15
+ private destroyed;
16
+ private readonly boundUnhandledRejectionHandler;
17
+ private readonly boundUncaughtExceptionHandler;
15
18
  constructor(name: ThreadNames, callback: (worker: WorkerWrapper) => Promise<boolean>);
16
19
  destroy(success: boolean): void;
20
+ private handleUnhandledRejection;
21
+ private handleUncaughtException;
22
+ private safeParentLog;
17
23
  parentPost(message: ParentPortMessage): void;
18
24
  parentLog(logName: string | undefined, logLevel: LogLevel, message: string): void;
19
25
  logger(level: LogLevel, message: string): void;
@@ -17,6 +17,13 @@ export class WorkerWrapper {
17
17
  server;
18
18
  workerData = workerData;
19
19
  tracker;
20
+ destroyed = false;
21
+ boundUnhandledRejectionHandler = (reason) => {
22
+ this.handleUnhandledRejection(reason);
23
+ };
24
+ boundUncaughtExceptionHandler = (error) => {
25
+ this.handleUncaughtException(error);
26
+ };
20
27
  constructor(name, callback) {
21
28
  this.name = name;
22
29
  this.callback = callback;
@@ -45,6 +52,10 @@ export class WorkerWrapper {
45
52
  logLevel: this.debug ? "debug" : "info",
46
53
  });
47
54
  this.server = new BroadcastServer('matterbridge', this.log);
55
+ if (!isMainThread) {
56
+ process.on('unhandledRejection', this.boundUnhandledRejectionHandler);
57
+ process.on('uncaughtException', this.boundUncaughtExceptionHandler);
58
+ }
48
59
  if (!isMainThread && parentPort && this.workerData) {
49
60
  parentPort.on('message', (message) => {
50
61
  if (this.debug)
@@ -92,20 +103,57 @@ export class WorkerWrapper {
92
103
  }
93
104
  }
94
105
  destroy(success) {
106
+ if (this.destroyed)
107
+ return;
108
+ this.destroyed = true;
109
+ if (!isMainThread) {
110
+ process.off('unhandledRejection', this.boundUnhandledRejectionHandler);
111
+ process.off('uncaughtException', this.boundUncaughtExceptionHandler);
112
+ }
95
113
  if (this.tracker)
96
114
  this.tracker.stop();
97
115
  this.server.close();
98
116
  if (!isMainThread && parentPort && this.workerData) {
99
117
  if (this.debug)
100
118
  this.parentLog(this.name, "info", `Worker ${this.name}:${threadId} exiting with success: ${success}.`);
101
- this.parentPost({ type: 'exit', threadId, threadName: this.name, memoryUsage: process.memoryUsage(), success });
102
- parentPort.close();
119
+ try {
120
+ this.parentPost({ type: 'exit', threadId, threadName: this.name, memoryUsage: process.memoryUsage(), success });
121
+ }
122
+ catch (error) {
123
+ this.log.error(`Worker ${this.name}:${threadId} failed to send exit message to parent: ${getErrorMessage(error)}`);
124
+ }
125
+ try {
126
+ parentPort.close();
127
+ }
128
+ catch (error) {
129
+ this.log.error(`Worker ${this.name}:${threadId} failed to close parentPort: ${getErrorMessage(error)}`);
130
+ }
103
131
  }
104
132
  else {
105
133
  if (this.debug)
106
134
  this.log.debug(`Worker ${this.name}:${threadId} exiting with success in main thread: ${success}.`);
107
135
  }
108
136
  }
137
+ handleUnhandledRejection(reason) {
138
+ const errorMessage = inspectError(this.log, `Worker ${this.name} unhandled rejection`, reason);
139
+ this.safeParentLog("error", errorMessage);
140
+ this.destroy(false);
141
+ }
142
+ handleUncaughtException(error) {
143
+ const errorMessage = inspectError(this.log, `Worker ${this.name} uncaught exception`, error);
144
+ this.safeParentLog("error", errorMessage);
145
+ this.destroy(false);
146
+ }
147
+ safeParentLog(level, message) {
148
+ if (this.destroyed)
149
+ return;
150
+ try {
151
+ this.logger(level, message);
152
+ }
153
+ catch (error) {
154
+ this.log.error(`Worker ${this.name} failed to send error log to parent: ${getErrorMessage(error)}`);
155
+ }
156
+ }
109
157
  parentPost(message) {
110
158
  if (!parentPort)
111
159
  throw new Error(`WorkerServer ${this.name}: parentPort is not available.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/thread",
3
- "version": "3.9.3-dev-20260627-5d60de5",
3
+ "version": "3.9.3-dev-20260628-fa05360",
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-20260627-5d60de5",
73
- "@matterbridge/utils": "3.9.3-dev-20260627-5d60de5",
72
+ "@matterbridge/types": "3.9.3-dev-20260628-fa05360",
73
+ "@matterbridge/utils": "3.9.3-dev-20260628-fa05360",
74
74
  "@zip.js/zip.js": "2.8.26",
75
75
  "node-ansi-logger": "3.3.0"
76
76
  }