X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Futils%2FConfiguration.ts;h=118ea64011aca7d5a9f435c922d2b01c8f9d12de;hb=d05b53c7a03b8fad2e106caee68d5871cc6aac6e;hp=dee8056c433d73c1a57c2670650cc913a1439fb6;hpb=ea32ea059bfdd7134abe2ba349985e5b15bc1d06;p=e-mobility-charging-stations-simulator.git diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index dee8056c..118ea640 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -1,4 +1,4 @@ -import { type FSWatcher, readFileSync, watch } from 'node:fs' +import { existsSync, type FSWatcher, readFileSync, watch } from 'node:fs' import { dirname, join } from 'node:path' import { env } from 'node:process' import { fileURLToPath } from 'node:url' @@ -21,7 +21,7 @@ import { type WorkerConfiguration } from '../types/index.js' import { - DEFAULT_ELEMENT_START_DELAY, + DEFAULT_ELEMENT_ADD_DELAY, DEFAULT_POOL_MAX_SIZE, DEFAULT_POOL_MIN_SIZE, DEFAULT_WORKER_START_DELAY, @@ -44,28 +44,80 @@ type ConfigurationSectionType = | WorkerConfiguration | UIServerConfiguration +const defaultUIServerConfiguration: UIServerConfiguration = { + enabled: false, + type: ApplicationProtocol.WS, + version: ApplicationProtocolVersion.VERSION_11, + options: { + host: Constants.DEFAULT_UI_SERVER_HOST, + port: Constants.DEFAULT_UI_SERVER_PORT + } +} + +const defaultStorageConfiguration: StorageConfiguration = { + enabled: true, + type: StorageType.NONE +} + +const defaultLogConfiguration: LogConfiguration = { + enabled: true, + file: 'logs/combined.log', + errorFile: 'logs/error.log', + statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL, + level: 'info', + format: 'simple', + rotate: true +} + +const defaultWorkerConfiguration: WorkerConfiguration = { + processType: WorkerProcessType.workerSet, + startDelay: DEFAULT_WORKER_START_DELAY, + elementsPerWorker: 'auto', + elementAddDelay: DEFAULT_ELEMENT_ADD_DELAY, + poolMinSize: DEFAULT_POOL_MIN_SIZE, + poolMaxSize: DEFAULT_POOL_MAX_SIZE +} + // eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Configuration { public static configurationChangeCallback?: () => Promise - private static readonly configurationFile = join( - dirname(fileURLToPath(import.meta.url)), - 'assets', - 'config.json' - ) - + private static configurationFile: string | undefined private static configurationFileReloading = false private static configurationData?: ConfigurationData private static configurationFileWatcher?: FSWatcher - private static readonly configurationSectionCache = new Map< - ConfigurationSection, - ConfigurationSectionType - >([ - [ConfigurationSection.log, Configuration.buildLogSection()], - [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()], - [ConfigurationSection.worker, Configuration.buildWorkerSection()], - [ConfigurationSection.uiServer, Configuration.buildUIServerSection()] - ]) + private static configurationSectionCache: Map + + static { + const configurationFile = join(dirname(fileURLToPath(import.meta.url)), 'assets', 'config.json') + if (existsSync(configurationFile)) { + Configuration.configurationFile = configurationFile + } else { + console.error( + `${chalk.green(logPrefix())} ${chalk.red( + `Configuration file '${configurationFile}' not found, using default configuration` + )}` + ) + Configuration.configurationData = { + stationTemplateUrls: [], + supervisionUrls: 'ws://localhost:8180/steve/websocket/CentralSystemService', + supervisionUrlDistribution: SupervisionUrlDistribution.ROUND_ROBIN, + uiServer: defaultUIServerConfiguration, + performanceStorage: defaultStorageConfiguration, + log: defaultLogConfiguration, + worker: defaultWorkerConfiguration + } + } + Configuration.configurationSectionCache = new Map< + ConfigurationSection, + ConfigurationSectionType + >([ + [ConfigurationSection.log, Configuration.buildLogSection()], + [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()], + [ConfigurationSection.worker, Configuration.buildWorkerSection()], + [ConfigurationSection.uiServer, Configuration.buildUIServerSection()] + ]) + } private constructor () { // This is intentional @@ -152,15 +204,7 @@ export class Configuration { } private static buildUIServerSection (): UIServerConfiguration { - let uiServerConfiguration: UIServerConfiguration = { - enabled: false, - type: ApplicationProtocol.WS, - version: ApplicationProtocolVersion.VERSION_11, - options: { - host: Constants.DEFAULT_UI_SERVER_HOST, - port: Constants.DEFAULT_UI_SERVER_PORT - } - } + let uiServerConfiguration: UIServerConfiguration = defaultUIServerConfiguration if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.uiServer)) { uiServerConfiguration = mergeDeepRight( uiServerConfiguration, @@ -171,7 +215,7 @@ export class Configuration { if (isCFEnvironment()) { delete uiServerConfiguration.options?.host // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - uiServerConfiguration.options!.port = parseInt(env.PORT!) + uiServerConfiguration.options!.port = Number.parseInt(env.PORT!) } return uiServerConfiguration } @@ -195,10 +239,7 @@ export class Configuration { break case StorageType.NONE: default: - storageConfiguration = { - enabled: true, - type: StorageType.NONE - } + storageConfiguration = defaultStorageConfiguration break } if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.performanceStorage)) { @@ -220,15 +261,6 @@ export class Configuration { } private static buildLogSection (): LogConfiguration { - const defaultLogConfiguration: LogConfiguration = { - enabled: true, - file: 'logs/combined.log', - errorFile: 'logs/error.log', - statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL, - level: 'info', - format: 'simple', - rotate: true - } const deprecatedLogConfiguration: LogConfiguration = { ...(hasOwnProp(Configuration.getConfigurationData(), 'logEnabled') && { enabled: Configuration.getConfigurationData()?.logEnabled @@ -271,14 +303,6 @@ export class Configuration { } private static buildWorkerSection (): WorkerConfiguration { - const defaultWorkerConfiguration: WorkerConfiguration = { - processType: WorkerProcessType.workerSet, - startDelay: DEFAULT_WORKER_START_DELAY, - elementsPerWorker: 'auto', - elementStartDelay: DEFAULT_ELEMENT_START_DELAY, - poolMinSize: DEFAULT_POOL_MIN_SIZE, - poolMaxSize: DEFAULT_POOL_MAX_SIZE - } const deprecatedWorkerConfiguration: WorkerConfiguration = { ...(hasOwnProp(Configuration.getConfigurationData(), 'workerProcess') && { processType: Configuration.getConfigurationData()?.workerProcess @@ -289,8 +313,11 @@ export class Configuration { ...(hasOwnProp(Configuration.getConfigurationData(), 'chargingStationsPerWorker') && { elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker }), - ...(hasOwnProp(Configuration.getConfigurationData(), 'elementStartDelay') && { - elementStartDelay: Configuration.getConfigurationData()?.elementStartDelay + ...(hasOwnProp(Configuration.getConfigurationData(), 'elementAddDelay') && { + elementAddDelay: Configuration.getConfigurationData()?.elementAddDelay + }), + ...(hasOwnProp(Configuration.getConfigurationData()?.worker, 'elementStartDelay') && { + elementAddDelay: Configuration.getConfigurationData()?.worker?.elementStartDelay }), ...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMinSize') && { poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize @@ -396,9 +423,9 @@ export class Configuration { `Use '${ConfigurationSection.worker}' section to define the number of element(s) per worker instead` ) Configuration.warnDeprecatedConfigurationKey( - 'elementStartDelay', + 'elementAddDelay', undefined, - `Use '${ConfigurationSection.worker}' section to define the worker's element start delay instead` + `Use '${ConfigurationSection.worker}' section to define the worker's element add delay instead` ) Configuration.warnDeprecatedConfigurationKey( 'workerPoolMinSize', @@ -425,6 +452,11 @@ export class Configuration { ConfigurationSection.worker, 'Not publicly exposed to end users' ) + Configuration.warnDeprecatedConfigurationKey( + 'elementStartDelay', + ConfigurationSection.worker, + "Use 'elementAddDelay' instead" + ) if ( Configuration.getConfigurationData()?.worker?.processType === ('staticPool' as WorkerProcessType) @@ -504,22 +536,22 @@ export class Configuration { private static warnDeprecatedConfigurationKey ( key: string, - sectionName?: string, + configurationSection?: ConfigurationSection, logMsgToAppend = '' ): void { if ( - sectionName != null && - Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData] != null && + configurationSection != null && + Configuration.getConfigurationData()?.[configurationSection as keyof ConfigurationData] != + null && ( - Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData] as Record< - string, - unknown - > + Configuration.getConfigurationData()?.[ + configurationSection as keyof ConfigurationData + ] as Record )[key] != null ) { console.error( `${chalk.green(logPrefix())} ${chalk.red( - `Deprecated configuration key '${key}' usage in section '${sectionName}'${ + `Deprecated configuration key '${key}' usage in section '${configurationSection}'${ logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : '' }` )}` @@ -535,8 +567,12 @@ export class Configuration { } } - private static getConfigurationData (): ConfigurationData | undefined { - if (Configuration.configurationData == null) { + public static getConfigurationData (): ConfigurationData | undefined { + if ( + Configuration.configurationData == null && + Configuration.configurationFile != null && + Configuration.configurationFile.length > 0 + ) { try { Configuration.configurationData = JSON.parse( readFileSync(Configuration.configurationFile, 'utf8') @@ -557,6 +593,9 @@ export class Configuration { } private static getConfigurationFileWatcher (): FSWatcher | undefined { + if (Configuration.configurationFile == null || Configuration.configurationFile.length === 0) { + return + } try { return watch(Configuration.configurationFile, (event, filename): void => { if (