UNPKG

@dashevo/wallet-lib

Version:
147 lines (123 loc) 4.13 kB
const _ = require('lodash'); const StandardPlugin = require('./StandardPlugin'); // eslint-disable-next-line no-underscore-dangle const _defaultOpts = { workerIntervalTime: 10 * 1000, executeOnStart: false, firstExecutionRequired: false, workerMaxPass: null, executeAfterStart: false, }; class Worker extends StandardPlugin { constructor(opts = JSON.parse(JSON.stringify(_defaultOpts))) { const defaultOpts = JSON.parse(JSON.stringify(_defaultOpts)); super({ type: 'Worker', ...opts }); this.worker = null; this.workerPass = 0; this.isWorkerRunning = false; this.awaitOnInjection = _.has(opts, 'awaitOnInjection') ? opts.awaitOnInjection : false; this.firstExecutionRequired = _.has(opts, 'firstExecutionRequired') ? opts.firstExecutionRequired : defaultOpts.firstExecutionRequired; this.executeOnStart = _.has(opts, 'executeOnStart') ? opts.executeOnStart : defaultOpts.executeOnStart; this.workerIntervalTime = _.has(opts, 'workerIntervalTime') ? opts.workerIntervalTime : defaultOpts.workerIntervalTime; this.workerMaxPass = (opts.workerMaxPass) ? opts.workerMaxPass : defaultOpts.workerMaxPass; this.state = { started: false, ready: false, }; } async startWorker() { let payloadResult = null; const self = this; const eventTypeStarting = `WORKER/${this.name.toUpperCase()}/STARTING`; this.parentEvents.emit(eventTypeStarting, { type: eventTypeStarting, payload: payloadResult }); try { if (this.worker) await this.stopWorker(); if (this.workerIntervalTime > 0) { this.worker = setInterval(this.execWorker.bind(self), this.workerIntervalTime); } if (this.executeOnStart === true) { if (this.onStart) { payloadResult = await this.onStart(); } } const eventTypeStarted = `WORKER/${this.name.toUpperCase()}/STARTED`; this.parentEvents.emit(eventTypeStarted, { type: eventTypeStarted, payload: payloadResult }); this.state.started = true; // TODO: refactor this to be more elegant // This change is needed to refine plugin execution sequence // with the least amount of refactoring if (this.executeOnStart && this.executeAfterStart) { await this.execWorker(); } } catch (e) { this.emit('error', e, { type: 'plugin', pluginType: 'worker', pluginName: this.name, }); } } /** * @param {Object} [options] * @param {Boolean} [options.force=false] * @param {Boolean} [options.reason] * @returns {Promise<void>} */ async stopWorker(options = {}) { let payloadResult = options.reason; clearInterval(this.worker); this.worker = null; this.workerPass = 0; this.isWorkerRunning = false; const eventType = `WORKER/${this.name.toUpperCase()}/STOPPED`; if (this.onStop) { payloadResult = await this.onStop(options); } this.state.started = false; this.parentEvents.emit(eventType, { type: eventType, payload: payloadResult }); } async execWorker() { let payloadResult = null; if (this.isWorkerRunning) { return false; } if (this.workerMaxPass !== null && this.workerPass >= this.workerMaxPass) { await this.stopWorker(); return false; } this.isWorkerRunning = true; if (this.execute) { try { payloadResult = await this.execute(); } catch (e) { await this.stopWorker({ reason: e.message, }); this.emit('error', e, { type: 'plugin', pluginType: 'worker', pluginName: this.name, }); } } else { throw new Error(`Worker ${this.name}: Missing execute function`); } this.isWorkerRunning = false; this.workerPass += 1; if (!this.state.ready) this.state.ready = true; const eventType = `WORKER/${this.name.toUpperCase()}/EXECUTED`; this.parentEvents.emit(eventType, { type: eventType, payload: payloadResult }); return true; } } module.exports = Worker;