Skip to content

Commit

Permalink
fix: fix performance configuration change at runtime
Browse files Browse the repository at this point in the history
Signed-off-by: Jérôme Benoit <[email protected]>
  • Loading branch information
Jérôme Benoit committed Nov 27, 2023
1 parent 9a2f0d4 commit 6d2b7d0
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/assets/config-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"processType": "workerSet"
},
"performanceStorage": {
"enabled": true,
"enabled": false,
"type": "jsonfile"
},
"uiServer": {
Expand Down
93 changes: 48 additions & 45 deletions src/charging-station/Bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ export class Bootstrap extends EventEmitter {
private static instance: Bootstrap | null = null;
public numberOfChargingStations!: number;
public numberOfChargingStationTemplates!: number;
private workerImplementation: WorkerAbstract<ChargingStationWorkerData> | null;
private readonly uiServer: AbstractUIServer | null;
private readonly storage!: Storage;
private workerConfiguration?: WorkerConfiguration;
private workerImplementation?: WorkerAbstract<ChargingStationWorkerData>;
private readonly uiServer?: AbstractUIServer;
private storage?: Storage;
private numberOfStartedChargingStations!: number;
private readonly version: string = version;
private initializedCounters: boolean;
private started: boolean;
private starting: boolean;
private stopping: boolean;
private readonly workerScript: string;

private constructor() {
super();
Expand All @@ -79,24 +79,16 @@ export class Bootstrap extends EventEmitter {
this.stopping = false;
this.initializedCounters = false;
this.initializeCounters();
this.workerImplementation = null;
this.workerScript = join(
dirname(fileURLToPath(import.meta.url)),
`ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`,
);
this.uiServer = UIServerFactory.getUIServerImplementation(
Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer),
);
const performanceStorageConfiguration =
Configuration.getConfigurationSection<StorageConfiguration>(
ConfigurationSection.performanceStorage,
);
performanceStorageConfiguration.enabled === true &&
(this.storage = StorageFactory.getStorage(
performanceStorageConfiguration.type!,
performanceStorageConfiguration.uri!,
this.logPrefix(),
));
this.on(ChargingStationWorkerMessageEvents.started, this.workerEventStarted);
this.on(ChargingStationWorkerMessageEvents.stopped, this.workerEventStopped);
this.on(ChargingStationWorkerMessageEvents.updated, this.workerEventUpdated);
this.on(
ChargingStationWorkerMessageEvents.performanceStatistics,
this.workerEventPerformanceStatistics,
);
Configuration.configurationChangeCallback = async () => Bootstrap.getInstance().restart(false);
}

Expand All @@ -112,12 +104,23 @@ export class Bootstrap extends EventEmitter {
if (this.starting === false) {
this.starting = true;
this.initializeCounters();
const workerConfiguration = Configuration.getConfigurationSection<WorkerConfiguration>(
this.workerConfiguration = Configuration.getConfigurationSection<WorkerConfiguration>(
ConfigurationSection.worker,
);
this.initializeWorkerImplementation(workerConfiguration);
this.initializeWorkerImplementation(this.workerConfiguration);
await this.workerImplementation?.start();
await this.storage?.open();
const performanceStorageConfiguration =
Configuration.getConfigurationSection<StorageConfiguration>(
ConfigurationSection.performanceStorage,
);
if (performanceStorageConfiguration.enabled === true) {
this.storage = StorageFactory.getStorage(
performanceStorageConfiguration.type!,
performanceStorageConfiguration.uri!,
this.logPrefix(),
);
await this.storage?.open();
}
Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
.enabled === true && this.uiServer?.start();
// Start ChargingStation object instance in worker thread
Expand All @@ -142,13 +145,13 @@ export class Bootstrap extends EventEmitter {
this.version
} started with ${this.numberOfChargingStations.toString()} charging station(s) from ${this.numberOfChargingStationTemplates.toString()} configured charging station template(s) and ${

Check warning on line 146 in src/charging-station/Bootstrap.ts

View workflow job for this annotation

GitHub Actions / Build simulator with Node 20.x on ubuntu-latest

This line has a length of 194. Maximum allowed is 100
Configuration.workerDynamicPoolInUse()
? `${workerConfiguration.poolMinSize?.toString()}/`
? `${this.workerConfiguration.poolMinSize?.toString()}/`
: ''
}${this.workerImplementation?.size}${
Configuration.workerPoolInUse()
? `/${workerConfiguration.poolMaxSize?.toString()}`
? `/${this.workerConfiguration.poolMaxSize?.toString()}`
: ''
} worker(s) concurrently running in '${workerConfiguration.processType}' mode${
} worker(s) concurrently running in '${this.workerConfiguration.processType}' mode${
!isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker)
? ` (${this.workerImplementation?.maxElementsPerWorker} charging station(s) per worker)`

Check warning on line 156 in src/charging-station/Bootstrap.ts

View workflow job for this annotation

GitHub Actions / Build simulator with Node 20.x on ubuntu-latest

This line has a length of 104. Maximum allowed is 100
: ''
Expand Down Expand Up @@ -191,9 +194,11 @@ export class Bootstrap extends EventEmitter {
}
}
await this.workerImplementation?.stop();
this.workerImplementation = null;
delete this.workerImplementation;
delete this.workerConfiguration;
this.uiServer?.stop();
await this.storage?.close();
delete this.storage;
this.resetCounters();
this.initializedCounters = false;
this.started = false;
Expand Down Expand Up @@ -243,21 +248,23 @@ export class Bootstrap extends EventEmitter {
? Math.round(this.numberOfChargingStations / (availableParallelism() * 1.5))
: 1;
}
this.workerImplementation === null &&
(this.workerImplementation = WorkerFactory.getWorkerImplementation<ChargingStationWorkerData>(
this.workerScript,
workerConfiguration.processType!,
{
workerStartDelay: workerConfiguration.startDelay,
elementStartDelay: workerConfiguration.elementStartDelay,
poolMaxSize: workerConfiguration.poolMaxSize!,
poolMinSize: workerConfiguration.poolMinSize!,
elementsPerWorker: elementsPerWorker ?? (workerConfiguration.elementsPerWorker as number),
poolOptions: {
messageHandler: this.messageHandler.bind(this) as (message: unknown) => void,
},
this.workerImplementation = WorkerFactory.getWorkerImplementation<ChargingStationWorkerData>(
join(
dirname(fileURLToPath(import.meta.url)),
`ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`,
),
workerConfiguration.processType!,
{
workerStartDelay: workerConfiguration.startDelay,
elementStartDelay: workerConfiguration.elementStartDelay,
poolMaxSize: workerConfiguration.poolMaxSize!,
poolMinSize: workerConfiguration.poolMinSize!,
elementsPerWorker: elementsPerWorker ?? (workerConfiguration.elementsPerWorker as number),
poolOptions: {
messageHandler: this.messageHandler.bind(this) as (message: unknown) => void,
},
));
},
);
}

private messageHandler(
Expand All @@ -273,19 +280,15 @@ export class Bootstrap extends EventEmitter {
try {
switch (msg.event) {
case ChargingStationWorkerMessageEvents.started:
this.workerEventStarted(msg.data as ChargingStationData);
this.emit(ChargingStationWorkerMessageEvents.started, msg.data as ChargingStationData);
break;
case ChargingStationWorkerMessageEvents.stopped:
this.workerEventStopped(msg.data as ChargingStationData);
this.emit(ChargingStationWorkerMessageEvents.stopped, msg.data as ChargingStationData);
break;
case ChargingStationWorkerMessageEvents.updated:
this.workerEventUpdated(msg.data as ChargingStationData);
this.emit(ChargingStationWorkerMessageEvents.updated, msg.data as ChargingStationData);
break;
case ChargingStationWorkerMessageEvents.performanceStatistics:
this.workerEventPerformanceStatistics(msg.data as Statistics);
this.emit(
ChargingStationWorkerMessageEvents.performanceStatistics,
msg.data as Statistics,
Expand Down Expand Up @@ -346,7 +349,7 @@ export class Bootstrap extends EventEmitter {
};

private workerEventPerformanceStatistics = (data: Statistics) => {
this.storage.storePerformanceStatistics(data) as void;
this.storage?.storePerformanceStatistics(data) as void;
};

private initializeCounters() {
Expand Down
4 changes: 1 addition & 3 deletions src/charging-station/ui-server/UIServerFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class UIServerFactory {

public static getUIServerImplementation(
uiServerConfiguration: UIServerConfiguration,
): AbstractUIServer | null {
): AbstractUIServer | undefined {
if (UIServerUtils.isLoopback(uiServerConfiguration.options!.host!) === false) {
console.warn(
chalk.yellow(
Expand Down Expand Up @@ -45,8 +45,6 @@ export class UIServerFactory {
return new UIWebSocketServer(uiServerConfiguration);
case ApplicationProtocol.HTTP:
return new UIHttpServer(uiServerConfiguration);
default:
return null;
}
}
}
8 changes: 6 additions & 2 deletions src/performance/storage/StorageFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ export class StorageFactory {
// This is intentional
}

public static getStorage(type: StorageType, connectionUri: string, logPrefix: string): Storage {
let storageInstance: Storage | null = null;
public static getStorage(
type: StorageType,
connectionUri: string,
logPrefix: string,
): Storage | undefined {
let storageInstance: Storage;
switch (type) {
case StorageType.JSON_FILE:
storageInstance = new JsonFileStorage(connectionUri, logPrefix);
Expand Down
4 changes: 2 additions & 2 deletions src/worker/WorkerFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ export class WorkerFactory {
workerScript: string,
workerProcessType: WorkerProcessType,
workerOptions?: WorkerOptions,
): WorkerAbstract<T> | null {
): WorkerAbstract<T> | undefined {
if (!isMainThread) {
throw new Error('Cannot get a worker implementation outside the main thread');
}
workerOptions = { ...DEFAULT_WORKER_OPTIONS, ...workerOptions };
let workerImplementation: WorkerAbstract<T> | null = null;
let workerImplementation: WorkerAbstract<T>;
switch (workerProcessType) {
case WorkerProcessType.workerSet:
workerImplementation = new WorkerSet(workerScript, workerOptions);
Expand Down

0 comments on commit 6d2b7d0

Please sign in to comment.