f44d9f2b35adc56ca0d9d503e927ccfac6eae760
[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.js'
7 import { BaseError } from '../../exception/index.js'
8 import { FileType, type Statistics } from '../../types/index.js'
9 import {
10 AsyncLock,
11 AsyncLockType,
12 JSONStringifyWithMapSupport,
13 handleFileException
14 } from '../../utils/index.js'
15
16 export class JsonFileStorage extends Storage {
17 private static performanceRecords: Map<string, Statistics>
18
19 private fd?: number
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 JsonFileStorage.performanceRecords.set(performanceStatistics.id, performanceStatistics)
29 AsyncLock.runExclusive(AsyncLockType.performance, () => {
30 writeSync(
31 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
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 })
45 }
46
47 public open (): void {
48 JsonFileStorage.performanceRecords = new Map<string, Statistics>()
49 try {
50 if (this.fd == null) {
51 if (!existsSync(dirname(this.dbName))) {
52 mkdirSync(dirname(this.dbName), { recursive: true })
53 }
54 this.fd = openSync(this.dbName, 'w')
55 }
56 } catch (error) {
57 handleFileException(
58 this.dbName,
59 FileType.PerformanceRecords,
60 error as NodeJS.ErrnoException,
61 this.logPrefix
62 )
63 }
64 }
65
66 public close (): void {
67 JsonFileStorage.performanceRecords.clear()
68 try {
69 if (this.fd != null) {
70 closeSync(this.fd)
71 delete this.fd
72 }
73 } catch (error) {
74 handleFileException(
75 this.dbName,
76 FileType.PerformanceRecords,
77 error as NodeJS.ErrnoException,
78 this.logPrefix
79 )
80 }
81 }
82
83 private checkPerformanceRecordsFile (): void {
84 if (this.fd == null) {
85 throw new BaseError(
86 `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`
87 )
88 }
89 }
90 }