hastebin/lib/document_stores/redis.js

171 lines
4.6 KiB
JavaScript

var redis = require('redis');
var winston = require('winston');
// For storing in redis or KeyDB (Redis API compatible)
// options[type] = redis
// options[host] - The host to connect to (default localhost)
// options[port] - The port to connect to (default 6379)
// options[db] - The db to use (default 0)
// options[password] - The password to use (if any)
// options[expire] - The time to live for each key set (default never)
// options[connectionTimeout] - Connection timeout in ms (default 5000)
var RedisDocumentStore = function(options, client) {
this.expire = options.expire;
if (client) {
winston.info('using predefined redis client');
RedisDocumentStore.client = client;
// Check if we need to promisify the client (for redis-url 0.1.0)
if (!RedisDocumentStore.client.connect && !RedisDocumentStore.isLegacyClient) {
winston.info('using legacy redis client from redis-url');
RedisDocumentStore.isLegacyClient = true;
}
} else if (!RedisDocumentStore.client) {
winston.info('configuring redis/keydb client');
RedisDocumentStore.connect(options);
}
};
// Create a connection according to config
RedisDocumentStore.connect = async function(options) {
var host = options.host || '127.0.0.1';
var port = options.port || 6379;
var index = options.db || 0;
var connectionTimeout = options.connectionTimeout || 5000;
const redisOptions = {
socket: {
host: host,
port: port,
connectTimeout: connectionTimeout
},
database: index
};
// Add password if provided
if (options.password) {
redisOptions.password = options.password;
}
// Add URL if provided (overrides other options)
if (options.url) {
delete redisOptions.socket;
delete redisOptions.database;
redisOptions.url = options.url;
}
try {
RedisDocumentStore.client = redis.createClient(redisOptions);
// Set up error handling
RedisDocumentStore.client.on('error', (err) => {
winston.error('Redis/KeyDB error', { error: err });
});
// Connect the client
await RedisDocumentStore.client.connect();
winston.info('connected to redis/keydb on ' + host + ':' + port + '/' + index);
}
catch (err) {
winston.error('error connecting to redis/keydb', { error: err });
process.exit(1);
}
};
// Save file in a key
RedisDocumentStore.prototype.set = async function(key, data, callback, skipExpire) {
var _this = this;
try {
// Handle legacy client (redis-url 0.1.0)
if (RedisDocumentStore.isLegacyClient) {
RedisDocumentStore.client.set(key, data, function(err) {
if (err) {
winston.error('error setting key', { error: err });
callback(false);
return;
}
if (!skipExpire) {
_this.setExpiration(key);
}
callback(true);
});
return;
}
// Modern redis 4.x client
await RedisDocumentStore.client.set(key, data);
if (!skipExpire) {
_this.setExpiration(key);
}
callback(true);
}
catch (err) {
winston.error('error setting key', { error: err });
callback(false);
}
};
// Expire a key in expire time if set
RedisDocumentStore.prototype.setExpiration = async function(key) {
if (this.expire) {
try {
if (RedisDocumentStore.isLegacyClient) {
RedisDocumentStore.client.expire(key, this.expire, function(err) {
if (err) {
winston.error('failed to set expiry on key: ' + key, { error: err });
}
});
return;
}
await RedisDocumentStore.client.expire(key, this.expire);
}
catch (err) {
winston.error('failed to set expiry on key: ' + key, { error: err });
}
}
};
// Get a file from a key
RedisDocumentStore.prototype.get = async function(key, callback, skipExpire) {
var _this = this;
try {
// Handle legacy client (redis-url 0.1.0)
if (RedisDocumentStore.isLegacyClient) {
RedisDocumentStore.client.get(key, function(err, reply) {
if (err) {
winston.error('error getting key', { error: err });
callback(false);
return;
}
if (reply && !skipExpire) {
_this.setExpiration(key);
}
callback(reply);
});
return;
}
// Modern redis 4.x client
const reply = await RedisDocumentStore.client.get(key);
if (reply && !skipExpire) {
_this.setExpiration(key);
}
callback(reply);
}
catch (err) {
winston.error('error getting key', { error: err });
callback(false);
}
};
module.exports = RedisDocumentStore;