build: switch to NodeNext module resolution
[e-mobility-charging-stations-simulator.git] / src / performance / storage / JsonFileStorage.ts
CommitLineData
edd13439 1// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
c27c3eee 2
f1c729e0 3import { closeSync, existsSync, mkdirSync, openSync, writeSync } from 'node:fs';
d972af76 4import { dirname } from 'node:path';
8114d10e 5
a6ef1ece
JB
6import { Storage } from './Storage.js';
7import { BaseError } from '../../exception/index.js';
8import { FileType, type Statistics } from '../../types/index.js';
9bf0ef23
JB
9import {
10 AsyncLock,
11 AsyncLockType,
9bf0ef23
JB
12 JSONStringifyWithMapSupport,
13 handleFileException,
14 isNullOrUndefined,
a6ef1ece 15} from '../../utils/index.js';
72f041bd 16
100a5301 17export class JsonFileStorage extends Storage {
3f073436 18 private static performanceRecords: Map<string, Statistics>;
f1c729e0
JB
19
20 private fd?: number;
2a370053 21
1f5df42a
JB
22 constructor(storageUri: string, logPrefix: string) {
23 super(storageUri, logPrefix);
24 this.dbName = this.storageUri.pathname;
72f041bd
JB
25 }
26
27 public storePerformanceStatistics(performanceStatistics: Statistics): void {
2a370053 28 this.checkPerformanceRecordsFile();
061ff2b0 29 JsonFileStorage.performanceRecords.set(performanceStatistics.id, performanceStatistics);
0ebf7c2e 30 AsyncLock.runExclusive(AsyncLockType.performance, () => {
0ebf7c2e
JB
31 writeSync(
32 this.fd!,
33 JSONStringifyWithMapSupport([...JsonFileStorage.performanceRecords.values()], 2),
34 0,
35 'utf8',
36 );
37 }).catch((error) => {
38 handleFileException(
39 this.dbName,
40 FileType.PerformanceRecords,
41 error as NodeJS.ErrnoException,
42 this.logPrefix,
43 );
44 });
72f041bd 45 }
b652b0c3 46
2a370053 47 public open(): void {
3f073436 48 JsonFileStorage.performanceRecords = new Map<string, Statistics>();
b652b0c3 49 try {
9bf0ef23 50 if (isNullOrUndefined(this?.fd)) {
d972af76
JB
51 if (!existsSync(dirname(this.dbName))) {
52 mkdirSync(dirname(this.dbName), { recursive: true });
f682b2dc 53 }
0ebf7c2e 54 this.fd = openSync(this.dbName, 'w');
a6ceb16a 55 }
b652b0c3 56 } catch (error) {
fa5995d6 57 handleFileException(
e7aeea18 58 this.dbName,
7164966d
JB
59 FileType.PerformanceRecords,
60 error as NodeJS.ErrnoException,
5edd8ba0 61 this.logPrefix,
e7aeea18 62 );
2a370053
JB
63 }
64 }
65
66 public close(): void {
3f073436 67 JsonFileStorage.performanceRecords.clear();
2a370053 68 try {
a6ceb16a 69 if (this?.fd) {
d972af76 70 closeSync(this.fd);
f1c729e0 71 delete this?.fd;
2a370053
JB
72 }
73 } catch (error) {
fa5995d6 74 handleFileException(
e7aeea18 75 this.dbName,
7164966d
JB
76 FileType.PerformanceRecords,
77 error as NodeJS.ErrnoException,
5edd8ba0 78 this.logPrefix,
e7aeea18 79 );
2a370053
JB
80 }
81 }
82
83 private checkPerformanceRecordsFile(): void {
73d09045 84 if (!this?.fd) {
7b5dbe91 85 throw new BaseError(
5edd8ba0 86 `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`,
e7aeea18 87 );
b652b0c3
JB
88 }
89 }
72f041bd 90}