Skip to content

Commit 142194f

Browse files
committedAug 20, 2020
refactor: cache
1 parent 1db57be commit 142194f

File tree

3 files changed

+80
-126
lines changed

3 files changed

+80
-126
lines changed
 

‎src/cache.js

+36-60
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,39 @@
11
'use strict'
22
// Import Packages
33
const nconf = require('nconf')
4-
const winston = require('winston')
5-
const colors = require('colors')
6-
74
const Redis = require('ioredis')
85

9-
let connectionFailedAttemp = 0
10-
class cache {
6+
const { handleError, ConnectionConfig } = require('./utils/cache')
7+
class Cache {
118
static connect(newConnection = false) {
129
// 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-
}
2610
if (nconf.get('redis:password') && nconf.get('redis:password') !== '') {
27-
config.password = nconf.get('redis:password')
11+
ConnectionConfig.password = nconf.get('redis:password')
2812
}
2913
// Connect Redis
3014
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))
5118
return true
5219
}
53-
const client = new Redis(config)
54-
return client
20+
return new Redis(ConnectionConfig)
5521
}
5622

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
6226
}
27+
return this.redis ? true : this.connect()
6328
}
6429

6530
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)
6833
}
6934

7035
static set(key, v, time) {
71-
this.connectOrSkip()
36+
this.connectOrSkip(this.isABSwitcher)
7237
const value = typeof v === 'object' ? JSON.stringify(v) : v
7338
if (time) {
7439
return this.redis.set('cache:' + key, value, 'EX', time)
@@ -78,7 +43,7 @@ class cache {
7843
}
7944

8045
static async get(key, toJson = true) {
81-
this.connectOrSkip()
46+
this.connectOrSkip(this.isABSwitcher)
8247
const data = await this.redis.get('cache:' + key)
8348
if (toJson) {
8449
try {
@@ -92,7 +57,16 @@ class cache {
9257
}
9358
}
9459

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+
*/
9568
static async remeber(key, time, ...params) {
69+
this.connectOrSkip(this.isABSwitcher)
9670
if (params.length <= 0 || params.length > 3) {
9771
throw new Error('the length of params is wrong')
9872
}
@@ -102,20 +76,22 @@ class cache {
10276
const caller = params[0]
10377
const callerParams = params[1] ?? []
10478
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+
)
11483
}
11584

11685
static getClient(newConnection = false) {
11786
return newConnection ? this.connect(true) : this.redis
11887
}
11988
}
12089

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

‎src/extensions/sentencesABSwitcher.js

+5-66
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,23 @@
44

55
const Cache = require('../cache')
66
const nconf = require('nconf')
7-
const colors = require('colors/safe')
8-
const winston = require('winston')
97
const Redis = require('ioredis')
10-
11-
let connectionFailedAttemp = 0
128
const databaseA = nconf.get('sentences_ab_switchter:a') || 1
139
const databaseB = nconf.get('sentences_ab_switchter:b') || 2
1410

11+
const { ConnectionConfig, handleError } = require('../utils/cache')
1512
class SentencesABSwitcher extends Cache {
1613
static connect(target = 'a', isDefault = false) {
1714
// Get Config
18-
const config = {
19-
host: nconf.get('redis:host') || '127.0.0.1',
20-
port: nconf.get('redis:port') || 6379,
21-
db: target === 'a' ? databaseA : databaseB, // default connect to A database,
22-
family: nconf.get('redis:family') || 4,
23-
reconnectOnError: (err) => {
24-
const targetError = 'READONLY'
25-
if (err.message.includes(targetError)) {
26-
// Only reconnect when the error contains "READONLY"
27-
return true
28-
}
29-
},
30-
}
15+
const config = { ...ConnectionConfig }
16+
config.db = target === 'a' ? databaseA : databaseB
3117
if (nconf.get('redis:password') && nconf.get('redis:password') !== '') {
3218
config.password = nconf.get('redis:password')
3319
}
3420
// Connect Redis
3521
const tmp = new Redis(config)
36-
tmp.on('connect', () => {
37-
connectionFailedAttemp = 0 // clear the attemp count
38-
})
39-
tmp.on('error', (err) => {
40-
winston.error(colors.red(err.stack))
41-
if (connectionFailedAttemp >= 3) {
42-
winston.error(
43-
'[AB] attemp to connect to redis ' +
44-
connectionFailedAttemp +
45-
' times, but all failed, process exiting.',
46-
)
47-
process.exit(1)
48-
}
49-
winston.error('[AB] failed to connect to redis, we will attemp again...')
50-
connectionFailedAttemp++
51-
SentencesABSwitcher.connect()
52-
})
22+
tmp.on('connect', () => nconf.set('connectionFailedAttemp', 0))
23+
tmp.on('error', handleError.bind(this))
5324
if (isDefault) {
5425
this.redis = tmp // set defalt slot
5526
}
@@ -73,38 +44,6 @@ class SentencesABSwitcher extends Cache {
7344
}
7445
}
7546

76-
static command(commands, params) {
77-
this.connectOrSkip()
78-
const param = params
79-
param[0] = 'cache:' + param[0]
80-
return this.redis[commands](param)
81-
}
82-
83-
static set(key, v, time) {
84-
this.connectOrSkip()
85-
const value = typeof v === 'object' ? JSON.stringify(v) : v
86-
if (time) {
87-
return this.redis.set('cache:' + key, value, 'EX', time)
88-
} else {
89-
return this.redis.set('cache:' + key, value)
90-
}
91-
}
92-
93-
static async get(key, toJson = true) {
94-
this.connectOrSkip()
95-
const data = await this.redis.get('cache:' + key)
96-
if (toJson) {
97-
try {
98-
const json = JSON.parse(data)
99-
return json
100-
} catch (e) {
101-
return data
102-
}
103-
} else {
104-
return data
105-
}
106-
}
107-
10847
static getConnection(target) {
10948
if (target === 'a') {
11049
return new WrapperRedis(this.redisA)

‎src/utils/cache.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const winston = require('winston')
2+
const nconf = require('nconf')
3+
const chalk = require('chalk')
4+
5+
let connectionFailedAttemp = nconf.get('connectionFailedAttemp')
6+
7+
const reconnect = (err) => {
8+
const targetError = 'READONLY'
9+
if (err.message.includes(targetError)) {
10+
// Only reconnect when the error contains "READONLY"
11+
return true
12+
}
13+
}
14+
15+
const ConnectionConfig = {
16+
host: nconf.get('redis:host') || '127.0.0.1',
17+
port: nconf.get('redis:port') || 6379,
18+
db: nconf.get('redis:database') || 0,
19+
family: nconf.get('redis:family') || 4,
20+
reconnectOnError: reconnect,
21+
}
22+
23+
const handleError = (err) => {
24+
winston.error(chalk.red(err.stack))
25+
if (connectionFailedAttemp >= 3) {
26+
winston.error(
27+
'[cache] attemp to connect to redis ' +
28+
connectionFailedAttemp +
29+
' times, but all failed, process exiting.',
30+
)
31+
process.exit(1)
32+
}
33+
winston.error('[cache] failed to connect to redis, we will attemp again...')
34+
connectionFailedAttemp++
35+
nconf.set('connectionFailedAttemp', connectionFailedAttemp)
36+
this.connect()
37+
}
38+
39+
module.exports = exports = { handleError, ConnectionConfig, reconnect }

0 commit comments

Comments
 (0)
Please sign in to comment.