Skip to content

Commit e14750c

Browse files
committed
Add GC limit for expired clients per cycle
If the set of clients is really large, the ZRANGEBYSCORE Redis command can overwhelm the process by taking too much time and too much memory. Setting the `gc_limit` option will now set the LIMIT parameter on that command, allowing the GC cycle to finish within a reasonable amount of time. Also adds some logging.
1 parent 3d219ac commit e14750c

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

faye-redis.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ multiRedis.COMMANDS.forEach(function(command) {
159159
// number of seconds. To completely disable GC, set this
160160
// to `false`.
161161
//
162+
// gc_limit By default, the GC tries to prune all expired
163+
// clients. This can be set to an integer, however, to
164+
// limit the number of expired clients to process in a
165+
// given GC cycle. Highly recommended.
166+
//
162167
var Engine = function(server, options) {
163168
this._options = options || {};
164169

@@ -181,6 +186,7 @@ var Engine = function(server, options) {
181186
}
182187

183188
if (gc) {
189+
this._gc_limit = this._options.gc_limit;
184190
this._gc = setInterval(function() { self.gc() }, gc * 1000);
185191
}
186192
};
@@ -350,23 +356,36 @@ Engine.prototype = {
350356
if (typeof timeout !== 'number') return;
351357

352358
this._redis.urls.forEach(function(url) {
359+
console.log("[" + url + "] Running GC");
353360
var connection = this._redis.connections[url];
354361

355362
this._withLock(connection, 'gc', function(releaseLock) {
356363
var cutoff = new Date().getTime() - 1000 * 2 * timeout,
357-
self = this;
364+
self = this,
365+
args;
358366

359-
connection.zrangebyscore(this._ns + '/clients', 0, cutoff, function(error, clients) {
367+
var pruneClientsCallback = function pruneClientsCallback(error, clients) {
360368
var i = 0, n = clients.length;
361369
if (i === n) return releaseLock();
362370

363371
clients.forEach(function(clientId) {
364372
this.destroyClient(clientId, function() {
365373
i += 1;
366-
if (i === n) releaseLock();
374+
if (i === n) {
375+
console.log("[" + url + "] Destroyed " + n + " expired clients");
376+
releaseLock();
377+
}
367378
}, this);
368379
}, self);
369-
});
380+
};
381+
382+
if (this._gc_limit) {
383+
args = [this._ns + "/clients", 0, cutoff, "LIMIT", 0, this._gc_limit, pruneClientsCallback];
384+
} else {
385+
args = [this._ns + "/clients", 0, cutoff, pruneClientsCallback];
386+
}
387+
388+
connection.zrangebyscore.apply(connection, args);
370389
}, this);
371390
}, this);
372391
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
, "author" : "James Coglan <jcoglan@gmail.com> (http://jcoglan.com/)"
55
, "keywords" : ["pubsub", "bayeux"]
66

7-
, "version" : "0.1.6"
7+
, "version" : "0.1.7"
88
, "engines" : {"node": ">=0.4.0"}
99
, "main" : "./faye-redis"
1010
, "dependencies" : {"hiredis": "", "redis": "", "consistent-hashing": ""}

0 commit comments

Comments
 (0)