1
1
/* eslint-disable @typescript-eslint/no-empty-function */
2
+ import { BinaryToTextEncoding , createHash , Hash } from 'crypto' ;
3
+ import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus' ;
4
+ import { EnvironmentVariablesService } from '../EnvironmentVariablesService' ;
2
5
import { IdempotencyRecord } from './IdempotencyRecord' ;
3
6
import { PersistenceLayerInterface } from './PersistenceLayerInterface' ;
4
7
5
8
abstract class PersistenceLayer implements PersistenceLayerInterface {
6
- public constructor ( ) { }
7
- public configure ( _functionName : string = '' ) : void { }
8
- public async deleteRecord ( ) : Promise < void > { }
9
- public async getRecord ( ) : Promise < IdempotencyRecord > {
10
- return Promise . resolve ( { } as IdempotencyRecord ) ;
9
+
10
+ // envVarsService is always initialized in the constructor
11
+ private envVarsService ! : EnvironmentVariablesService ;
12
+
13
+ private expiresAfterSeconds : number ;
14
+
15
+ private functionName : string = '' ;
16
+
17
+ private hashDigest : BinaryToTextEncoding ;
18
+
19
+ private hashFunction : string ;
20
+
21
+ public constructor ( ) {
22
+ this . setEnvVarsService ( ) ;
23
+ this . expiresAfterSeconds = 60 * 60 ; //one hour is the default expiration
24
+ this . hashFunction = 'md5' ;
25
+ this . hashDigest = 'base64' ;
26
+
27
+ }
28
+ public configure ( functionName : string = '' ) : void {
29
+ this . functionName = this . getEnvVarsService ( ) . getLambdaFunctionName ( ) + '.' + functionName ;
30
+ }
31
+
32
+ /**
33
+ * Deletes a record from the persistence store for the persistence key generated from the data passed in.
34
+ *
35
+ * @param data - the data payload that will be hashed to create the hash portion of the idempotency key
36
+ */
37
+ public async deleteRecord ( data : unknown ) : Promise < void > {
38
+ const idempotencyRecord : IdempotencyRecord =
39
+ new IdempotencyRecord ( this . getHashedIdempotencyKey ( data ) ,
40
+ IdempotencyRecordStatus . EXPIRED ,
41
+ undefined ,
42
+ undefined ,
43
+ undefined ,
44
+ undefined
45
+ ) ;
46
+
47
+ this . _deleteRecord ( idempotencyRecord ) ;
48
+ }
49
+ /**
50
+ * Retrieves idempotency key for the provided data and fetches data for that key from the persistence store
51
+ *
52
+ * @param data - the data payload that will be hashed to create the hash portion of the idempotency key
53
+ */
54
+ public async getRecord ( data : unknown ) : Promise < IdempotencyRecord > {
55
+ const idempotencyKey : string = this . getHashedIdempotencyKey ( data ) ;
56
+
57
+ return this . _getRecord ( idempotencyKey ) ;
58
+ }
59
+
60
+ /**
61
+ * Saves a record indicating that the function's execution is currently in progress
62
+ *
63
+ * @param data - the data payload that will be hashed to create the hash portion of the idempotency key
64
+ */
65
+ public async saveInProgress ( data : unknown ) : Promise < void > {
66
+ const idempotencyRecord : IdempotencyRecord =
67
+ new IdempotencyRecord ( this . getHashedIdempotencyKey ( data ) ,
68
+ IdempotencyRecordStatus . INPROGRESS ,
69
+ this . getExpiryTimestamp ( ) ,
70
+ undefined ,
71
+ undefined ,
72
+ undefined
73
+ ) ;
74
+
75
+ return this . _putRecord ( idempotencyRecord ) ;
76
+ }
77
+
78
+ /**
79
+ * Saves a record of the function completing successfully. This will create a record with a COMPLETED status
80
+ * and will save the result of the completed function in the idempotency record.
81
+ *
82
+ * @param data - the data payload that will be hashed to create the hash portion of the idempotency key
83
+ * @param result - the result of the successfully completed function
84
+ */
85
+ public async saveSuccess ( data : unknown , result : Record < string , unknown > ) : Promise < void > {
86
+ const idempotencyRecord : IdempotencyRecord =
87
+ new IdempotencyRecord ( this . getHashedIdempotencyKey ( data ) ,
88
+ IdempotencyRecordStatus . COMPLETED ,
89
+ this . getExpiryTimestamp ( ) ,
90
+ undefined ,
91
+ result ,
92
+ undefined
93
+ ) ;
94
+
95
+ this . _updateRecord ( idempotencyRecord ) ;
11
96
}
12
- public async saveInProgress ( ) : Promise < void > { }
13
- public async saveSuccess ( ) : Promise < void > { }
14
97
15
98
protected abstract _deleteRecord ( record : IdempotencyRecord ) : Promise < void > ;
16
99
protected abstract _getRecord ( idempotencyKey : string ) : Promise < IdempotencyRecord > ;
17
100
protected abstract _putRecord ( record : IdempotencyRecord ) : Promise < void > ;
18
101
protected abstract _updateRecord ( record : IdempotencyRecord ) : Promise < void > ;
102
+
103
+ /**
104
+ * Generates a hash of the data and returns the digest of that hash
105
+ *
106
+ * @param data the data payload that will generate the hash
107
+ * @returns the digest of the generated hash
108
+ */
109
+ private generateHash ( data : string ) : string {
110
+ const hash : Hash = createHash ( this . hashFunction ) ;
111
+ hash . update ( data ) ;
112
+
113
+ return hash . digest ( this . hashDigest ) ;
114
+ }
115
+
116
+ /**
117
+ * Getter for `envVarsService`.
118
+ * Used internally during initialization.
119
+ */
120
+ private getEnvVarsService ( ) : EnvironmentVariablesService {
121
+ return this . envVarsService ;
122
+ }
123
+
124
+ /**
125
+ * Creates the expiry timestamp for the idempotency record
126
+ *
127
+ * @returns the expiry time for the record expressed as number of seconds past the UNIX epoch
128
+ */
129
+ private getExpiryTimestamp ( ) : number {
130
+ const currentTime : number = Date . now ( ) / 1000 ;
131
+
132
+ return currentTime + this . expiresAfterSeconds ;
133
+ }
134
+
135
+ /**
136
+ * Generates the idempotency key used to identify records in the persistence store.
137
+ *
138
+ * @param data the data payload that will be hashed to create the hash portion of the idempotency key
139
+ * @returns the idempotency key
140
+ */
141
+ private getHashedIdempotencyKey ( data : unknown ) : string {
142
+ if ( ! data ) {
143
+ console . warn ( 'No data found for idempotency key' ) ;
144
+ }
145
+
146
+ return this . functionName + '#' + this . generateHash ( JSON . stringify ( data ) ) ;
147
+ }
148
+
149
+ /**
150
+ * Setter and initializer for `envVarsService`.
151
+ * Used internally during initialization.
152
+ */
153
+ private setEnvVarsService ( ) : void {
154
+ this . envVarsService = new EnvironmentVariablesService ( ) ;
155
+ }
156
+
19
157
}
20
158
21
159
export {
22
- IdempotencyRecord ,
23
160
PersistenceLayer
24
161
} ;
0 commit comments