Silence linter some more
[e-mobility-charging-stations-simulator.git] / src / performance / storage / JSONFileStorage.ts
index 25ba236703f4b60393b963fa0f349b7c01ea9b9d..7e23365ef77212cab7cf9f8ef690d214edad9ef7 100644 (file)
@@ -5,6 +5,7 @@ import FileUtils from '../../utils/FileUtils';
 import Statistics from '../../types/Statistics';
 import { Storage } from './Storage';
 import fs from 'fs';
+import lockfile from 'proper-lockfile';
 
 export class JSONFileStorage extends Storage {
   private fd: number | null = null;
@@ -16,19 +17,33 @@ export class JSONFileStorage extends Storage {
 
   public storePerformanceStatistics(performanceStatistics: Statistics): void {
     this.checkPerformanceRecordsFile();
-    fs.readFile(this.dbName, 'utf-8', (error, data) => {
-      if (error) {
-        FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error);
-      } else {
-        const performanceRecords: Statistics[] = data ? JSON.parse(data) as Statistics[] : [];
-        performanceRecords.push(performanceStatistics);
-        fs.writeFile(this.dbName, JSON.stringify(performanceRecords, null, 2), 'utf-8', (err) => {
-          if (err) {
-            FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, err);
-          }
-        });
-      }
-    });
+    lockfile.lock(this.dbName, { stale: 5000, retries: 3 })
+      .then(async (release) => {
+        try {
+          const fileData = fs.readFileSync(this.dbName, 'utf8');
+          const performanceRecords: Statistics[] = fileData ? JSON.parse(fileData) as Statistics[] : [];
+          performanceRecords.push(performanceStatistics);
+          fs.writeFileSync(
+            this.dbName,
+            JSON.stringify(performanceRecords,
+              (key, value) => {
+                if (value instanceof Map) {
+                  return {
+                    dataType: 'Map',
+                    value: [...value]
+                  };
+                }
+                return value as Statistics;
+              },
+              2),
+            'utf8'
+          );
+        } catch (error) {
+          FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error as NodeJS.ErrnoException);
+        }
+        await release();
+      })
+      .catch(() => { /* This is intentional */ });
   }
 
   public open(): void {
@@ -37,7 +52,7 @@ export class JSONFileStorage extends Storage {
         this.fd = fs.openSync(this.dbName, 'a+');
       }
     } catch (error) {
-      FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error);
+      FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error as NodeJS.ErrnoException);
     }
   }
 
@@ -48,12 +63,12 @@ export class JSONFileStorage extends Storage {
         this.fd = null;
       }
     } catch (error) {
-      FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error);
+      FileUtils.handleFileException(this.logPrefix, Constants.PERFORMANCE_RECORDS_FILETYPE, this.dbName, error as NodeJS.ErrnoException);
     }
   }
 
   private checkPerformanceRecordsFile(): void {
-    if (!this.fd) {
+    if (!this?.fd) {
       throw new Error(`${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`);
     }
   }