<commit_before>var assert = require('assert'),
    crypto = require('crypto'),
    util = require('util');

var TOKEN_TIMEOUT = 90;



/**
 * Constructor
 *
 * @param options {Object} Options must contain ``redis``, a redis client instance
 */
var Sessions = function(options) {
    options = options || {};
    assert.ok(options.redis, 'options.redis required | redis client instance');

    this.redis = options.redis;
    this.log = options.log;
};

module.exports = {
    Sessions: Sessions,
    createSessions: function(options) {
        return new Sessions(options);
    }
};



/**
 * Retrieve data associated with an auth token
 *
 * @param id {String} auth token identifier
 * @param cb {Function} callback in the form of fn(err, data) -> void
 */
Sessions.prototype.get = function(id, cb) {
    var self = this;
    this.log.debug('session.get %s', id);

    var k = _sessionKey(id);
    this.redis.get(k, function(err, data) {
        self.log.debug('session.get cb', err, data);
        if (err) {
            self.log.error(err);
            cb(err);
        } else {
            if (null === data) {
                cb(null, null);
            } else {
                cb(null, JSON.parse(data));
            }
        }
    });
};

/**
 * Extends a Session's expiry by TOKEN_TIMEOUT given a session id
 *
 * @param id {String} session id
 * @param data {Object} data to set
 * @param cb {Function} callback in form of fn(err);
 */
Sessions.prototype.touch = function(id, cb) {
    var self = this;
    this.log.debug('touch %s', id);

    var k = _sessionKey(id);
    this.redis.expire(k, TOKEN_TIMEOUT, function(err, v) {
        if (err) {
            self.log.error(err);
            if (typeof(cb) === 'function') {
                cb(err);
            }
        } else {
            if (typeof(cb) === 'function') {
                cb(null);
            }
        }
    });
};

/**
 * Extends a Session's expiry by TOKEN_TIMEOUT given a session id
 *
 * @param id {String} session id
 * @param data {Object} data to set
 * @param cb {Function} callback in form of fn(err);
 */
Sessions.prototype.setData = function(id, data, cb) {
    var self = this;
    this.log.debug('touch %s', id);

    var k = _sessionKey(id);
    this.redis.set(k, JSON.stringify(data), function(err, v) {
        if (err) {
            self.log.error(err);
            (typeof(cb) === 'function') && cb(err);
        } else {
            (typeof(cb) === 'function') && cb(null);
        }
    });
};

/**
 * Creates a new Session given data to store with that token
 *
 * @param data Object, data to store with the token
 * @param callback Function callback in form of fn(err, token, data)
 */
Sessions.prototype.create = function(data, callback) {
    var log = this.log;
    var redis = this.redis;

    var seed = crypto.randomBytes(20);
    var token = crypto.createHash('sha1').update(seed).digest('hex');

    log.debug('create %s', token);
    var k = _sessionKey(token);

    redis.multi()
    .set(k, JSON.stringify(data))
    .expire(k, TOKEN_TIMEOUT)
    .exec(function(err) {
        if (err) {
            callback(err);
        } else {
            callback(null, token, data);
        }
    });
}

function _sessionKey(k) {
    return util.format('session:%s', k);
}<commit_msg>ADMINUI-1599 gracefully handle no connection to redis<commit_after>var assert = require('assert'),
    crypto = require('crypto'),
    util = require('util');

var TOKEN_TIMEOUT = 90;



/**
 * Constructor
 *
 * @param options {Object} Options must contain ``redis``, a redis client instance
 */
var Sessions = function(options) {
    options = options || {};
    assert.ok(options.redis, 'options.redis required | redis client instance');

    this.redis = options.redis;
    this.log = options.log;
};

module.exports = {
    Sessions: Sessions,
    createSessions: function(options) {
        return new Sessions(options);
    }
};



/**
 * Retrieve data associated with an auth token
 *
 * @param id {String} auth token identifier
 * @param cb {Function} callback in the form of fn(err, data) -> void
 */
Sessions.prototype.get = function(id, cb) {
    var self = this;
    if (false === this.redis.connected) {
        return cb(new Error('No Connection to redis'));
    }
    this.log.debug('session.get %s', id);

    var k = _sessionKey(id);
    this.redis.get(k, function(err, data) {
        self.log.debug('session.get cb', err, data);
        if (err) {
            self.log.error(err);
            cb(err);
        } else {
            if (null === data) {
                cb(null, null);
            } else {
                cb(null, JSON.parse(data));
            }
        }
    });
};

/**
 * Extends a Session's expiry by TOKEN_TIMEOUT given a session id
 *
 * @param id {String} session id
 * @param data {Object} data to set
 * @param cb {Function} callback in form of fn(err);
 */
Sessions.prototype.touch = function(id, cb) {
    var self = this;
    this.log.debug('touch %s', id);

    if (false === this.redis.connected) {
        return cb('No Connection to redis');
    }
    var k = _sessionKey(id);
    this.redis.expire(k, TOKEN_TIMEOUT, function(err, v) {
        if (err) {
            self.log.error(err);
            if (typeof(cb) === 'function') {
                cb(err);
            }
        } else {
            if (typeof(cb) === 'function') {
                cb(null);
            }
        }
    });
};

/**
 * Extends a Session's expiry by TOKEN_TIMEOUT given a session id
 *
 * @param id {String} session id
 * @param data {Object} data to set
 * @param cb {Function} callback in form of fn(err);
 */
Sessions.prototype.setData = function(id, data, cb) {
    var self = this;
    this.log.debug('touch %s', id);

    var k = _sessionKey(id);
    if (false === this.redis.connected) {
        return cb(new Error('No Connection to redis'));
    }
    this.redis.set(k, JSON.stringify(data), function(err, v) {
        if (err) {
            self.log.error(err);
            (typeof(cb) === 'function') && cb(err);
        } else {
            (typeof(cb) === 'function') && cb(null);
        }
    });
};

/**
 * Creates a new Session given data to store with that token
 *
 * @param data Object, data to store with the token
 * @param callback Function callback in form of fn(err, token, data)
 */
Sessions.prototype.create = function(data, callback) {
    var log = this.log;
    var redis = this.redis;

    if (false === this.redis.connected) {
        return callback(new Error('No Connection to redis'));
    }

    var seed = crypto.randomBytes(20);
    var token = crypto.createHash('sha1').update(seed).digest('hex');

    log.debug('create %s', token);
    var k = _sessionKey(token);

    redis.multi()
        .set(k, JSON.stringify(data))
        .expire(k, TOKEN_TIMEOUT)
        .exec(function(err) {
            if (err) {
                callback(err);
            } else {
                callback(null, token, data);
            }
        });
}

function _sessionKey(k) {
    return util.format('session:%s', k);
}
{'fraction_non_alphanumeric': 0.14898132427843802, 'fraction_numerical': 0.0019807583474816073, 'mean_word_length': 2.251609935602576, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1405049', 'n_tokens_mistral': 2264, 'n_tokens_neox': 2205, 'n_words': 607}