Skip to content

Commit 006d537

Browse files
Merge pull request #6 from pearlshare/master
refactoring and added custom logger
2 parents bcad516 + 6428185 commit 006d537

File tree

10 files changed

+573
-181
lines changed

10 files changed

+573
-181
lines changed

README.md

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
[![npm version](http://img.shields.io/npm/v/simple-redis-cache.svg)](https://npmjs.org/package/simple-redis-cache)
1+
[![npm version](http://img.shields.io/npm/v/simple-redis-cache.svg?style=flat-square)](https://npmjs.org/package/simple-redis-cache)
22
[![Build Status](https://travis-ci.org/pasupulaphani/simple-redis-cache.svg?branch=master)](https://travis-ci.org/pasupulaphani/simple-redis-cache)
33
[![Coverage Status](https://coveralls.io/repos/github/pasupulaphani/simple-redis-cache/badge.svg?branch=master)](https://coveralls.io/github/pasupulaphani/simple-redis-cache?branch=master)
4-
[![dependencies Status](https://david-dm.org/pasupulaphani/simple-redis-cache/status.svg)](https://david-dm.org/pasupulaphani/simple-redis-cache)
5-
[![Gratipay donate button](https://img.shields.io/badge/gratipay-donate-yellow.svg)](https://gratipay.com/simple-redis-store/)
4+
[![Dependency Status](https://www.versioneye.com/user/projects/583c520dd2d44d003fb603be/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/583c520dd2d44d003fb603be)
5+
[![Gratipay donate button](https://img.shields.io/badge/gratipay-donate-yellow.svg?style=flat-square)](https://gratipay.com/simple-redis-store/)
66

77
# simple-redis-cache
88
Redis cache ready to scale with node-pool support
@@ -13,7 +13,7 @@ Redis cache ready to scale with node-pool support
1313
1414
## Prerequisites
1515

16-
This module requires nodejs v4 or above as it has dependencies on constious es6 components such as Map, Set, Promise etc.
16+
This module requires nodejs v4 or above as it has dependencies on es6 components such as Map, Set, Promise etc.
1717

1818
## Featuring
1919
- Out of the box default configuration (but fully configurable)
@@ -31,17 +31,56 @@ This module requires nodejs v4 or above as it has dependencies on constious es6
3131

3232
npm install simple-redis-cache
3333

34-
var RedisCache = require("simple-redis-cache");
35-
var cache = new RedisCache();
34+
const RedisCache = require("simple-redis-cache");
35+
const cache = new RedisCache();
3636

3737
// set
3838
cache.set("key", "value");
3939

40+
#### API
41+
42+
- RedisCache([options])
43+
44+
#### `options` object properties
45+
46+
| Property | Default | Description |
47+
|-----------|-----------|-------------|
48+
| name | Random unique string | Name your pool |
49+
| redisOptions | ```{url: redis://127.0.0.1:6379}``` | opts from https://github.com/NodeRedis/node_redis#options-object-properties |
50+
| poolOptions | null | opts from https://github.com/coopernurse/node-pool#createpool |
51+
| logger | null | Inject your custom logger |
52+
4053
### Run tests
4154

4255
bash test.sh
43-
44-
45-
### Contributing
56+
57+
## Contribute
58+
59+
[Discover how you can contribute by heading on over to the `CONTRIBUTING.md` file.](https://github.com/pasupulaphani/simple-redis-cache/blob/master/CONTRIBUTING.md)
60+
61+
## Backers
62+
63+
### Maintainers
64+
65+
These amazing people are maintaining this project:
66+
67+
* [Phani](https://github.com/pasupulaphani)[view contributions](https://github.com/pasupulaphani/simple-redis-cache/commits?author=pasupulaphani)
68+
69+
### Sponsors
70+
71+
No sponsors yet! Will you be the first?
72+
73+
[![Patreon donate button](https://img.shields.io/badge/patreon-donate-yellow.svg)](http://patreon.com/phaninder "Donate to this project using Patreon")
74+
[![Gratipay donate button](https://img.shields.io/badge/gratipay-donate-yellow.svg)](https://gratipay.com/~pasupulaphani/ "Donate weekly to this project using Gratipay")
75+
[![Flattr donate button](https://img.shields.io/badge/flattr-donate-yellow.svg)](https://flattr.com/profile/pasupulaphani "Donate to this project using Flattr")
76+
<!-- [![PayPal donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://phaninder.com/paypal "Donate to this project using Paypal") -->
77+
<!-- [![Bitcoin donate button](https://img.shields.io/badge/bitcoin-donate-yellow.svg)](https://phaninder.com/bitcoin "Donate once-off to this project using Bitcoin") -->
78+
<!-- [![Wishlist browse button](https://img.shields.io/badge/wishlist-donate-yellow.svg)](https://phaninder.com/wishlist "Buy an item on our wishlist for us") -->
79+
80+
### Contributors
81+
82+
These amazing people have contributed code to this project:
83+
84+
* [Oliver Brooks](https://github.com/oliverbrooks)
4685

4786
Feel free to make changes. Please see the [Contributors' Guide](https://github.com/pasupulaphani/simple-redis-cache/blob/master/CONTRIBUTING.md) for more information on contributing to the documentation.

lib/logger.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = function (logger) {
2+
if (!logger) {
3+
logger = {};
4+
}
5+
6+
return Object.assign({
7+
log: function () {},
8+
info: function () {},
9+
warn: function () {},
10+
error: function () {}
11+
}, logger);
12+
};

lib/redis_cache.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ const RedisStore = require("./redis_store");
22

33
const debug = require("debug")("simpleRedisCache");
44

5-
var RedisCache = module.exports = function (name, redisOptions, poolOptions) {
6-
7-
this.name = name;
8-
this.redisOptions = redisOptions;
9-
this.poolOptions = poolOptions;
10-
this.store = new RedisStore(name, redisOptions, poolOptions);
5+
const RedisCache = module.exports = function (options) {
6+
7+
this.name = options.name || `redisCache-${Math.random().toString(36).substr(2, 10)}`;
8+
this.redisOptions = options.redisOptions;
9+
this.poolOptions = options.poolOptions;
10+
this.logger = require("./logger")(options.logger);
11+
this.store = new RedisStore({
12+
name: this.name,
13+
redisOptions: this.redisOptions,
14+
poolOptions: this.poolOptions,
15+
logger: this.logger
16+
});
1117
};
1218

1319
RedisCache.prototype.set = function (key, value, ttlInSeconds) {

lib/redis_pool.js

Lines changed: 95 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,151 @@
1+
"use strict";
2+
13
const genericPool = require("generic-pool");
4+
const retry = require("retry-as-promised");
25
const redis = require("./redis");
36

47
const debug = require("debug")("simpleRedisPool");
58

6-
var RedisPool = module.exports = function (name, redisOptions, poolOptions) {
9+
const create = function (redisOptions) {
10+
return new Promise((resolve, reject) => {
11+
const client = redis.createClient(redisOptions);
712

8-
this.name = name;
9-
this.redisOptions = redisOptions;
10-
this.poolOptions = poolOptions;
11-
this._redisDb = redisOptions.db || 0;
13+
client.on("error", err => reject(err));
14+
client.on("connect", () => resolve(client));
15+
});
16+
};
1217

13-
const factory = {
14-
create: () => {
15-
return new Promise((resolve, reject) => {
18+
const selectDB = function (client, db) {
19+
return new Promise((resolve, reject) => {
20+
client.select(db, function (err) {
21+
if (err) reject(err);
22+
debug("DB selected: ", db);
23+
resolve(client);
24+
});
25+
});
26+
};
1627

17-
const client = redis.createClient(redisOptions);
28+
const RedisPool = module.exports = function (options) {
1829

19-
if (["undefined", null, ""].indexOf(this._redisDb) !== -1) {
20-
debug("Selected Redis DB: ", this._redisDb);
21-
client.select(this._redisDb);
22-
}
30+
this.name = options.name || `redisPool-${Math.random().toString(36).substr(2, 10)}`;
31+
this.redisOptions = options.redisOptions;
32+
this.poolOptions = options.poolOptions;
33+
this.logger = require("./logger")(options.logger);
34+
35+
// for retry
36+
let createAttempts = 0;
37+
38+
const factory = {
39+
create: () => {
2340

24-
// Register the authentication password if needed.
25-
if (redisOptions.auth_pass) {
26-
client.auth(redisOptions.auth_pass);
41+
// this is due to the limitation of node-pool ATM
42+
// https://github.com/coopernurse/node-pool/issues/161#issuecomment-261109882
43+
return retry(function () {
44+
createAttempts++;
45+
if (createAttempts > 3) {
46+
const err = new Error("CONN_FAILED");
47+
debug("Max conn createAttempts reached: %s, resolving to error:", createAttempts, err);
48+
49+
// reset for next try
50+
createAttempts = 0;
51+
return Promise.resolve(err);
2752
}
2853

29-
client.on("error", err => reject(err));
30-
client.on("connect", () => resolve(client));
54+
return create(options.redisOptions);
55+
}, {
56+
max: 10,
57+
name: "factory.create",
58+
report: debug
3159
});
3260
},
3361
destroy: (client) => {
3462
return new Promise((resolve) => {
3563

3664
try {
3765
// Flush when closing.
38-
client.end(true);
39-
debug("Client conn closed. Available count : %s. Pool size: %s", this.pool.availableObjectsCount(), this.pool.getPoolSize());
40-
resolve();
66+
client.end(true, () => resolve());
67+
debug("Client conn closed. Available count : %s. Pool size: %s", this.availableObjectsCount(), this.getPoolSize());
68+
this.logger.log("Client conn closed. Available count : %s. Pool size: %s", this.availableObjectsCount(), this.getPoolSize());
4169
} catch (err) {
42-
throw new Error("error", "Error destroying redis client.");
70+
throw err;
4371
}
4472
});
4573
}
4674
};
4775

4876
// Now that the pool settings are ready create a pool instance.
49-
this.pool = genericPool.createPool(factory, poolOptions);
77+
this.pool = genericPool.createPool(factory, this.poolOptions);
5078

5179
this.pool.on("factoryCreateError", e => {
52-
debug("Errored connecting Redis", e);
80+
debug("Errored while connecting Redis", e);
81+
this.logger.error("Errored while connecting Redis", e);
5382
});
54-
5583
this.pool.on("factoryDestroyError", e => {
56-
debug("Errored destroying Redis conn", e);
84+
debug("Errored while destroying Redis conn", e);
85+
this.logger.error("Errored while destroying Redis conn", e);
5786
});
58-
59-
// test connectivity by acquiring a conn
60-
// this.pool.acquire()
61-
// .then(client => this.pool.release(client));
6287
};
6388

64-
// Acquire a database connection and use an optional priority.
65-
RedisPool.prototype.acquire = function (priority) {
66-
return this.pool.acquire(priority);
89+
RedisPool.prototype.sendCommand = function (commandName, commandArgs) {
90+
return this.pool.acquire()
91+
.then(conn =>
92+
conn.send_commandAsync(commandName, [].concat(commandArgs))
93+
.then(result => {
94+
this.pool.release(conn);
95+
return result;
96+
})
97+
.catch(err => {
98+
this.pool.release(conn);
99+
throw err;
100+
})
101+
);
67102
};
68103

69-
RedisPool.prototype.acquireDb = function (db, priority) {
104+
// Acquire a database connection and use an optional priority.
105+
RedisPool.prototype.acquire = function (priority, db) {
70106
return this.pool.acquire(priority)
71107
.then(client => {
72-
if (client._db_selected !== db) {
73-
client["_db_selected"] = db;
74-
client.select(db);
108+
109+
if (client instanceof Error) {
110+
debug("Couldn't acquire connection to %j", this.redisOptions);
111+
this.logger.error("Couldn't acquire connection to %j", this.redisOptions);
112+
throw client;
113+
}
114+
115+
if (db) {
116+
this.logger.info("select DB:", db);
117+
return selectDB(client, db);
118+
} else {
119+
return client;
75120
}
76-
debug("DB selected: ", client._db_selected);
77121
});
78122
};
79123

80124
// Release a database connection to the pool.
81125
RedisPool.prototype.release = function (client) {
126+
return this.pool.release(client);
127+
};
82128

83-
// Always reset the DB to the default. This prevents issues
84-
// if a user used the select command to change the DB.
85-
if (client._db_selected !== this._redisDb) {
86-
debug("Releasing client. Reset the DB to the given: ", this._redisDb);
87-
client.select(this._redisDb);
88-
}
89-
this.pool.release(client);
129+
RedisPool.prototype.destroy = function (client) {
130+
return this.pool.destroy(client);
90131
};
91132

92133
// Drains the connection pool and call the callback id provided.
93-
RedisPool.prototype.drain = (cb) => {
94-
this.pool.drain(() => {
95-
this.pool.destroyAllNow();
96-
if (cb) {
97-
cb();
98-
}
99-
});
134+
RedisPool.prototype.drain = function () {
135+
return this.pool.drain(() => this.pool.clear());
100136
};
101137

102138
// Returns factory.name for this pool
103139
RedisPool.prototype.getName = function () {
104140
return this.name;
105141
};
106142

107-
RedisPool.prototype.getRedisDB = function () {
108-
return this._redisDb;
143+
RedisPool.prototype.getRedisOptions = function () {
144+
return this.redisOptions;
145+
};
146+
147+
RedisPool.prototype.getPoolOptions = function () {
148+
return this.poolOptions;
109149
};
110150

111151
RedisPool.prototype.getPoolSize = function () {
@@ -124,8 +164,7 @@ RedisPool.prototype.status = function () {
124164
return {
125165
name: this.name,
126166
size: this.pool.size,
127-
db: this._redisDb,
128-
avail: this.pool.available,
167+
available: this.pool.available,
129168
waiting: this.pool.pending
130169
};
131170
};

0 commit comments

Comments
 (0)