Commit | Line | Data |
---|---|---|
c27c3eee JB |
1 | // Copyright Jerome Benoit. 2021. All Rights Reserved. |
2 | ||
8114d10e JB |
3 | import fs from 'fs'; |
4 | ||
5 | import lockfile from 'proper-lockfile'; | |
6 | ||
a95873d8 | 7 | import { FileType } from '../../types/FileType'; |
72f041bd | 8 | import Statistics from '../../types/Statistics'; |
8114d10e | 9 | import FileUtils from '../../utils/FileUtils'; |
72f041bd | 10 | import { Storage } from './Storage'; |
72f041bd | 11 | |
100a5301 | 12 | export 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 | } |