1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const Base = require('../base/Component');
|
7 |
|
8 | module.exports = class Scheduler extends Base {
|
9 |
|
10 | static getConstants () {
|
11 | return {
|
12 | EVENT_TASK_BEFORE_RUN: 'taskBeforeRun',
|
13 | EVENT_TASK_DONE: 'taskDone',
|
14 | EVENT_TASK_FAIL: 'taskFail'
|
15 | };
|
16 | }
|
17 |
|
18 | constructor (config) {
|
19 | super({
|
20 | tasks: {},
|
21 | refreshInterval: 60,
|
22 | Task: require('./Task'),
|
23 | ...config
|
24 | });
|
25 | this._taskMap = new DataMap;
|
26 | this._taskBeforeRunHandler = this.taskBeforeRun.bind(this);
|
27 | this._taskDoneHandler = this.taskDone.bind(this);
|
28 | this._taskFailHandler = this.taskFail.bind(this);
|
29 | this.Task = ClassHelper.normalizeSpawn(this.Task);
|
30 | }
|
31 |
|
32 | init () {
|
33 | this.addTasks(this.tasks);
|
34 | this.module.app.on(this.module.app.EVENT_AFTER_START, this.refresh.bind(this));
|
35 | }
|
36 |
|
37 | isActive () {
|
38 | return !!this._timer;
|
39 | }
|
40 |
|
41 | start () {
|
42 | this.stop();
|
43 | this._timer = setTimeout(this.refresh.bind(this), this.refreshInterval * 1000);
|
44 | }
|
45 |
|
46 | stop () {
|
47 | if (this._timer) {
|
48 | clearTimeout(this._timer);
|
49 | this._timer = null;
|
50 | }
|
51 | }
|
52 |
|
53 | async refresh () {
|
54 | for (const task of this._taskMap) {
|
55 | await task.refresh();
|
56 | }
|
57 | this.start();
|
58 | }
|
59 |
|
60 |
|
61 |
|
62 | getTask (name) {
|
63 | return this._taskMap.get(name);
|
64 | }
|
65 |
|
66 | addTasks (data, params) {
|
67 | if (data) {
|
68 | for (const name of Object.keys(data)) {
|
69 | this.addTask(name, data[name], params);
|
70 | }
|
71 | }
|
72 | }
|
73 |
|
74 | addTask (name, config, params) {
|
75 | if (this.getTask(name)) {
|
76 | return this.log('error', `Task already exists: ${name}`);
|
77 | }
|
78 | try {
|
79 | const task = this.createTask(name, config, params);
|
80 | task.init();
|
81 | this._taskMap.set(name, task);
|
82 | this.log('info', `Task added: ${name}`);
|
83 | } catch (err) {
|
84 | this.log('error', `Invalid task: ${name}`, err);
|
85 | }
|
86 | }
|
87 |
|
88 | createTask (name, config, params) {
|
89 | config = {...this.Task, ...config};
|
90 | const task = this.spawn(config, {...params, name, scheduler: this});
|
91 | task.on(task.EVENT_BEFORE_RUN, this._taskBeforeRunHandler);
|
92 | task.on(task.EVENT_DONE, this._taskDoneHandler);
|
93 | task.on(task.EVENT_FAIL, this._taskFailHandler);
|
94 | return task;
|
95 | }
|
96 |
|
97 | deleteTask (name) {
|
98 | const task = this.getTask(name);
|
99 | if (!task) {
|
100 | return this.log('error', `Task not found: ${name}`);
|
101 | }
|
102 | if (this.detachTask(task)) {
|
103 | this._taskMap.unset(name);
|
104 | this.log('info', `Task deleted: ${name}`);
|
105 | return true;
|
106 | }
|
107 | }
|
108 |
|
109 | deleteAllTasks () {
|
110 | for (const task of this._taskMap) {
|
111 | this.detachTask(task);
|
112 | }
|
113 | this._taskMap.clear();
|
114 | }
|
115 |
|
116 | detachTask (task) {
|
117 | try {
|
118 | task.off();
|
119 | task.stop();
|
120 | return true;
|
121 | } catch (err) {
|
122 | this.log('error', `Task detaching failed: ${task.name}`, err);
|
123 | }
|
124 | }
|
125 |
|
126 | async executeTasks (names) {
|
127 | if (Array.isArray(names)) {
|
128 | for (const name of names) {
|
129 | await this.executeTask(name);
|
130 | }
|
131 | }
|
132 | }
|
133 |
|
134 | executeTask (name) {
|
135 | const task = this.getTask(name);
|
136 | if (!task) {
|
137 | return this.log('error', `Task not found: ${name}`);
|
138 | }
|
139 | return task.isActive() ? task.execute() : null;
|
140 | }
|
141 |
|
142 | taskBeforeRun (event) {
|
143 | return this.trigger(this.EVENT_TASK_BEFORE_RUN, event);
|
144 | }
|
145 |
|
146 | taskDone (event) {
|
147 | this.log('info', `Task done: ${event.sender.name}`, event.result);
|
148 | return this.trigger(this.EVENT_TASK_DONE, event);
|
149 | }
|
150 |
|
151 | taskFail (event) {
|
152 | this.log('error', `Task failed: ${event.sender.name}:`, event.error);
|
153 | return this.trigger(this.EVENT_TASK_FAIL, event);
|
154 | }
|
155 | };
|
156 | module.exports.init();
|
157 |
|
158 | const ClassHelper = require('../helper/ClassHelper');
|
159 | const DataMap = require('../base/DataMap'); |
\ | No newline at end of file |