X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fperformance%2Fstorage%2FJsonFileStorage.ts;h=97ab104ccfb73a11fb52aafd8ca408eeaf1ff84f;hb=551f2b6e68f544b559243a2634c8b52a15bcdeec;hp=8465290325173d316a24e6ef26f1d6a252675ad1;hpb=8a36b1eb6df21e7ff434b36333d26739edf0e146;p=e-mobility-charging-stations-simulator.git diff --git a/src/performance/storage/JsonFileStorage.ts b/src/performance/storage/JsonFileStorage.ts index 84652903..97ab104c 100644 --- a/src/performance/storage/JsonFileStorage.ts +++ b/src/performance/storage/JsonFileStorage.ts @@ -1,90 +1,82 @@ -// Copyright Jerome Benoit. 2021. All Rights Reserved. +// Copyright Jerome Benoit. 2021-2024. All Rights Reserved. -import fs from 'fs'; +import { closeSync, existsSync, mkdirSync, openSync, writeSync } from 'node:fs' +import { dirname } from 'node:path' -import lockfile from 'proper-lockfile'; - -import { FileType } from '../../types/FileType'; -import type { Statistics } from '../../types/Statistics'; -import FileUtils from '../../utils/FileUtils'; -import Utils from '../../utils/Utils'; -import { Storage } from './Storage'; +import { BaseError } from '../../exception/index.js' +import { FileType, MapStringifyFormat, type Statistics } from '../../types/index.js' +import { AsyncLock, AsyncLockType, handleFileException, JSONStringify } from '../../utils/index.js' +import { Storage } from './Storage.js' export class JsonFileStorage extends Storage { - private fd: number | null = null; + private fd?: number - constructor(storageUri: string, logPrefix: string) { - super(storageUri, logPrefix); - this.dbName = this.storageUri.pathname; + constructor (storageUri: string, logPrefix: string) { + super(storageUri, logPrefix) + this.dbName = this.storageUri.pathname } - public storePerformanceStatistics(performanceStatistics: Statistics): void { - this.checkPerformanceRecordsFile(); - lockfile - .lock(this.dbName, { stale: 5000, retries: 3 }) - .then(async (release) => { - try { - const fileData = fs.readFileSync(this.dbName, 'utf8'); - const performanceRecords: Statistics[] = fileData - ? (JSON.parse(fileData) as Statistics[]) - : []; - performanceRecords.push(performanceStatistics); - fs.writeFileSync( - this.dbName, - Utils.JSONStringifyWithMapSupport(performanceRecords, 2), - 'utf8' - ); - } catch (error) { - FileUtils.handleFileException( - this.logPrefix, - FileType.PerformanceRecords, - this.dbName, - error as NodeJS.ErrnoException - ); - } - await release(); - }) - .catch(() => { - /* This is intentional */ - }); + public storePerformanceStatistics (performanceStatistics: Statistics): void { + this.setPerformanceStatistics(performanceStatistics) + this.checkPerformanceRecordsFile() + AsyncLock.runExclusive(AsyncLockType.performance, () => { + writeSync( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.fd!, + JSONStringify([...this.getPerformanceStatistics()], 2, MapStringifyFormat.object), + 0, + 'utf8' + ) + }).catch((error: unknown) => { + handleFileException( + this.dbName, + FileType.PerformanceRecords, + error as NodeJS.ErrnoException, + this.logPrefix + ) + }) } - public open(): void { + public open (): void { try { - if (!this?.fd) { - this.fd = fs.openSync(this.dbName, 'a+'); + if (this.fd == null) { + if (!existsSync(dirname(this.dbName))) { + mkdirSync(dirname(this.dbName), { recursive: true }) + } + this.fd = openSync(this.dbName, 'w') } } catch (error) { - FileUtils.handleFileException( - this.logPrefix, - FileType.PerformanceRecords, + handleFileException( this.dbName, - error as NodeJS.ErrnoException - ); + FileType.PerformanceRecords, + error as NodeJS.ErrnoException, + this.logPrefix + ) } } - public close(): void { + public close (): void { + this.clearPerformanceStatistics() try { - if (this?.fd) { - fs.closeSync(this.fd); - this.fd = null; + if (this.fd != null) { + closeSync(this.fd) + delete this.fd } } catch (error) { - FileUtils.handleFileException( - this.logPrefix, - FileType.PerformanceRecords, + handleFileException( this.dbName, - error as NodeJS.ErrnoException - ); + FileType.PerformanceRecords, + error as NodeJS.ErrnoException, + this.logPrefix + ) } } - private checkPerformanceRecordsFile(): void { - if (!this?.fd) { - throw new Error( + private checkPerformanceRecordsFile (): void { + if (this.fd == null) { + throw new BaseError( `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found` - ); + ) } } }