uow-store-rethink
Version:
A RethinkDB storage driver for the Unit-of-Work Queue module.
174 lines (121 loc) • 3.57 kB
JavaScript
var R = require('ramda');
var bluebird = require('bluebird');
var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter;
var DB = require('./db.js');
var TABLE = 'uow_task';
var defaults = {
// Default search delay is 500ms.
taskReadyDelay: 500,
isTaskReady: R.where({ status: R.equals('ready') }),
runTaskSearch: false
};
function RethinkDriver(options) {
options = R.merge(defaults, options);
this.db = DB(options);
this.r = this.db.r;
this.isTaskReady = options.isTaskReady;
this.taskReadyDelay = options.taskReadyDelay;
this.runTaskSearch = options.runTaskSearch;
this.readyTaskQuery = this.r.table(TABLE).filter(
this.r.row('status').eq('ready')
.and(
this.r.row.hasFields('semaphore').not().or(
this.r.row('semaphore').eq(null)
)
)
);
if (this.runTaskSearch) {
this.findReady(this.taskReadyDelay);
}
}
inherits(RethinkDriver, EventEmitter);
/**
* Search through the stored tasks to find any ready to proces tasks.
* ------------------------------------------------------------------
* @param {int} delay - number of milliseconds
*/
RethinkDriver.prototype.findReady = function(delay) {
if (delay) {
return setTimeout(this.findReady.bind(this), delay);
}
this.db.run(this.readyTaskQuery)
.then(function(readyTaskList) {
for (var i = 0; i < readyTaskList.length; i += 1) {
this.emit('task::ready', readyTaskList[i].id);
}
}.bind(this));
if (this.runTaskSearch) {
this.findReady(this.taskReadyDelay);
}
};
/**
* Store the given task object.
* ----------------------------
* @param {Task} task
* @return {Promise::Task}
* @throws {TypeError}
*/
RethinkDriver.prototype.create = function(task) {
return bluebird.resolve(task.id)
.then(function(taskId) {
if (!taskId) {
throw new TypeError('TaskIdNotPresent');
}
return this.getById(taskId)
.then(function() {
throw new TypeError('TaskIdExists');
})
.catch(RangeError, function() {
return task;
});
}.bind(this))
.then(function(task) {
var query = this.r.table(TABLE).insert(task);
return this.db.run(query)
.then(function() {
return this.getById(task.id);
}.bind(this));
}.bind(this));
};
/**
* Replace the stored task object with the given task object.
* ----------------------------------------------------------
* @param {Task} task
* @return {Promise::Task}
* @throws {TypeError}
*/
RethinkDriver.prototype.update = function(task) {
return bluebird.resolve(task.id)
.then(function(taskId) {
if (!taskId) {
throw new TypeError('TaskIdNotPresent');
}
var update = this.r.table(TABLE).get(taskId).update(task);
return this.db.run(update);
}.bind(this))
.then(function(updated) {
if (updated.skipped > 0) {
throw new RangeError('TaskNotFound');
}
return this.getById(task.id);
}.bind(this));
};
/**
* Retrieve a task by its identifier.
* ----------------------------------
* @param {string} id
* @return {Promise::Task}
* @throws {RangeError}
*/
RethinkDriver.prototype.getById = function(id) {
var query = this.r.table(TABLE).get(id);
return this.db.run(query)
.then(function(task) {
if (!task) {
throw new RangeError('TaskNotFound');
}
return task;
});
};
module.exports = RethinkDriver;