Use eslint extension for import sorting instead of unmaintained external ones
[e-mobility-charging-stations-simulator.git] / src / performance / storage / JsonFileStorage.ts
CommitLineData
c27c3eee
JB
1// Copyright Jerome Benoit. 2021. All Rights Reserved.
2
8114d10e
JB
3import fs from 'fs';
4
5import lockfile from 'proper-lockfile';
6
a95873d8 7import { FileType } from '../../types/FileType';
72f041bd 8import Statistics from '../../types/Statistics';
8114d10e 9import FileUtils from '../../utils/FileUtils';
72f041bd 10import { Storage } from './Storage';
72f041bd 11
100a5301 12export class JsonFileStorage extends Storage {
2a370053
JB
13 private fd: number | null = null;
14
1f5df42a
JB
15 constructor(storageUri: string, logPrefix: string) {
16 super(storageUri, logPrefix);
17 this.dbName = this.storageUri.pathname;
72f041bd
JB
18 }
19
20 public storePerformanceStatistics(performanceStatistics: Statistics): void {
2a370053 21 this.checkPerformanceRecordsFile();
e7aeea18
JB
22 lockfile
23 .lock(this.dbName, { stale: 5000, retries: 3 })
c63c21bc
JB
24 .then(async (release) => {
25 try {
26 const fileData = fs.readFileSync(this.dbName, 'utf8');
e7aeea18
JB
27 const performanceRecords: Statistics[] = fileData
28 ? (JSON.parse(fileData) as Statistics[])
29 : [];
c63c21bc 30 performanceRecords.push(performanceStatistics);
1830ad42
JB
31 fs.writeFileSync(
32 this.dbName,
e7aeea18
JB
33 JSON.stringify(
34 performanceRecords,
ff4b895e
JB
35 (key, value) => {
36 if (value instanceof Map) {
37 return {
38 dataType: 'Map',
e7aeea18 39 value: [...value],
ff4b895e
JB
40 };
41 }
42 return value as Statistics;
43 },
e7aeea18
JB
44 2
45 ),
1830ad42
JB
46 'utf8'
47 );
c63c21bc 48 } catch (error) {
e7aeea18
JB
49 FileUtils.handleFileException(
50 this.logPrefix,
a95873d8 51 FileType.PerformanceRecords,
e7aeea18
JB
52 this.dbName,
53 error as NodeJS.ErrnoException
54 );
c63c21bc
JB
55 }
56 await release();
57 })
e7aeea18
JB
58 .catch(() => {
59 /* This is intentional */
60 });
72f041bd 61 }
b652b0c3 62
2a370053 63 public open(): void {
b652b0c3 64 try {
a6ceb16a
JB
65 if (!this?.fd) {
66 this.fd = fs.openSync(this.dbName, 'a+');
67 }
b652b0c3 68 } catch (error) {
e7aeea18
JB
69 FileUtils.handleFileException(
70 this.logPrefix,
a95873d8 71 FileType.PerformanceRecords,
e7aeea18
JB
72 this.dbName,
73 error as NodeJS.ErrnoException
74 );
2a370053
JB
75 }
76 }
77
78 public close(): void {
79 try {
a6ceb16a 80 if (this?.fd) {
2a370053
JB
81 fs.closeSync(this.fd);
82 this.fd = null;
83 }
84 } catch (error) {
e7aeea18
JB
85 FileUtils.handleFileException(
86 this.logPrefix,
a95873d8 87 FileType.PerformanceRecords,
e7aeea18
JB
88 this.dbName,
89 error as NodeJS.ErrnoException
90 );
2a370053
JB
91 }
92 }
93
94 private checkPerformanceRecordsFile(): void {
73d09045 95 if (!this?.fd) {
e7aeea18
JB
96 throw new Error(
97 `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`
98 );
b652b0c3
JB
99 }
100 }
72f041bd 101}