UNPKG

alaska

Version:

Componentized and pluggable web framework for Node.js

346 lines (307 loc) 7.67 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _collie = require('collie'); var _collie2 = _interopRequireDefault(_collie); var _stringRandom = require('string-random'); var _stringRandom2 = _interopRequireDefault(_stringRandom); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Sled { /** * Sled构造函数 * @param {Object} [params] */ constructor(params) { this.params = params || {}; //队列item数据,只有从队列中读取的Sled或将Sled发送到队列后才有此属性 this.item = null; //执行结果 this.result = undefined; //错误 this.error = undefined; } /** * 获取sled所属service * @returns {Service} */ get service() { return this.constructor.service; } /** * 获取Sled name * @returns {string} */ get sledName() { return this.constructor.sledName || this.constructor.name; } /** * 获取Sled key * @returns {string} */ get key() { return this.constructor.key; } /** * 获取sled配置 * @private * @returns {Object} */ get config() { return this.constructor.config; } /** * 获取队列驱动 * @private * @returns {Alaska$QueueDriver} */ createQueueDriver() { return this.constructor.createQueueDriver(); } /** * 获取订阅驱动 * @private * @param {string} channel 频道ID * @returns {Alaska$SubscribeDriver} */ createSubscribeDriver(channel) { return this.constructor.createSubscribeDriver(channel); } /** * 注册 Sled 前置钩子 * @param fn */ static pre(fn) { if (!this._pre) { this._pre = []; } this._pre.push(fn); } /** * 注册 Sled 后置钩子 * @param fn */ static post(fn) { if (!this._post) { this._post = []; } this._post.push(fn); } /** * 获取Sled设置 * @private * @returns {Object} */ static get config() { if (!this._config) { let { service, key } = this; let name = 'sled.' + key; let config = service.getConfig(name, undefined, true); if (!config) { config = service.getConfig('sled', undefined, true); } this._config = config; } if (!this._config) { throw new ReferenceError('sled config not found'); } return this._config; } /** * 获取Sled队列驱动 * @private * @returns {Alaska$QueueDriver} */ static createQueueDriver() { let { config, key } = this; if (!config.queue) { throw new ReferenceError('sled queue config not found'); } // $Flow return this.service.createDriver(_lodash2.default.defaults({}, config.queue, { key })); } /** * 获取Sled订阅驱动 * @private * @param {string} channel 频道ID * @returns {Alaska$SubscribeDriver} */ static createSubscribeDriver(channel) { let { config } = this; if (!config.subscribe) { throw new ReferenceError('sled subscribe config not found'); } // $Flow return this.service.createDriver(_lodash2.default.defaults({ channel }, config.subscribe)); } /** * alias for sled.run() * @param {Object} [params] * @returns {Promise<any>} */ static run(params) { let sled = new this(params); return sled.run(); } /** * 将Sled发送到队列 * @param {number} [timeout] Sled超时时间,单位秒,默认60天 * @param {boolean} [notify] Sled执行后是否需要通知,默认false */ async send(timeout, notify) { if (this.result || this.error) { throw new Error('can not send a finished sled'); } //如果已经有item属性,代表已经发送到队列,或者是从队列中读取的sled if (this.item) { return this.item; } //默认60天超时 timeout = timeout || 60 * 86400; let { params, key, id } = this; if (this.toJSON) { params = this.toJSON(); } if (!id) { id = 'sled.' + key + '.' + (0, _stringRandom2.default)(10); this.id = id; } let item = { id, key, notify: notify || false, params, sledName: this.sledName, result: undefined, error: undefined, timeout: timeout || 0, createdAt: new Date(), expiredAt: new Date(Date.now() + timeout * 1000) }; let queue = this.createQueueDriver(); await queue.push(item); queue.free(); return item; } /** * 从队列中读取一个sled * @param {number} [timeout] 读取超时,单位毫秒,默认Infinity */ static async read(timeout) { let queue = this.createQueueDriver(); let item = await queue.pop(timeout); queue.free(); if (!item) { return null; } let sled = new this(); if (sled.fromJSON) { sled.fromJSON(item.params); } else { sled.params = item.params; } if (item.result !== undefined) { sled.result = item.result; } else if (item.error) { sled.error = new Error(item.error); } sled.fromQueue = true; sled.item = item; sled.id = item.id; // $Flow return sled; } /** * 等待队列中sled执行 * @param {number} [waitTimeout] 超时时间,单位秒,默认为Infinity,超时后将返回null * @param {number} [sledTimeout] Sled执行超时时间,单位秒,默认为60天 */ async wait(waitTimeout, sledTimeout) { if (this.result) { return this.result; } if (this.error) { throw this.error; } if (!this.id) { this.id = 'sled.' + this.key + '.' + (0, _stringRandom2.default)(10); } let { id } = this; if (!this.item) { //异步将sled插入队列 this.send(sledTimeout, true); } let subscribe = this.createSubscribeDriver(id); let msg = await subscribe.once(waitTimeout); subscribe.free(); if (!msg) { return null; } if (msg.result !== undefined) { this.result = msg.result; } else if (msg.error) { this.error = new Error(msg.error); throw this.error; } return this.result; } /** * 执行sled * @returns {*} */ async run() { if (this.error) { throw this.error; } if (this.result !== undefined) { return this.result; } if (this.validate) { let promise = this.validate(this.params); if (promise && promise.then) { await promise; } } if (this.constructor._pre) { await _collie2.default.compose(this.constructor._pre, [], this); } let { result } = this; //如果已经有result,说明在前置hooks中已经执行完成任务 try { result = this.exec(this.params); if (result && result.then) { result = await result; } } catch (error) { this.error = error; if (this.item && this.item.notify) { // 发送通知 let subscribe = this.createSubscribeDriver(this.item.id); await subscribe.publish({ error: error.message }); subscribe.free(); } throw error; } this.result = result; if (this.constructor._post) { await _collie2.default.compose(this.constructor._post, [result], this); } if (this.item && this.item.notify) { // 发送通知 let subscribe = this.createSubscribeDriver(this.item.id); await subscribe.publish({ result }); subscribe.free(); } return result; } /** * @method validate */ /** * @method exec */ } exports.default = Sled; Sled.classOfSled = true;