Make the worker start delay a tunable.
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 30 Apr 2021 18:54:37 +0000 (20:54 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 30 Apr 2021 18:54:37 +0000 (20:54 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
12 files changed:
package-lock.json
package.json
src/charging-station/Bootstrap.ts
src/types/ConfigurationData.ts
src/types/Worker.ts
src/utils/Configuration.ts
src/utils/Constants.ts
src/worker/WorkerAbstract.ts
src/worker/WorkerDynamicPool.ts
src/worker/WorkerFactory.ts
src/worker/WorkerSet.ts
src/worker/WorkerStaticPool.ts

index 95ce88e6458b2b0cf12159da402c32ac3df49d0d..3706f3c8b8e03d899e29eae36d9de12df601501f 100644 (file)
         "kuler": "^2.0.0"
       }
     },
+    "@es-joy/jsdoccomment": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.1.1.tgz",
+      "integrity": "sha512-6lIx5Pjc50D7VJU9lfRZ1twfIrIwQk+aeT9Ink2C07IUu/y9pxkIpDqmhY/VN3jAW42dA5z6ioOdyhOZZU1isw==",
+      "dev": true
+    },
     "@eslint/eslintrc": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
       }
     },
     "eslint-plugin-jsdoc": {
-      "version": "32.3.3",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-32.3.3.tgz",
-      "integrity": "sha512-WxXohbMYlZvCt3r7MepwT++nTLsO4CPegWcm5toM4IGq3MBmYkG+Uf5yDa+n1MwPXLg+KbJqAsI19hmkVD7MPg==",
+      "version": "33.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-33.0.0.tgz",
+      "integrity": "sha512-bkopnnuDdT04abKWPfDdD6XcAp2yX6UDpDViyvIdYmxbZYbpHXCRzQzLqCTo+SzWSTS0KFWz/V3shmmMr+x4EA==",
       "dev": true,
       "requires": {
+        "@es-joy/jsdoccomment": "^0.1.1",
         "comment-parser": "1.1.5",
         "debug": "^4.3.1",
         "jsdoctypeparser": "^9.0.0",
index e7c480ee79dd0088af1c5d3dfe2f800d320f765d..adca5292ef3bf1b526889a507ca464fceee7e6fb 100644 (file)
@@ -70,7 +70,7 @@
     "cross-env": "^7.0.3",
     "eslint": "^7.25.0",
     "eslint-plugin-import": "^2.22.1",
-    "eslint-plugin-jsdoc": "^32.3.3",
+    "eslint-plugin-jsdoc": "^33.0.0",
     "mbt": "^1.1.1",
     "npm-check": "^5.9.2",
     "rollup": "^2.46.0",
index ddf21f48bb61721686bb81c45d2a23424fdd2330..bb101ca7b75bf3f79153770a0d0dce82ef51d494 100644 (file)
@@ -78,11 +78,13 @@ export default class Bootstrap {
 
   private getWorkerImplementationInstance(): WorkerAbstract {
     if (!this.workerImplementationInstance) {
-      this.workerImplementationInstance = WorkerFactory.getWorkerImplementation<StationWorkerData>(this.workerScript, Configuration.getWorkerProcess(), {
-        poolMaxSize: Configuration.getWorkerPoolMaxSize(),
-        poolMinSize: Configuration.getWorkerPoolMinSize(),
-        elementsPerWorker: Configuration.getChargingStationsPerWorker()
-      });
+      this.workerImplementationInstance = WorkerFactory.getWorkerImplementation<StationWorkerData>(this.workerScript, Configuration.getWorkerProcess(),
+        {
+          startDelay: Configuration.getWorkerStartDelay(),
+          poolMaxSize: Configuration.getWorkerPoolMaxSize(),
+          poolMinSize: Configuration.getWorkerPoolMinSize(),
+          elementsPerWorker: Configuration.getChargingStationsPerWorker()
+        });
     }
     return this.workerImplementationInstance;
   }
index 125ecef636d693afc840fd16b35abde81308a0ec..9c7c098e2395667660f43138dd6616755bf3d072 100644 (file)
@@ -13,6 +13,7 @@ export default interface ConfigurationData {
   autoReconnectMaxRetries?: number;
   distributeStationsToTenantsEqually?: boolean;
   workerProcess?: WorkerProcessType;
+  workerStartDelay?: number;
   workerPoolMinSize?: number;
   workerPoolMaxSize?: number;
   chargingStationsPerWorker?: number;
index bc2972684c0cb2677f34176ffbd11b119392d423..dde976aea42278d2c3e17c63ec891e9c44849f58 100644 (file)
@@ -7,12 +7,14 @@ export enum WorkerProcessType {
 }
 
 export interface WorkerOptions {
+  startDelay?: number;
   poolMaxSize?: number;
   poolMinSize?: number;
   elementsPerWorker?: number;
 }
 
-export interface WorkerData { }
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface WorkerData {}
 
 export interface StationWorkerData extends WorkerData {
   index: number;
index 552fab21dc21bb764b179a7ca49078c2ae4214f4..4bc1853d2d8543db22b4f8c3d35996100467dcc1 100644 (file)
@@ -1,5 +1,6 @@
 import ConfigurationData, { StationTemplateURL } from '../types/ConfigurationData';
 
+import Constants from './Constants';
 import { WorkerProcessType } from '../types/Worker';
 import fs from 'fs';
 import path from 'path';
@@ -51,6 +52,10 @@ export default class Configuration {
     return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'workerProcess') ? Configuration.getConfig().workerProcess : WorkerProcessType.WORKER_SET;
   }
 
+  static getWorkerStartDelay(): number {
+    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'workerStartDelay') ? Configuration.getConfig().workerStartDelay : Constants.WORKER_START_DELAY;
+  }
+
   static getWorkerPoolMinSize(): number {
     return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'workerPoolMinSize') ? Configuration.getConfig().workerPoolMinSize : 4;
   }
index 1959ed935340ebf7424285fc682a5213ffa03d05..6a1a7cfeaf05fe1bf80b959e34dbdbb8f16b508d 100644 (file)
@@ -31,6 +31,6 @@ export default class Constants {
 
   static readonly TRANSACTION_DEFAULT_TAGID = '00000000';
 
-  static readonly START_WORKER_DELAY = 500;
+  static readonly WORKER_START_DELAY = 500;
   static readonly WORKER_POOL_MAX_INACTIVE_TIME = 60000;
 }
index 9f16af737457cf5daa522a1d25859514a6b6b3b1..772bf1b47cc59d3a2593ea8d6dc483f7f9f73832 100644 (file)
@@ -1,7 +1,9 @@
+import Constants from '../utils/Constants';
 import { WorkerData } from '../types/Worker';
 
 export default abstract class WorkerAbstract {
-  protected workerScript: string;
+  protected readonly workerScript: string;
+  protected readonly workerStartDelay: number;
   public abstract size: number;
   public abstract maxElementsPerWorker: number;
 
@@ -9,9 +11,11 @@ export default abstract class WorkerAbstract {
    * `WorkerAbstract` constructor.
    *
    * @param {string} workerScript
+   * @param {number} workerStartDelay
    */
-  constructor(workerScript: string) {
+  constructor(workerScript: string, workerStartDelay: number = Constants.WORKER_START_DELAY) {
     this.workerScript = workerScript;
+    this.workerStartDelay = workerStartDelay;
   }
 
   public abstract start(): Promise<void>;
index a9aa56f09765912a3a4193bb8acc299654d1d3a2..cf22c0a8e865587166ec362431474c693f41e7c8 100644 (file)
@@ -1,6 +1,5 @@
 import { DynamicThreadPool, PoolOptions } from 'poolifier';
 
-import Constants from '../utils/Constants';
 import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
@@ -15,9 +14,10 @@ export default class WorkerDynamicPool<T> extends WorkerAbstract {
    * @param {string} workerScript
    * @param {number} min
    * @param {number} max
+   * @param {number} workerStartDelay
    */
-  constructor(workerScript: string, min: number, max: number,) {
-    super(workerScript);
+  constructor(workerScript: string, min: number, max: number, workerStartDelay?: number) {
+    super(workerScript, workerStartDelay);
     this.pool = DynamicPool.getInstance(min, max, this.workerScript);
   }
 
@@ -56,7 +56,7 @@ export default class WorkerDynamicPool<T> extends WorkerAbstract {
   public async addElement(elementData: T): Promise<void> {
     await this.pool.execute(elementData);
     // Start worker sequentially to optimize memory at startup
-    await Utils.sleep(Constants.START_WORKER_DELAY);
+    await Utils.sleep(this.workerStartDelay);
   }
 }
 
index 242121fbb289b64f54b45de0aa510146a96ccffc..34369e186b06c03c683b4a0ece10c7e898e864b2 100644 (file)
@@ -1,6 +1,6 @@
 import { WorkerOptions, WorkerProcessType } from '../types/Worker';
 
-import Utils from '../utils/Utils';
+import Constants from '../utils/Constants';
 import WorkerAbstract from './WorkerAbstract';
 import WorkerDynamicPool from './WorkerDynamicPool';
 import WorkerSet from './WorkerSet';
@@ -12,20 +12,19 @@ export default class WorkerFactory {
     if (!isMainThread) {
       throw new Error('Trying to get a worker implementation outside the main thread');
     }
-    if (Utils.isUndefined(options)) {
-      options = {} as WorkerOptions;
-    }
+    options = options ?? {} as WorkerOptions;
+    options.startDelay = options.startDelay ?? Constants.WORKER_START_DELAY;
     switch (workerProcessType) {
       case WorkerProcessType.WORKER_SET:
         options.elementsPerWorker = options.elementsPerWorker ?? 1;
-        return new WorkerSet<T>(workerScript, options.elementsPerWorker);
+        return new WorkerSet<T>(workerScript, options.elementsPerWorker, options.startDelay);
       case WorkerProcessType.STATIC_POOL:
         options.poolMaxSize = options.poolMaxSize ?? 16;
-        return new WorkerStaticPool<T>(workerScript, options.poolMaxSize);
+        return new WorkerStaticPool<T>(workerScript, options.poolMaxSize, options.startDelay);
       case WorkerProcessType.DYNAMIC_POOL:
         options.poolMinSize = options.poolMinSize ?? 4;
         options.poolMaxSize = options.poolMaxSize ?? 16;
-        return new WorkerDynamicPool<T>(workerScript, options.poolMinSize, options.poolMaxSize);
+        return new WorkerDynamicPool<T>(workerScript, options.poolMinSize, options.poolMaxSize, options.startDelay);
       default:
         return null;
     }
index bf8b70210cc289efd0db0e631b12cf72d7099e4a..0e6855f1887cf6f1d3563bf45b3a07b7e6d7f8b1 100644 (file)
@@ -1,6 +1,5 @@
 import { WorkerEvents, WorkerSetElement } from '../types/Worker';
 
-import Constants from '../utils/Constants';
 import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
@@ -14,9 +13,10 @@ export default class WorkerSet<T> extends WorkerAbstract {
    *
    * @param {string} workerScript
    * @param {number} maxElementsPerWorker
+   * @param {number} workerStartDelay
    */
-  constructor(workerScript: string, maxElementsPerWorker = 1) {
-    super(workerScript);
+  constructor(workerScript: string, maxElementsPerWorker = 1, workerStartDelay?: number) {
+    super(workerScript, workerStartDelay);
     this.workerSet = new Set<WorkerSetElement>();
     this.maxElementsPerWorker = maxElementsPerWorker;
   }
@@ -38,7 +38,7 @@ export default class WorkerSet<T> extends WorkerAbstract {
     if (this.getLastWorkerSetElement().numberOfWorkerElements >= this.maxElementsPerWorker) {
       this.startWorker();
       // Start worker sequentially to optimize memory at startup
-      await Utils.sleep(Constants.START_WORKER_DELAY);
+      await Utils.sleep(this.workerStartDelay);
     }
     this.getLastWorker().postMessage({ id: WorkerEvents.START_WORKER_ELEMENT, workerData: elementData });
     this.getLastWorkerSetElement().numberOfWorkerElements++;
@@ -52,7 +52,7 @@ export default class WorkerSet<T> extends WorkerAbstract {
   public async start(): Promise<void> {
     this.startWorker();
     // Start worker sequentially to optimize memory at startup
-    await Utils.sleep(Constants.START_WORKER_DELAY);
+    await Utils.sleep(this.workerStartDelay);
   }
 
   /**
index 6421762918cc1ce9986a277cb1e46e58a5e16ccc..c78768e01360a788f131029025433ee8590a5f9b 100644 (file)
@@ -1,6 +1,5 @@
 import { FixedThreadPool, PoolOptions } from 'poolifier';
 
-import Constants from '../utils/Constants';
 import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
@@ -14,9 +13,10 @@ export default class WorkerStaticPool<T> extends WorkerAbstract {
    *
    * @param {string} workerScript
    * @param {number} numberOfThreads
+   * @param {number} startWorkerDelay
    */
-  constructor(workerScript: string, numberOfThreads: number) {
-    super(workerScript);
+  constructor(workerScript: string, numberOfThreads: number, startWorkerDelay?: number) {
+    super(workerScript, startWorkerDelay);
     this.pool = StaticPool.getInstance(numberOfThreads, this.workerScript);
   }
 
@@ -54,7 +54,7 @@ export default class WorkerStaticPool<T> extends WorkerAbstract {
   public async addElement(elementData: T): Promise<void> {
     await this.pool.execute(elementData);
     // Start worker sequentially to optimize memory at startup
-    await Utils.sleep(Constants.START_WORKER_DELAY);
+    await Utils.sleep(this.workerStartDelay);
   }
 }