UNPKG

qm

Version:

QMachine: A platform for World Wide Computing

241 lines (209 loc) 8.34 kB
//- JavaScript source code //- defs-redis.js ~~ // // The first step here was just to get things running with plain old arrays in // JavaScript, and I accomplished that. The next step is to jettison anything // that hinders performance, since it's downright sinful to choose a platform // like Node.js + Redis and then squander cycles needlessly ... // // ~~ (c) SRW, 23 Nov 2012 // ~~ last updated 28 Jan 2015 (function () { 'use strict'; // Pragmas /*jshint maxparams: 2, quotmark: single, strict: true */ /*jslint indent: 4, maxlen: 80, node: true */ /*properties api, auth, avar_ttl, body, ceil, collect_garbage, createClient, detect_buffers, enable_offline_queue, error, exec, exists, expire, forEach, get_avar, get_list, hget, hmset, hostname, isMaster, keys, length, log, multi, no_ready_check, on, parse, parser, persistent_storage, port, quit, redis, replace, return_buffers, sadd, set_avar, smembers, socket_nodelay, split, srem, status, stringify */ // Declarations var cluster, redis, url; // Definitions cluster = require('cluster'); redis = require('redis'); url = require('url'); // Out-of-scope definitions exports.api = function (settings) { // This function needs documentation. var collect_garbage, conn, db, exp_date, get_avar, get_list, set_avar; collect_garbage = function () { // This function needs documentation. var remaining, seek_and_destroy; seek_and_destroy = function (queue) { // This function needs documentation. var box = queue.replace(/^\$\:([\w\-]+)[&][\w\-]+/, '$1'); db.smembers(queue, function (err, response) { // This function needs documentation. if (err !== null) { console.error('Error:', err); return; } var callback, n; callback = function () { // This function needs documentation. n -= 1; if (n === 0) { remaining -= 1; if (remaining === 0) { console.log('Finished collecting garbage.'); } } return; }; n = response.length; response.forEach(function (key) { // This function needs documentation. db.exists(box + '&' + key, function (err, response) { // This function needs documentation. if (err !== null) { console.error('Error:', err); } if (response === 0) { db.srem(queue, key, function (err) { // This function accepts a second argument, // but I have omitted it because it irritates // JSLint et al. otherwise. if (err !== null) { console.error('Error:', err); } return callback(); }); } else { callback(); } return; }); return; }); if (n === 0) { callback(); } return; }); return; }; db.keys('$:*', function (err, queues) { // This function needs documentation. if (err !== null) { console.error('Error:', err); return; } remaining = queues.length; queues.forEach(seek_and_destroy); if (remaining === 0) { console.log('Finished collecting garbage.'); } return; }); return; }; conn = url.parse(settings.persistent_storage.redis); db = redis.createClient(conn.port, conn.hostname, { // For more information, see http://git.io/PRZ7Bw . detect_buffers: false, enable_offline_queue: true, no_ready_check: true, parser: 'hiredis', return_buffers: false, socket_nodelay: true }); exp_date = function () { // This function needs documentation. return Math.ceil(settings.avar_ttl); }; get_avar = function (params, callback) { // This function needs documentation. db.hget(params[0] + '&' + params[1], 'body', function (err, body) { // This function needs documentation. if (err === null) { // NOT A MISTAKE -- it means it was found. // Postpone eviction db.expire(params[0] + '&' + params[1], exp_date()); } return callback(err, body); }); return; }; get_list = function (params, callback) { // This function needs documentation. db.smembers('$:' + params[0] + '&' + params[1], function (err, x) { // This function needs documentation. var y = (x instanceof Array) ? JSON.stringify(x) : '[]'; return callback(err, y); }); return; }; set_avar = function (params, callback) { // This function needs documentation. var body, box, key, status; if (params.length === 4) { body = params[3]; status = params[2]; } else { body = params[2]; } box = params[0]; key = params[1]; db.hget(box + '&' + key, 'status', function (err, res) { // This function needs documentation. if (err !== null) { return callback(err, res); } var multi, set1, set2, updated; multi = db.multi(); updated = {body: body}; if (res !== null) { set1 = '$:' + box + '&' + res; multi.srem(set1, key); } if (status !== undefined) { updated.status = status; set2 = '$:' + box + '&' + updated.status; multi.sadd(set2, key); } multi.hmset(box + '&' + key, updated); multi.expire(box + '&' + key, exp_date()); multi.exec(callback); return; }); return; }; db.auth(conn.auth.split(':')[1]); db.on('connect', function () { // This function needs documentation. if (cluster.isMaster) { console.log('API: Redis storage is ready.'); } return; }); db.on('end', function () { // This function needs documentation. console.log('(Redis client closed)'); return; }); db.on('error', function (message) { // This function needs documentation. console.error('Error:', message); return; }); process.on('exit', function () { // This function needs documentation. db.quit(); console.log('(Redis client released)'); return; }); return { collect_garbage: collect_garbage, get_avar: get_avar, get_list: get_list, set_avar: set_avar }; }; // That's all, folks! return; }()); //- vim:set syntax=javascript: