@@ -15,6 +15,7 @@ import { ScanOptions, ScanCommonOptions } from '../commands/SCAN';
15
15
import { RedisLegacyClient , RedisLegacyClientType } from './legacy-mode' ;
16
16
import { RedisPoolOptions , RedisClientPool } from './pool' ;
17
17
import { RedisVariadicArgument , parseArgs , pushVariadicArguments } from '../commands/generic-transformers' ;
18
+ import { BasicClientSideCache , ClientSideCacheConfig , ClientSideCacheProvider } from './cache' ;
18
19
import { BasicCommandParser , CommandParser } from './parser' ;
19
20
20
21
export interface RedisClientOptions <
@@ -72,6 +73,10 @@ export interface RedisClientOptions<
72
73
* TODO
73
74
*/
74
75
commandOptions ?: CommandOptions < TYPE_MAPPING > ;
76
+ /**
77
+ * TODO
78
+ */
79
+ clientSideCache ?: ClientSideCacheProvider | ClientSideCacheConfig ;
75
80
}
76
81
77
82
type WithCommands <
@@ -280,10 +285,12 @@ export default class RedisClient<
280
285
#monitorCallback?: MonitorCallback < TYPE_MAPPING > ;
281
286
private _self = this ;
282
287
private _commandOptions ?: CommandOptions < TYPE_MAPPING > ;
288
+
283
289
#dirtyWatch?: string ;
284
- #epoch: number ;
285
290
#watchEpoch?: number ;
286
291
292
+ #clientSideCache?: ClientSideCacheProvider ;
293
+
287
294
get options ( ) : RedisClientOptions < M , F , S , RESP > | undefined {
288
295
return this . _self . #options;
289
296
}
@@ -300,6 +307,11 @@ export default class RedisClient<
300
307
return this . _self . #queue. isPubSubActive ;
301
308
}
302
309
310
+ get socketEpoch ( ) {
311
+ return this . _self . #socket. socketEpoch ;
312
+ }
313
+
314
+
303
315
get isWatching ( ) {
304
316
return this . _self . #watchEpoch !== undefined ;
305
317
}
@@ -310,10 +322,20 @@ export default class RedisClient<
310
322
311
323
constructor ( options ?: RedisClientOptions < M , F , S , RESP , TYPE_MAPPING > ) {
312
324
super ( ) ;
325
+
313
326
this . #options = this . #initiateOptions( options ) ;
314
327
this . #queue = this . #initiateQueue( ) ;
315
328
this . #socket = this . #initiateSocket( ) ;
316
- this . #epoch = 0 ;
329
+
330
+ if ( options ?. clientSideCache ) {
331
+ if ( options . clientSideCache instanceof ClientSideCacheProvider ) {
332
+ this . #clientSideCache = options . clientSideCache ;
333
+ } else {
334
+ const cscConfig = options . clientSideCache ;
335
+ this . #clientSideCache = new BasicClientSideCache ( cscConfig ) ;
336
+ }
337
+ this . #queue. setInvalidateCallback ( this . #clientSideCache. invalidate . bind ( this . #clientSideCache) ) ;
338
+ }
317
339
}
318
340
319
341
#initiateOptions( options ?: RedisClientOptions < M , F , S , RESP , TYPE_MAPPING > ) : RedisClientOptions < M , F , S , RESP , TYPE_MAPPING > | undefined {
@@ -347,7 +369,6 @@ export default class RedisClient<
347
369
348
370
#handshake( selectedDB : number ) {
349
371
const commands = [ ] ;
350
-
351
372
if ( this . #options?. RESP ) {
352
373
const hello : HelloOptions = { } ;
353
374
@@ -392,6 +413,13 @@ export default class RedisClient<
392
413
) ;
393
414
}
394
415
416
+ if ( this . #clientSideCache) {
417
+ const tracking = this . #clientSideCache. trackingOn ( ) ;
418
+ if ( tracking ) {
419
+ commands . push ( tracking ) ;
420
+ }
421
+ }
422
+
395
423
return commands ;
396
424
}
397
425
@@ -445,6 +473,7 @@ export default class RedisClient<
445
473
} )
446
474
. on ( 'error' , err => {
447
475
this . emit ( 'error' , err ) ;
476
+ this . #clientSideCache?. onError ( ) ;
448
477
if ( this . #socket. isOpen && ! this . #options?. disableOfflineQueue ) {
449
478
this . #queue. flushWaitingForReply ( err ) ;
450
479
} else {
@@ -453,7 +482,6 @@ export default class RedisClient<
453
482
} )
454
483
. on ( 'connect' , ( ) => this . emit ( 'connect' ) )
455
484
. on ( 'ready' , ( ) => {
456
- this . #epoch++ ;
457
485
this . emit ( 'ready' ) ;
458
486
this . #setPingTimer( ) ;
459
487
this . #maybeScheduleWrite( ) ;
@@ -581,13 +609,21 @@ export default class RedisClient<
581
609
commandOptions : CommandOptions < TYPE_MAPPING > | undefined ,
582
610
transformReply : TransformReply | undefined ,
583
611
) {
584
- const reply = await this . sendCommand ( parser . redisArgs , commandOptions ) ;
612
+ const csc = this . _self . #clientSideCache;
613
+ const defaultTypeMapping = this . _self . #options?. commandOptions === commandOptions ;
585
614
586
- if ( transformReply ) {
587
- return transformReply ( reply , parser . preserve , commandOptions ?. typeMapping ) ;
588
- }
615
+ const fn = ( ) => { return this . sendCommand ( parser . redisArgs , commandOptions ) } ;
616
+
617
+ if ( csc && command . CACHEABLE && defaultTypeMapping ) {
618
+ return await csc . handleCache ( this . _self , parser as BasicCommandParser , fn , transformReply , commandOptions ?. typeMapping ) ;
619
+ } else {
620
+ const reply = await fn ( ) ;
589
621
590
- return reply ;
622
+ if ( transformReply ) {
623
+ return transformReply ( reply , parser . preserve , commandOptions ?. typeMapping ) ;
624
+ }
625
+ return reply ;
626
+ }
591
627
}
592
628
593
629
/**
@@ -752,7 +788,7 @@ export default class RedisClient<
752
788
const reply = await this . _self . sendCommand (
753
789
pushVariadicArguments ( [ 'WATCH' ] , key )
754
790
) ;
755
- this . _self . #watchEpoch ??= this . _self . #epoch ;
791
+ this . _self . #watchEpoch ??= this . _self . socketEpoch ;
756
792
return reply as unknown as ReplyWithTypeMapping < SimpleStringReply < 'OK' > , TYPE_MAPPING > ;
757
793
}
758
794
@@ -819,7 +855,7 @@ export default class RedisClient<
819
855
}
820
856
821
857
const chainId = Symbol ( 'Pipeline Chain' ) ,
822
- promise = Promise . all (
858
+ promise = Promise . allSettled (
823
859
commands . map ( ( { args } ) => this . _self . #queue. addCommand ( args , {
824
860
chainId,
825
861
typeMapping : this . _commandOptions ?. typeMapping
@@ -855,7 +891,7 @@ export default class RedisClient<
855
891
throw new WatchError ( dirtyWatch ) ;
856
892
}
857
893
858
- if ( watchEpoch && watchEpoch !== this . _self . #epoch ) {
894
+ if ( watchEpoch && watchEpoch !== this . _self . socketEpoch ) {
859
895
throw new WatchError ( 'Client reconnected after WATCH' ) ;
860
896
}
861
897
@@ -1075,6 +1111,7 @@ export default class RedisClient<
1075
1111
return new Promise < void > ( resolve => {
1076
1112
clearTimeout ( this . _self . #pingTimer) ;
1077
1113
this . _self . #socket. close ( ) ;
1114
+ this . _self . #clientSideCache?. onClose ( ) ;
1078
1115
1079
1116
if ( this . _self . #queue. isEmpty ( ) ) {
1080
1117
this . _self . #socket. destroySocket ( ) ;
@@ -1099,6 +1136,7 @@ export default class RedisClient<
1099
1136
clearTimeout ( this . _self . #pingTimer) ;
1100
1137
this . _self . #queue. flushAll ( new DisconnectsClientError ( ) ) ;
1101
1138
this . _self . #socket. destroy ( ) ;
1139
+ this . _self . #clientSideCache?. onClose ( ) ;
1102
1140
}
1103
1141
1104
1142
ref ( ) {
0 commit comments