import { EventEmitter } from 'node:events';
import { dirname, extname, join } from 'node:path';
+import { exit } from 'node:process';
import { fileURLToPath } from 'node:url';
import { isMainThread } from 'node:worker_threads';
import chalk from 'chalk';
import { availableParallelism } from 'poolifier';
-import { waitChargingStationEvents } from './ChargingStationUtils';
+import { waitChargingStationEvents } from './Helpers';
import type { AbstractUIServer } from './ui-server/AbstractUIServer';
import { UIServerFactory } from './ui-server/UIServerFactory';
import { version } from '../../package.json' assert { type: 'json' };
const moduleName = 'Bootstrap';
enum exitCodes {
+ succeeded = 0,
missingChargingStationsConfiguration = 1,
noChargingStationTemplates = 2,
+ gracefulShutdownError = 3,
}
export class Bootstrap extends EventEmitter {
performanceStorageConfiguration.uri!,
this.logPrefix(),
));
- Configuration.setConfigurationChangeCallback(async () => Bootstrap.getInstance().restart());
+ Configuration.configurationChangeCallback = async () => Bootstrap.getInstance().restart();
}
public static getInstance(): Bootstrap {
public async start(): Promise<void> {
if (!isMainThread) {
- throw new Error('Cannot start charging stations simulator from worker thread');
+ throw new BaseError('Cannot start charging stations simulator from worker thread');
}
if (this.started === false) {
if (this.starting === false) {
Configuration.workerDynamicPoolInUse() &&
console.warn(
chalk.yellow(
- 'Charging stations simulator is using dynamic pool mode. This is an experimental feature with known issues.\nPlease consider using static pool or worker set mode instead',
+ 'Charging stations simulator is using dynamic pool mode. This is an experimental feature with known issues.\nPlease consider using fixed pool or worker set mode instead',
),
);
console.info(chalk.green('Worker set/pool information:'), this.workerImplementation?.info);
public async stop(): Promise<void> {
if (!isMainThread) {
- throw new Error('Cannot stop charging stations simulator from worker thread');
+ throw new BaseError('Cannot stop charging stations simulator from worker thread');
}
if (this.started === true) {
if (this.stopping === false) {
this.uiServer.buildProtocolRequest(
generateUUID(),
ProcedureName.STOP_CHARGING_STATION,
- Constants.EMPTY_FREEZED_OBJECT,
+ Constants.EMPTY_FROZEN_OBJECT,
),
);
await Promise.race([
if (workerConfiguration?.elementsPerWorker === 'auto') {
elementsPerWorker =
this.numberOfChargingStations > availableParallelism()
- ? Math.round(this.numberOfChargingStations / availableParallelism())
+ ? Math.round(this.numberOfChargingStations / (availableParallelism() * 1.5))
: 1;
}
this.workerImplementation === null &&
// logger.debug(
// `${this.logPrefix()} ${moduleName}.messageHandler: Worker channel message received: ${JSON.stringify(
// msg,
- // null,
+ // undefined,
// 2,
// )}`,
// );
- if (isNullOrUndefined(msg?.event)) {
- return;
- }
try {
switch (msg.event) {
case ChargingStationWorkerMessageEvents.started:
msg.data as Statistics,
);
break;
+ case ChargingStationWorkerMessageEvents.startWorkerElementError:
+ logger.error(
+ `${this.logPrefix()} ${moduleName}.messageHandler: Error occured while starting worker element:`,
+ msg.data,
+ );
+ this.emit(ChargingStationWorkerMessageEvents.startWorkerElementError, msg.data);
+ break;
+ case ChargingStationWorkerMessageEvents.startedWorkerElement:
+ break;
default:
throw new BaseError(
- `Unknown event type: '${msg.event}' for data: ${JSON.stringify(msg.data, null, 2)}`,
+ `Unknown charging station worker event: '${
+ msg.event
+ }' received with data: ${JSON.stringify(msg.data, undefined, 2)}`,
);
}
} catch (error) {
console.warn(
chalk.yellow("'stationTemplateUrls' not defined or empty in configuration, exiting"),
);
- process.exit(exitCodes.missingChargingStationsConfiguration);
+ exit(exitCodes.missingChargingStationsConfiguration);
}
if (this.numberOfChargingStations === 0) {
console.warn(
chalk.yellow('No charging station template enabled in configuration, exiting'),
);
- process.exit(exitCodes.noChargingStationTemplates);
+ exit(exitCodes.noChargingStationTemplates);
}
this.initializedCounters = true;
}
}
private gracefulShutdown = (): void => {
- console.info(`${chalk.green('Graceful shutdown')}`);
this.stop()
.then(() => {
- process.exit(0);
+ console.info(`${chalk.green('Graceful shutdown')}`);
+ exit(exitCodes.succeeded);
})
.catch((error) => {
console.error(chalk.red('Error while shutdowning charging stations simulator: '), error);
- process.exit(1);
+ exit(exitCodes.gracefulShutdownError);
});
};