ac-node
Version:
A common module for building Atlassian Connect add-ons
146 lines (130 loc) • 3.94 kB
JavaScript
var rsvp = require('rsvp');
var Promise = rsvp.Promise;
var redis = require('redis');
var redisScan = require('redisscan');
var urls = require('url');
function RedisStore(redisUrlOrClient, scope) {
if (!(this instanceof RedisStore)) {
return new RedisStore(redisUrlOrClient, scope);
}
if (redisUrlOrClient) {
if (typeof redisUrlOrClient === 'object') {
this._client = redisUrlOrClient;
} else {
this._client = createClient(redisUrlOrClient);
}
} else {
this._client = createClient('redis://localhost:6379');
}
this._scope = scope;
};
RedisStore.prototype._get = function (key) {
var self = this;
return new Promise(function (resolve, reject) {
self._client.get(key, function (err, value) {
if (err) return reject(err);
value = JSON.parse(value);
resolve(value);
});
});
};
RedisStore.prototype.get = function (key) {
return this._get(this._key(key));
};
RedisStore.prototype._set = function (key, value, expiresIn) {
var self = this;
var args = [key, JSON.stringify(value)];
if (expiresIn) {
args.push('EX', expiresIn);
}
return new Promise(function (resolve, reject) {
self._client.set.apply(self._client, args.concat(function (err) {
if (err) return reject(err);
resolve();
}));
});
};
RedisStore.prototype.set = function (key, value, expiresIn) {
return this._set(this._key(key), value, expiresIn);
};
RedisStore.prototype._del = function (key) {
var self = this;
return new Promise(function (resolve, reject) {
self._client.del(key, function (err) {
if (err) return reject(err);
resolve();
});
});
};
RedisStore.prototype.del = function (key) {
return this._del(this._key(key));
};
RedisStore.prototype._all = function (scope, limit, offset) {
var self = this;
scope = scope || '';
var prefix = scope + (scope ? ':' : '');
limit = limit >>> 0;
offset = offset >>> 0;
var args = [offset, 'match', prefix + '*'];
if (limit) {
args.push('count', limit);
}
return new Promise(function (resolve, reject) {
self._client.scan.apply(self._client, args.concat([function (err, results) {
if (err) return reject(err);
var page = {};
var keys = results[1];
if (keys && keys.length > 0) {
self._client.mget.apply(self._client, keys.concat([function (err, values) {
if (err) return reject(err);
values.forEach(function (value, i) {
page[keys[i].slice(prefix.length)] = JSON.parse(values[i]);
});
resolve(page);
}]));
return;
}
resolve(page);
}]));
});
};
RedisStore.prototype.all = function (limit, offset) {
return this._all(this._scope, limit, offset);
};
RedisStore.prototype.narrow = function (subscope) {
return new RedisStore(this._client, this._key(subscope));
};
RedisStore.prototype.clear = function () {
var self = this;
return new Promise(function (resolve, reject) {
var pattern = (self._scope ? self._scope + ':' : '') + '*';
redisScan({
redis: self._client,
pattern: pattern,
// _unknown is an arg not defined in the docs and unclear from the scan lib code
each_callback: function (type, key, subkey, _unknown, value, next) {
self._del(key).then(next, next);
},
done_callback: function (err) {
if (err) return reject(err);
resolve();
}
});
});
};
RedisStore.prototype._key = function (key) {
return this._scope ? this._scope + ':' + key : key;
}
RedisStore.create = function (config, scope) {
var url = config.REDIS_ENV && process.env[config.REDIS_ENV];
return RedisStore(url, scope);
};
function createClient(redisUrl) {
var parsed = urls.parse(redisUrl);
var client = redis.createClient(parsed.port, parsed.hostname);
if (parsed.auth) {
client.auth(parsed.auth.split(':')[1]);
}
return client;
}
module.exports = RedisStore;