fix: fix performance records duplication
[e-mobility-charging-stations-simulator.git] / src / performance / storage / JsonFileStorage.ts
1 // Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
2
3 import { closeSync, existsSync, mkdirSync, openSync, writeSync } from 'node:fs';
4 import { dirname } from 'node:path';
5
6 import { Storage } from './Storage';
7 import { BaseError } from '../../exception';
8 import { FileType, type Statistics } from '../../types';
9 import {
10 AsyncLock,
11 AsyncLockType,
12 Constants,
13 JSONStringifyWithMapSupport,
14 handleFileException,
15 isNullOrUndefined,
16 } from '../../utils';
17
18 export class JsonFileStorage extends Storage {
19 private static readonly performanceRecords: Map<string, Statistics> = new Map<
20 string,
21 Statistics
22 >();
23
24 private fd?: number;
25
26 constructor(storageUri: string, logPrefix: string) {
27 super(storageUri, logPrefix);
28 this.dbName = this.storageUri.pathname;
29 }
30
31 public storePerformanceStatistics(performanceStatistics: Statistics): void {
32 this.checkPerformanceRecordsFile();
33 AsyncLock.acquire(AsyncLockType.performance)
34 .then(() => {
35 JsonFileStorage.performanceRecords.set(performanceStatistics.id, performanceStatistics);
36 writeSync(
37 this.fd!,
38 JSONStringifyWithMapSupport([...JsonFileStorage.performanceRecords.values()], 2),
39 0,
40 'utf8',
41 );
42 })
43 .catch((error) => {
44 handleFileException(
45 this.dbName,
46 FileType.PerformanceRecords,
47 error as NodeJS.ErrnoException,
48 this.logPrefix,
49 );
50 })
51 .finally(() => {
52 AsyncLock.release(AsyncLockType.performance).catch(Constants.EMPTY_FUNCTION);
53 });
54 }
55
56 public open(): void {
57 try {
58 if (isNullOrUndefined(this?.fd)) {
59 if (!existsSync(dirname(this.dbName))) {
60 mkdirSync(dirname(this.dbName), { recursive: true });
61 }
62 this.fd = openSync(this.dbName, 'w+');
63 }
64 } catch (error) {
65 handleFileException(
66 this.dbName,
67 FileType.PerformanceRecords,
68 error as NodeJS.ErrnoException,
69 this.logPrefix,
70 );
71 }
72 }
73
74 public close(): void {
75 try {
76 if (this?.fd) {
77 closeSync(this.fd);
78 delete this?.fd;
79 }
80 } catch (error) {
81 handleFileException(
82 this.dbName,
83 FileType.PerformanceRecords,
84 error as NodeJS.ErrnoException,
85 this.logPrefix,
86 );
87 }
88 }
89
90 private checkPerformanceRecordsFile(): void {
91 if (!this?.fd) {
92 throw new BaseError(
93 `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`,
94 );
95 }
96 }
97 }