-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjob.js
More file actions
128 lines (111 loc) · 3.2 KB
/
job.js
File metadata and controls
128 lines (111 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const _ = require('lodash');
const config = require('@cheevr/config');
const Context = require('./context');
const Logger = require('@cheevr/logging');
const moment = require('moment');
const path = require('path');
/**
* The general configuration object for any type of job.
* @typedef {object} JobConfig
* @property {string} [name=executor.name] The name for this job, used to identify it later on.
* @property {number} [sleep=0] The minimum time to wait between jobs
*/
/**
* The function that will execute a job is given by the developer.
* @typedef {function} JobExecutor
* @params {JobContext} context
*/
const log = Logger[config.tasks.logger];
const taskFile = process.argv[4];
const taskName = path.basename(taskFile, path.extname(taskFile));
class Job {
/**
* @param {JobConfig} jobConfig
* @param {JobExecutor} executor
*/
constructor(jobConfig, executor) {
_.defaultsDeep(jobConfig, config.defaults.tasks);
this._config = jobConfig;
this._exector = executor;
this._lastRun = 0;
this.state = 'idle';
if (jobConfig.sleep) {
jobConfig.sleep = Job._toInterval(jobConfig.sleep);
}
this._timeout = setTimeout(this.run.bind(this), this.nextRun);
}
run() {
this.state = 'running';
let context = new Context();
this._lastRun = moment();
return context.execute(this).then(() => {
log.debug('Job "%s" in task "%s" finished within %s', this.id, taskName, context.elapsed.humanize());
this.state = 'idle';
return context;
}).catch(err => {
log.error('Error running job', err.stack || err.toString());
this.state = 'error';
});
}
/**
* Will send the current state to the task object in the parent instance.
* @param {string} state Should be one of idle, running or error
*/
set state(state) {
this._state = state;
Job._send({ method:'state', args: [this.id, state]});
}
/**
* Will return the current state (idle, running or error)
* @returns {string}
*/
get state() {
return this._state;
}
/**
* This will a unique identifier for this job (which for now is the user given job name).
* @returns {string}
*/
get id() {
return this._config.name;
}
/**
* @returns {JobExecutor}
*/
get executor() {
return this._exector;
}
/**
* @returns {JobConfig}
*/
get config() {
return this._config;
}
/**
* @returns {moment.Moment}
*/
get lastRun() {
return this._lastRun;
}
/**
* The ms until the next run should occur.
* @returns {number}
*/
get nextRun() {
return this._config.sleep;
}
/**
* Tries a few times to send a message to the parent process.
* @param {object} message
* @param {number} [retries=0]
* @private
*/
static _send(message, retries = 0) {
try {
process.send(message);
} catch (err) {
retries < 3 && setImmediate(() => send(message, ++retries));
}
}
}
module.exports = exports = Job;