1
1
'use strict'
2
2
// Import Packages
3
3
const nconf = require ( 'nconf' )
4
- const winston = require ( 'winston' )
5
- const colors = require ( 'colors' )
6
-
7
4
const Redis = require ( 'ioredis' )
8
5
9
- let connectionFailedAttemp = 0
10
- class cache {
6
+ const { handleError , ConnectionConfig } = require ( './utils/cache' )
7
+ class Cache {
11
8
static connect ( newConnection = false ) {
12
9
// Get Config
13
- const config = {
14
- host : nconf . get ( 'redis:host' ) || '127.0.0.1' ,
15
- port : nconf . get ( 'redis:port' ) || 6379 ,
16
- db : nconf . get ( 'redis:database' ) || 0 ,
17
- family : nconf . get ( 'redis:family' ) || 4 ,
18
- reconnectOnError : ( err ) => {
19
- const targetError = 'READONLY'
20
- if ( err . message . includes ( targetError ) ) {
21
- // Only reconnect when the error contains "READONLY"
22
- return true
23
- }
24
- } ,
25
- }
26
10
if ( nconf . get ( 'redis:password' ) && nconf . get ( 'redis:password' ) !== '' ) {
27
- config . password = nconf . get ( 'redis:password' )
11
+ ConnectionConfig . password = nconf . get ( 'redis:password' )
28
12
}
29
13
// Connect Redis
30
14
if ( ! newConnection ) {
31
- this . redis = new Redis ( config )
32
- this . redis . on ( 'connect' , ( ) => {
33
- connectionFailedAttemp = 0 // clear the attemp count
34
- } )
35
- this . redis . on ( 'error' , ( err ) => {
36
- console . log ( colors . red ( err . stack ) )
37
- if ( connectionFailedAttemp >= 3 ) {
38
- winston . error (
39
- '[cache] attemp to connect to redis ' +
40
- connectionFailedAttemp +
41
- ' times, but all failed, process exiting.' ,
42
- )
43
- process . exit ( 1 )
44
- }
45
- winston . error (
46
- '[cache] failed to connect to redis, we will attemp again...' ,
47
- )
48
- connectionFailedAttemp ++
49
- cache . connect ( )
50
- } )
15
+ this . redis = new Redis ( ConnectionConfig )
16
+ this . redis . on ( 'connect' , ( ) => nconf . set ( 'connectionFailedAttemp' , 0 ) )
17
+ this . redis . on ( 'error' , handleError . bind ( this ) )
51
18
return true
52
19
}
53
- const client = new Redis ( config )
54
- return client
20
+ return new Redis ( ConnectionConfig )
55
21
}
56
22
57
- static connectOrSkip ( ) {
58
- if ( this . redis ) {
59
- return true
60
- } else {
61
- return this . connect ( )
23
+ static connectOrSkip ( isABSwitcher ) {
24
+ if ( isABSwitcher ) {
25
+ return
62
26
}
27
+ return this . redis ? true : this . connect ( )
63
28
}
64
29
65
30
static command ( commands , ...params ) {
66
- this . connectOrSkip ( )
67
- return this . redis [ commands ] ( ... params )
31
+ params [ 0 ] = 'cache:' + params [ 0 ]
32
+ return this . redis [ commands ] ( params )
68
33
}
69
34
70
35
static set ( key , v , time ) {
71
- this . connectOrSkip ( )
36
+ this . connectOrSkip ( this . isABSwitcher )
72
37
const value = typeof v === 'object' ? JSON . stringify ( v ) : v
73
38
if ( time ) {
74
39
return this . redis . set ( 'cache:' + key , value , 'EX' , time )
@@ -78,7 +43,7 @@ class cache {
78
43
}
79
44
80
45
static async get ( key , toJson = true ) {
81
- this . connectOrSkip ( )
46
+ this . connectOrSkip ( this . isABSwitcher )
82
47
const data = await this . redis . get ( 'cache:' + key )
83
48
if ( toJson ) {
84
49
try {
@@ -92,7 +57,16 @@ class cache {
92
57
}
93
58
}
94
59
60
+ /**
61
+ * Call Caller and store, or return cached Caller Data
62
+ * @param {string } key
63
+ * @param {number } time
64
+ * @param {number } caller the callerFunc
65
+ * @param {any[] } callerParams the callerFunc params
66
+ * @param {boolean } toJSON
67
+ */
95
68
static async remeber ( key , time , ...params ) {
69
+ this . connectOrSkip ( this . isABSwitcher )
96
70
if ( params . length <= 0 || params . length > 3 ) {
97
71
throw new Error ( 'the length of params is wrong' )
98
72
}
@@ -102,20 +76,22 @@ class cache {
102
76
const caller = params [ 0 ]
103
77
const callerParams = params [ 1 ] ?? [ ]
104
78
const toJSON = params [ 2 ] ?? true
105
- let data = await this . get ( key , toJSON )
106
- if ( ! data ) {
107
- // data is empty
108
- data = await caller ( ...callerParams )
109
- if ( data ) {
110
- this . set ( key , data , time ) // async set
111
- }
112
- }
113
- return data
79
+ return (
80
+ ( await this . get ( key , toJSON ) ) ||
81
+ ( await callAndStore ( caller , callerParams , key , time ) )
82
+ )
114
83
}
115
84
116
85
static getClient ( newConnection = false ) {
117
86
return newConnection ? this . connect ( true ) : this . redis
118
87
}
119
88
}
120
89
121
- module . exports = cache
90
+ const callAndStore = async ( caller , params , key , time ) => {
91
+ const data = await caller ( ...params )
92
+ if ( data ) {
93
+ Cache . set ( key , data , time )
94
+ }
95
+ }
96
+
97
+ module . exports = Cache
0 commit comments