@@ -16,17 +16,19 @@ class QueryCache {
16
16
new LocalCacheDriver ( ) ;
17
17
}
18
18
19
- cachedQueryResult ( queryBody , preAggregationsTablesToTempTables ) {
20
- const replacePreAggregationTableNames = ( queryAndParams ) =>
21
- QueryCache . replacePreAggregationTableNames ( queryAndParams , preAggregationsTablesToTempTables ) ;
19
+ async cachedQueryResult ( queryBody , preAggregationsTablesToTempTables ) {
20
+ const replacePreAggregationTableNames = ( queryAndParams ) => QueryCache . replacePreAggregationTableNames (
21
+ queryAndParams , preAggregationsTablesToTempTables
22
+ ) ;
22
23
23
24
const query = replacePreAggregationTableNames ( queryBody . query ) ;
24
25
let queuePriority = 10 ;
25
26
if ( Number . isInteger ( queryBody . queuePriority ) ) {
27
+ // eslint-disable-next-line prefer-destructuring
26
28
queuePriority = queryBody . queuePriority ;
27
29
}
28
30
const forceNoCache = queryBody . forceNoCache || false ;
29
- const values = queryBody . values ;
31
+ const { values } = queryBody ;
30
32
const cacheKeyQueries =
31
33
(
32
34
queryBody . cacheKeyQueries && queryBody . cacheKeyQueries . queries ||
@@ -39,7 +41,7 @@ class QueryCache {
39
41
const expireSecs = queryBody . expireSecs || 24 * 3600 ;
40
42
41
43
if ( ! cacheKeyQueries ) {
42
- return this . queryWithRetryAndRelease ( query , values , queryBody . external ) ;
44
+ return { data : await this . queryWithRetryAndRelease ( query , values , queryBody . external ) } ;
43
45
}
44
46
const cacheKey = QueryCache . queryCacheKey ( queryBody ) ;
45
47
@@ -67,22 +69,25 @@ class QueryCache {
67
69
} ) ;
68
70
}
69
71
70
- return mainPromise ;
72
+ return {
73
+ data : await mainPromise ,
74
+ lastRefreshTime : await this . lastRefreshTime ( cacheKey )
75
+ } ;
71
76
}
72
77
73
78
static queryCacheKey ( queryBody ) {
74
79
return [ queryBody . query , queryBody . values , ( queryBody . preAggregations || [ ] ) . map ( p => p . loadSql ) ] ;
75
80
}
76
81
77
82
static replaceAll ( replaceThis , withThis , inThis ) {
78
- withThis = withThis . replace ( / \$ / g, "$$$$" ) ;
83
+ withThis = withThis . replace ( / \$ / g, "$$$$" ) ;
79
84
return inThis . replace (
80
- new RegExp ( replaceThis . replace ( / ( [ / , ! \\ ^ $ { } [ \] ( ) . * + ? | < > \- & ] ) / g, "\\$&" ) , "g" ) ,
85
+ new RegExp ( replaceThis . replace ( / ( [ / , ! \\ ^ $ { } [ \] ( ) . * + ? | < > \- & ] ) / g, "\\$&" ) , "g" ) ,
81
86
withThis
82
87
) ;
83
88
}
84
89
85
- static replacePreAggregationTableNames ( queryAndParams , preAggregationsTablesToTempTables ) {
90
+ static replacePreAggregationTableNames ( queryAndParams , preAggregationsTablesToTempTables ) {
86
91
const [ keyQuery , params ] = Array . isArray ( queryAndParams ) ? queryAndParams : [ queryAndParams , [ ] ] ;
87
92
const replacedKeqQuery = preAggregationsTablesToTempTables . reduce (
88
93
( query , [ tableName , tempTable ] ) => QueryCache . replaceAll ( tableName , tempTable , query ) ,
@@ -169,9 +174,9 @@ class QueryCache {
169
174
query , values , cacheKeyQueries , expireSecs , cacheKey , renewalThreshold , options
170
175
) . catch ( e => {
171
176
if ( ! ( e instanceof ContinueWaitError ) ) {
172
- this . logger ( 'Error while renew cycle' , { query, query_values : values , error : e . stack || e } )
177
+ this . logger ( 'Error while renew cycle' , { query, query_values : values , error : e . stack || e } ) ;
173
178
}
174
- } )
179
+ } ) ;
175
180
}
176
181
177
182
renewQuery ( query , values , cacheKeyQueries , expireSecs , cacheKey , renewalThreshold , options ) {
@@ -192,30 +197,34 @@ class QueryCache {
192
197
this . logger ( 'Error fetching cache key queries' , { error : e . stack || e } ) ;
193
198
return [ ] ;
194
199
} )
195
- . then ( cacheKeyQueryResults => {
196
- return this . cacheQueryResult (
197
- query , values ,
198
- cacheKey ,
199
- expireSecs ,
200
- {
201
- renewalThreshold : renewalThreshold || 6 * 60 * 60 ,
202
- renewalKey : cacheKeyQueryResults && [
203
- cacheKeyQueries , cacheKeyQueryResults , this . queryRedisKey ( [ query , values ] )
204
- ] ,
205
- waitForRenew : true ,
206
- external : options . external
207
- }
208
- ) ;
209
- } ) ;
200
+ . then ( async cacheKeyQueryResults => (
201
+ {
202
+ data : await this . cacheQueryResult (
203
+ query , values ,
204
+ cacheKey ,
205
+ expireSecs ,
206
+ {
207
+ renewalThreshold : renewalThreshold || 6 * 60 * 60 ,
208
+ renewalKey : cacheKeyQueryResults && [
209
+ cacheKeyQueries , cacheKeyQueryResults , this . queryRedisKey ( [ query , values ] )
210
+ ] ,
211
+ waitForRenew : true ,
212
+ external : options . external
213
+ }
214
+ ) ,
215
+ refreshKeyValues : cacheKeyQueryResults ,
216
+ lastRefreshTime : await this . lastRefreshTime ( cacheKey )
217
+ }
218
+ ) ) ;
210
219
}
211
220
212
221
cacheQueryResult ( query , values , cacheKey , expiration , options ) {
213
222
options = options || { } ;
214
- const renewalThreshold = options . renewalThreshold ;
223
+ const { renewalThreshold } = options ;
215
224
const renewalKey = options . renewalKey && this . queryRedisKey ( options . renewalKey ) ;
216
225
const redisKey = this . queryRedisKey ( cacheKey ) ;
217
- const fetchNew = ( ) => {
218
- return this . queryWithRetryAndRelease ( query , values , options . priority , cacheKey , options . external ) . then ( res => {
226
+ const fetchNew = ( ) => (
227
+ this . queryWithRetryAndRelease ( query , values , options . priority , cacheKey , options . external ) . then ( res => {
219
228
const result = {
220
229
time : ( new Date ( ) ) . getTime ( ) ,
221
230
result : res ,
@@ -224,17 +233,17 @@ class QueryCache {
224
233
return this . cacheDriver . set ( redisKey , result , expiration )
225
234
. then ( ( ) => {
226
235
this . logger ( 'Renewed' , { cacheKey } ) ;
227
- return res
236
+ return res ;
228
237
} ) ;
229
238
} ) . catch ( e => {
230
239
if ( ! ( e instanceof ContinueWaitError ) ) {
231
240
this . logger ( 'Dropping Cache' , { cacheKey, error : e . stack || e } ) ;
232
241
this . cacheDriver . remove ( redisKey )
233
- . catch ( e => this . logger ( 'Error removing key' , { cacheKey, error : e . stack || e } ) ) ;
242
+ . catch ( err => this . logger ( 'Error removing key' , { cacheKey, error : err . stack || err } ) ) ;
234
243
}
235
244
throw e ;
236
- } ) ;
237
- } ;
245
+ } )
246
+ ) ;
238
247
239
248
if ( options . forceNoCache ) {
240
249
this . logger ( 'Force no cache for' , { cacheKey } ) ;
@@ -268,7 +277,7 @@ class QueryCache {
268
277
this . logger ( 'Renewing existing key' , { cacheKey, renewalThreshold } ) ;
269
278
fetchNew ( ) . catch ( e => {
270
279
if ( ! ( e instanceof ContinueWaitError ) ) {
271
- this . logger ( 'Error renewing' , { cacheKey, error : e . stack || e } )
280
+ this . logger ( 'Error renewing' , { cacheKey, error : e . stack || e } ) ;
272
281
}
273
282
} ) ;
274
283
}
@@ -282,8 +291,13 @@ class QueryCache {
282
291
} ) ;
283
292
}
284
293
294
+ async lastRefreshTime ( cacheKey ) {
295
+ const cachedValue = await this . cacheDriver . get ( this . queryRedisKey ( cacheKey ) ) ;
296
+ return cachedValue && new Date ( cachedValue . time ) ;
297
+ }
298
+
285
299
queryRedisKey ( cacheKey ) {
286
- return `SQL_QUERY_RESULT_${ this . redisPrefix } _${ crypto . createHash ( 'md5' ) . update ( JSON . stringify ( cacheKey ) ) . digest ( "hex" ) } `
300
+ return `SQL_QUERY_RESULT_${ this . redisPrefix } _${ crypto . createHash ( 'md5' ) . update ( JSON . stringify ( cacheKey ) ) . digest ( "hex" ) } ` ;
287
301
}
288
302
}
289
303
0 commit comments