thinknode
Version:
A fast, flexible and all-in-one web framework for node.js.
269 lines (216 loc) • 10.7 kB
JavaScript
'use strict';
exports.__esModule = true;
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 基于redis的简单队列
* 支持订阅sub,发布pub
* @author richen
* @copyright Copyright (c) 2016 - <richenlin(at)gmail.com>
* @license MIT
* @version 2016/11/2
*/
var _class = function (_THINK$Base) {
(0, _inherits3.default)(_class, _THINK$Base);
function _class() {
(0, _classCallCheck3.default)(this, _class);
return (0, _possibleConstructorReturn3.default)(this, _THINK$Base.apply(this, arguments));
}
_class.prototype.init = function init(channel, options) {
this.channel = channel || 'queue';
this.options = {
redis_host: options.redis_host || '127.0.0.1',
redis_port: options.redis_port || 6379,
redis_db: options.redis_db || '1',
redis_password: options.redis_password || '',
redis_timeout: null
};
this.prefix = 'THINKQUEUE';
};
_class.prototype.connect = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2() {
var key, self;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
key = THINK.hash(this.options.redis_host + '_' + this.channel);
!THINK_CACHES.INSTANCES.REDISQUEUE && (THINK_CACHES.INSTANCES.REDISQUEUE = {});
if (!THINK_CACHES.INSTANCES.REDISQUEUE[key]) {
_context2.next = 4;
break;
}
return _context2.abrupt('return', _promise2.default.resolve(THINK_CACHES.INSTANCES.REDISQUEUE[key]));
case 4:
self = this;
return _context2.abrupt('return', THINK.await(key, (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
var pub, sub;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
THINK_CACHES.INSTANCES.REDISQUEUE[key] = {};
pub = THINK.adapter('RedisSocket', self.options);
sub = THINK.adapter('RedisSocket', self.options);
THINK_CACHES.INSTANCES.REDISQUEUE[key].INS = pub;
THINK_CACHES.INSTANCES.REDISQUEUE[key].INS.QUEUE = {};
_context.next = 7;
return pub.connect();
case 7:
THINK_CACHES.INSTANCES.REDISQUEUE[key].PUB = pub.handle;
_context.next = 10;
return sub.connect();
case 10:
THINK_CACHES.INSTANCES.REDISQUEUE[key].SUB = sub.handle;
return _context.abrupt('return', THINK_CACHES.INSTANCES.REDISQUEUE[key]);
case 12:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}))));
case 6:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function connect() {
return _ref.apply(this, arguments);
}
return connect;
}();
/**
* 发布
* @param data
*/
_class.prototype.pub = function () {
var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(data) {
var key, handle;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
key = this.prefix + '_' + this.channel, handle = void 0;
return _context3.abrupt('return', this.connect(this.channel).then(function (cls) {
handle = cls;
return THINK.await(key, function () {
return handle.INS.wrap('lrange', [key, 0, -1]).then(function (list) {
//队列中存在未处理完的任务
var ps = [];
list.forEach(function (item) {
ps.push(handle.PUB.publish(key, item));
});
return _promise2.default.all(ps);
});
});
}).then(function () {
//非标量序列化
if (!THINK.isScalar(data)) {
data = (0, _stringify2.default)(data);
}
//压入队列
return handle.INS.wrap('rpush', [key, data]);
}).then(function () {
return handle.PUB.publish(key, data);
}));
case 2:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function pub(_x) {
return _ref3.apply(this, arguments);
}
return pub;
}();
/**
* 取消发布
* @returns {Promise.<TResult>}
*/
_class.prototype.unpub = function unpub() {
return this.connect(this.channel).then(function (cls) {
return cls.PUB.quit();
});
};
/**
* 订阅
* @param handles
* @returns {Promise.<TResult>}
*/
_class.prototype.sub = function () {
var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4(handles) {
var _this2 = this;
var key, handle;
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
key = this.prefix + '_' + this.channel, handle = void 0;
return _context4.abrupt('return', this.connect(this.channel).then(function (cls) {
handle = cls;
//防止多次订阅
if (!handle.INS.QUEUE[_this2.channel]) {
handle.INS.QUEUE[_this2.channel] = 1;
handle.SUB.subscribe(key);
//订阅处理
handle.SUB.on('message', function (channel, msg) {
return handle.INS.wrap('lpop', [key]).then(function (value) {
//外部处理函数托管
return handles(value, msg);
});
// .catch(err => {
// return handle.INS.wrap('rpush', [key, data]);
//});
});
}
return _promise2.default.resolve();
// return handle.INS.wrap('lrange', [key, 0, -1]);
// }).then(list => {
// //队列中存在未处理完的任务
// let ps = [];
// list.forEach(item => {
// ps.push(func(key, item, arg));
// });
// return Promise.all(ps);
}));
case 2:
case 'end':
return _context4.stop();
}
}
}, _callee4, this);
}));
function sub(_x2) {
return _ref4.apply(this, arguments);
}
return sub;
}();
/**
* 取消订阅
*/
_class.prototype.ubsub = function ubsub() {
return this.connect(this.channel).then(function (cls) {
return cls.SUB.quit();
});
};
return _class;
}(THINK.Base);
exports.default = _class;