-// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { ChargingStationWorkerData, WorkerMessage, WorkerMessageEvents } from '../types/Worker';
-import { parentPort, workerData } from 'worker_threads';
+import { AsyncResource } from 'node:async_hooks';
+import { parentPort } from 'node:worker_threads';
-import ChargingStation from './ChargingStation';
-import Constants from '../utils/Constants';
import { ThreadWorker } from 'poolifier';
-import Utils from '../utils/Utils';
-// Conditionally export ThreadWorker instance for pool usage
-export let threadWorker: ThreadWorker;
-if (Utils.workerPoolInUse()) {
- threadWorker = new ThreadWorker<ChargingStationWorkerData>(startChargingStation, { maxInactiveTime: Constants.WORKER_POOL_MAX_INACTIVE_TIME, async: false });
-} else {
- // Add message listener to start charging station from main thread
- addMessageListener();
- if (!Utils.isUndefined(workerData)) {
- startChargingStation({ index: workerData.index as number, templateFile: workerData.templateFile as string });
- }
-}
+import { ChargingStation } from './ChargingStation';
+import type { ChargingStationWorkerData } from '../types';
+import { Configuration } from '../utils';
+import { WorkerConstants, type WorkerMessage, WorkerMessageEvents } from '../worker';
-/**
- * Listen messages send by the main thread
- */
-function addMessageListener(): void {
- parentPort?.on('message', (message: WorkerMessage) => {
- if (message.id === WorkerMessageEvents.START_WORKER_ELEMENT) {
- startChargingStation(message.data);
- }
- });
-}
+const moduleName = 'ChargingStationWorker';
/**
- * Create and start a charging station instance
+ * Creates and starts a charging station instance
*
- * @param data workerData
+ * @param data - workerData
*/
-function startChargingStation(data: ChargingStationWorkerData): void {
- const station = new ChargingStation(data.index, data.templateFile);
- station.start();
+const startChargingStation = (data?: ChargingStationWorkerData): void => {
+ new ChargingStation(data!.index, data!.templateFile).start();
+};
+
+class ChargingStationWorker extends AsyncResource {
+ constructor() {
+ super(moduleName);
+ // Add message listener to create and start charging station from the main thread
+ parentPort?.on('message', (message: WorkerMessage<ChargingStationWorkerData>) => {
+ switch (message.event) {
+ case WorkerMessageEvents.startWorkerElement:
+ try {
+ this.runInAsyncScope(
+ startChargingStation.bind(this) as (data?: ChargingStationWorkerData) => void,
+ this,
+ message.data,
+ );
+ parentPort?.postMessage({
+ event: WorkerMessageEvents.startedWorkerElement,
+ });
+ } catch (error) {
+ parentPort?.postMessage({
+ event: WorkerMessageEvents.startWorkerElementError,
+ data: {
+ message: (error as Error).message,
+ stack: (error as Error).stack,
+ },
+ });
+ }
+ break;
+ default:
+ throw new Error(
+ `Unknown worker event: '${message.event}' received with data: '${JSON.stringify(
+ message.data,
+ null,
+ 2,
+ )}'`,
+ );
+ }
+ });
+ }
+}
+
+export let chargingStationWorker: ChargingStationWorker | ThreadWorker<ChargingStationWorkerData>;
+if (Configuration.workerPoolInUse()) {
+ chargingStationWorker = new ThreadWorker<ChargingStationWorkerData>(startChargingStation, {
+ maxInactiveTime: WorkerConstants.POOL_MAX_INACTIVE_TIME,
+ });
+} else {
+ chargingStationWorker = new ChargingStationWorker();
}