UNPKG

thinknode

Version:

A fast, flexible and all-in-one web framework for node.js.

272 lines (216 loc) 11 kB
'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的简单定时任务。 * 通过订阅redis __keyevent@{db}__:expired事件来执行。 * 需要开启Redis Keyspace Notifications * 修改redis配置notify-keyspace-events: 'Ex' * @author richen * @copyright Copyright (c) 2017 - <richenlin(at)gmail.com> * @license MIT * @version 2017/2/24 */ 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(options) { 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 = 'THINKTASK'; }; _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 + '_keyevent'); !THINK_CACHES.INSTANCES.REDISTASK && (THINK_CACHES.INSTANCES.REDISTASK = {}); if (!THINK_CACHES.INSTANCES.REDISTASK[key]) { _context2.next = 4; break; } return _context2.abrupt('return', _promise2.default.resolve(THINK_CACHES.INSTANCES.REDISTASK[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.REDISTASK[key] = {}; pub = THINK.adapter('RedisSocket', self.options); sub = THINK.adapter('RedisSocket', self.options); THINK_CACHES.INSTANCES.REDISTASK[key].INS = pub; THINK_CACHES.INSTANCES.REDISTASK[key].TASK = {}; _context.next = 7; return pub.connect(); case 7: THINK_CACHES.INSTANCES.REDISTASK[key].PUB = pub.handle; _context.next = 10; return sub.connect(); case 10: THINK_CACHES.INSTANCES.REDISTASK[key].SUB = sub.handle; return _context.abrupt('return', THINK_CACHES.INSTANCES.REDISTASK[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 cls * @param fname * @param args * @param timeout * @return {Promise.<void>} */ _class.prototype.task = function () { var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(cls, fname, args, timeout) { var handle, cronValue, cronKey, info; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _context3.next = 2; return this.trigger(cls, fname); case 2: _context3.next = 4; return this.connect(); case 4: handle = _context3.sent; cronValue = args; //非标量序列化 if (!THINK.isScalar(args)) { cronValue = (0, _stringify2.default)(args); } cronKey = THINK.md5(cronValue); //判断任务是否已经在队列中 _context3.next = 10; return handle.INS.wrap('hget', [this.prefix + '_TASK_DATA', this.prefix + '_' + cronKey]).catch(function (e) { THINK.log(e); return ''; }); case 10: info = _context3.sent; if (info) { _context3.next = 15; break; } _context3.next = 14; return handle.INS.wrap('hset', [this.prefix + '_TASK_DATA', this.prefix + '_' + cronKey, cronValue]).catch(function (e) { THINK.log(e); return null; }); case 14: return _context3.abrupt('return', handle.INS.wrap('setex', [this.prefix + '_' + cronKey, timeout, 1])); case 15: return _context3.abrupt('return', _promise2.default.resolve()); case 16: case 'end': return _context3.stop(); } } }, _callee3, this); })); function task(_x, _x2, _x3, _x4) { return _ref3.apply(this, arguments); } return task; }(); /** * 监听 * @param cls * @param fname * @return {Promise.<T>} */ _class.prototype.trigger = function () { var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4(cls, fname) { var handle, self; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: _context4.next = 2; return this.connect(); case 2: handle = _context4.sent; self = this; //查询订阅标志,防止多次订阅 if (!handle.TASK[self.options.redis_db]) { //订阅redis __keyevent@{db}__:expired事件 handle.SUB.psubscribe('__keyevent@' + self.options.redis_db + '__:expired'); handle.TASK[self.options.redis_db] = 1; //当接收到订阅消息调用对应服务 handle.SUB.on('pmessage', function (pattern, channel, expiredKey) { return handle.INS.wrap('hget', [self.prefix + '_TASK_DATA', expiredKey]).then(function (data) { var _args = []; try { // 解析函数参数 _args = JSON.parse(data); } catch (e) { return THINK.error(e); } //移除保存的数据 return handle.INS.wrap('hdel', [self.prefix + '_TASK_DATA', expiredKey]).then(function () { //执行任务 return cls[fname](_args); }); }); }); } return _context4.abrupt('return', _promise2.default.resolve()); case 6: case 'end': return _context4.stop(); } } }, _callee4, this); })); function trigger(_x5, _x6) { return _ref4.apply(this, arguments); } return trigger; }(); return _class; }(THINK.Base); exports.default = _class;