c4a9f7483e30060047607bdbad5a97e15fb7c91c
[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, readFileSync, writeFileSync } 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 fd: number | null = null;
20
21 constructor(storageUri: string, logPrefix: string) {
22 super(storageUri, logPrefix);
23 this.dbName = this.storageUri.pathname;
24 }
25
26 public storePerformanceStatistics(performanceStatistics: Statistics): void {
27 this.checkPerformanceRecordsFile();
28 AsyncLock.acquire(AsyncLockType.performance)
29 .then(() => {
30 const fileData = readFileSync(this.dbName, 'utf8');
31 const performanceRecords: Statistics[] = fileData
32 ? (JSON.parse(fileData) as Statistics[])
33 : [];
34 performanceRecords.push(performanceStatistics);
35 writeFileSync(this.dbName, JSONStringifyWithMapSupport(performanceRecords, 2), 'utf8');
36 })
37 .catch((error) => {
38 handleFileException(
39 this.dbName,
40 FileType.PerformanceRecords,
41 error as NodeJS.ErrnoException,
42 this.logPrefix
43 );
44 })
45 .finally(() => {
46 AsyncLock.release(AsyncLockType.performance).catch(Constants.EMPTY_FUNCTION);
47 });
48 }
49
50 public open(): void {
51 try {
52 if (isNullOrUndefined(this?.fd)) {
53 if (!existsSync(dirname(this.dbName))) {
54 mkdirSync(dirname(this.dbName), { recursive: true });
55 }
56 this.fd = openSync(this.dbName, 'a+');
57 }
58 } catch (error) {
59 handleFileException(
60 this.dbName,
61 FileType.PerformanceRecords,
62 error as NodeJS.ErrnoException,
63 this.logPrefix
64 );
65 }
66 }
67
68 public close(): void {
69 try {
70 if (this?.fd) {
71 closeSync(this.fd);
72 this.fd = null;
73 }
74 } catch (error) {
75 handleFileException(
76 this.dbName,
77 FileType.PerformanceRecords,
78 error as NodeJS.ErrnoException,
79 this.logPrefix
80 );
81 }
82 }
83
84 private checkPerformanceRecordsFile(): void {
85 if (!this?.fd) {
86 throw new BaseError(
87 `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`
88 );
89 }
90 }
91 }