@nexrender/worker 1.49.5 → 1.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/index.js +3 -191
- package/src/instance.js +209 -0
- package/test/manual.js +11 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexrender/worker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.50.1",
|
|
4
4
|
"author": "inlife",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"homepage": "https://www.nexrender.com",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
]
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@nexrender/api": "^1.
|
|
22
|
+
"@nexrender/api": "^1.50.1",
|
|
23
23
|
"@nexrender/core": "^1.49.4",
|
|
24
24
|
"@nexrender/types": "^1.45.6",
|
|
25
25
|
"arg": "^4.1.0",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "e83623a41385043839ce1135e8748b0273008aee"
|
|
33
33
|
}
|
package/src/index.js
CHANGED
|
@@ -1,193 +1,5 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const { init, render } = require('@nexrender/core')
|
|
3
|
-
const { getRenderingStatus } = require('@nexrender/types/job')
|
|
4
|
-
const pkg = require('../package.json')
|
|
1
|
+
const { createWorker } = require('./instance')
|
|
5
2
|
|
|
6
|
-
const
|
|
7
|
-
const NEXRENDER_TOLERATE_EMPTY_QUEUES = process.env.NEXRENDER_TOLERATE_EMPTY_QUEUES;
|
|
8
|
-
var emptyReturns = 0;
|
|
3
|
+
const instance = createWorker()
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const delay = amount => (
|
|
13
|
-
new Promise(resolve => setTimeout(resolve, amount))
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
const nextJob = async (client, settings) => {
|
|
17
|
-
do {
|
|
18
|
-
try {
|
|
19
|
-
let job = await (settings.tagSelector ?
|
|
20
|
-
await client.pickupJob(settings.tagSelector) :
|
|
21
|
-
await client.pickupJob()
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
if (job && job.uid) {
|
|
25
|
-
emptyReturns = 0;
|
|
26
|
-
return job
|
|
27
|
-
} else {
|
|
28
|
-
// no job was returned by the server. If enough checks have passed, and the exit option is set, deactivate the worker
|
|
29
|
-
emptyReturns++;
|
|
30
|
-
if (settings.exitOnEmptyQueue && emptyReturns > settings.tolerateEmptyQueues) active = false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
} catch (err) {
|
|
34
|
-
if (settings.stopOnError) {
|
|
35
|
-
throw err;
|
|
36
|
-
} else {
|
|
37
|
-
console.error(err)
|
|
38
|
-
console.error("render proccess stopped with error...")
|
|
39
|
-
console.error("continue listening next job...")
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (active) await delay(settings.polling || NEXRENDER_API_POLLING)
|
|
44
|
-
} while (active)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Starts worker "thread" of continious loop
|
|
49
|
-
* of fetching queued projects and rendering them
|
|
50
|
-
* @param {String} host
|
|
51
|
-
* @param {String} secret
|
|
52
|
-
* @param {Object} settings
|
|
53
|
-
* @return {Promise}
|
|
54
|
-
*/
|
|
55
|
-
const start = async (host, secret, settings, headers) => {
|
|
56
|
-
settings = init(Object.assign({ process: 'nexrender-worker' }, settings, {
|
|
57
|
-
logger: console,
|
|
58
|
-
}))
|
|
59
|
-
|
|
60
|
-
settings.logger.log('starting nexrender-worker with following settings:')
|
|
61
|
-
Object.keys(settings).forEach(key => {
|
|
62
|
-
settings.logger.log(` - ${key}: ${settings[key]}`)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
if (typeof settings.tagSelector == 'string') {
|
|
66
|
-
settings.tagSelector = settings.tagSelector.replace(/[^a-z0-9, ]/gi, '')
|
|
67
|
-
}
|
|
68
|
-
// if there is no setting for how many empty queues to tolerate, make one from the
|
|
69
|
-
// environment variable, or the default (which is zero)
|
|
70
|
-
if (!(typeof settings.tolerateEmptyQueues == 'number')) {
|
|
71
|
-
settings.tolerateEmptyQueues = NEXRENDER_TOLERATE_EMPTY_QUEUES;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
headers = headers || {};
|
|
75
|
-
headers['user-agent'] = ('nexrender-worker/' + pkg.version + ' ' + (headers['user-agent'] || '')).trim();
|
|
76
|
-
|
|
77
|
-
const client = createClient({ host, secret, headers, name: settings.name });
|
|
78
|
-
|
|
79
|
-
settings.track('Worker Started', {
|
|
80
|
-
worker_tags_set: !!settings.tagSelector,
|
|
81
|
-
worker_setting_tolerate_empty_queues: settings.tolerateEmptyQueues,
|
|
82
|
-
worker_setting_exit_on_empty_queue: settings.exitOnEmptyQueue,
|
|
83
|
-
worker_setting_polling: settings.polling,
|
|
84
|
-
worker_setting_stop_on_error: settings.stopOnError,
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
do {
|
|
88
|
-
let job = await nextJob(client, settings);
|
|
89
|
-
|
|
90
|
-
// if the worker has been deactivated, exit this loop
|
|
91
|
-
if (!active) break;
|
|
92
|
-
|
|
93
|
-
settings.track('Worker Job Started', {
|
|
94
|
-
job_id: job.uid, // anonymized internally
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
job.state = 'started';
|
|
98
|
-
job.startedAt = new Date()
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
await client.updateJob(job.uid, job)
|
|
102
|
-
} catch (err) {
|
|
103
|
-
console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
|
|
104
|
-
console.log(`[${job.uid}] error stack: ${err.stack}`)
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
job.onRenderProgress = (job) => {
|
|
110
|
-
try {
|
|
111
|
-
/* send render progress to our server */
|
|
112
|
-
client.updateJob(job.uid, getRenderingStatus(job));
|
|
113
|
-
|
|
114
|
-
if (settings.onRenderProgress) {
|
|
115
|
-
settings.onRenderProgress(job);
|
|
116
|
-
}
|
|
117
|
-
} catch (err) {
|
|
118
|
-
if (settings.stopOnError) {
|
|
119
|
-
throw err;
|
|
120
|
-
} else {
|
|
121
|
-
console.log(`[${job.uid}] error occurred: ${err.stack}`)
|
|
122
|
-
console.log(`[${job.uid}] render proccess stopped with error...`)
|
|
123
|
-
console.log(`[${job.uid}] continue listening next job...`)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
job.onRenderError = (job, err /* on render error */) => {
|
|
129
|
-
job.error = [].concat(job.error || [], [err.toString()]);
|
|
130
|
-
|
|
131
|
-
if (settings.onRenderError) {
|
|
132
|
-
settings.onRenderError(job, err);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
job = await render(job, settings); {
|
|
137
|
-
job.state = 'finished';
|
|
138
|
-
job.finishedAt = new Date();
|
|
139
|
-
if (settings.onFinished) {
|
|
140
|
-
settings.onFinished(job);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
settings.track('Worker Job Finished', { job_id: job.uid })
|
|
145
|
-
|
|
146
|
-
await client.updateJob(job.uid, getRenderingStatus(job))
|
|
147
|
-
} catch (err) {
|
|
148
|
-
job.error = [].concat(job.error || [], [err.toString()]);
|
|
149
|
-
job.errorAt = new Date();
|
|
150
|
-
job.state = 'error';
|
|
151
|
-
|
|
152
|
-
settings.track('Worker Job Error', { job_id: job.uid });
|
|
153
|
-
|
|
154
|
-
if (settings.onError) {
|
|
155
|
-
settings.onError(job, err);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
await client.updateJob(job.uid, getRenderingStatus(job))
|
|
160
|
-
}
|
|
161
|
-
catch (e) {
|
|
162
|
-
console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
|
|
163
|
-
console.log(`[${job.uid}] error stack: ${e.stack}`)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (settings.stopOnError) {
|
|
167
|
-
throw err;
|
|
168
|
-
} else {
|
|
169
|
-
console.log(`[${job.uid}] error occurred: ${err.stack}`)
|
|
170
|
-
console.log(`[${job.uid}] render proccess stopped with error...`)
|
|
171
|
-
console.log(`[${job.uid}] continue listening next job...`)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
} while (active)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Stops worker "thread"
|
|
179
|
-
* @return {void}
|
|
180
|
-
*/
|
|
181
|
-
const stop = () => {
|
|
182
|
-
active = false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Returns the current status of the worker
|
|
187
|
-
* @return {Boolean}
|
|
188
|
-
*/
|
|
189
|
-
const isRunning = () => {
|
|
190
|
-
return active;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
module.exports = { start, stop, isRunning }
|
|
5
|
+
module.exports = instance
|
package/src/instance.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
const { createClient } = require('@nexrender/api')
|
|
2
|
+
const { init, render } = require('@nexrender/core')
|
|
3
|
+
const { getRenderingStatus } = require('@nexrender/types/job')
|
|
4
|
+
const pkg = require('../package.json')
|
|
5
|
+
|
|
6
|
+
const NEXRENDER_API_POLLING = process.env.NEXRENDER_API_POLLING || 30 * 1000;
|
|
7
|
+
const NEXRENDER_TOLERATE_EMPTY_QUEUES = process.env.NEXRENDER_TOLERATE_EMPTY_QUEUES;
|
|
8
|
+
|
|
9
|
+
const delay = amount => new Promise(resolve => setTimeout(resolve, amount))
|
|
10
|
+
|
|
11
|
+
const createWorker = () => {
|
|
12
|
+
let emptyReturns = 0;
|
|
13
|
+
let active = false;
|
|
14
|
+
let settingsRef = null;
|
|
15
|
+
|
|
16
|
+
const nextJob = async (client, settings) => {
|
|
17
|
+
do {
|
|
18
|
+
try {
|
|
19
|
+
let job = await (settings.tagSelector ?
|
|
20
|
+
await client.pickupJob(settings.tagSelector) :
|
|
21
|
+
await client.pickupJob()
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
if (job && job.uid) {
|
|
25
|
+
emptyReturns = 0;
|
|
26
|
+
return job
|
|
27
|
+
} else {
|
|
28
|
+
// no job was returned by the server. If enough checks have passed, and the exit option is set, deactivate the worker
|
|
29
|
+
emptyReturns++;
|
|
30
|
+
if (settings.exitOnEmptyQueue && emptyReturns > settings.tolerateEmptyQueues) active = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} catch (err) {
|
|
34
|
+
if (settings.stopOnError) {
|
|
35
|
+
throw err;
|
|
36
|
+
} else {
|
|
37
|
+
console.error(err)
|
|
38
|
+
console.error("render proccess stopped with error...")
|
|
39
|
+
console.error("continue listening next job...")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (active) await delay(settings.polling || NEXRENDER_API_POLLING)
|
|
44
|
+
} while (active)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Starts worker "thread" of continious loop
|
|
49
|
+
* of fetching queued projects and rendering them
|
|
50
|
+
* @param {String} host
|
|
51
|
+
* @param {String} secret
|
|
52
|
+
* @param {Object} settings
|
|
53
|
+
* @return {Promise}
|
|
54
|
+
*/
|
|
55
|
+
const start = async (host, secret, settings, headers) => {
|
|
56
|
+
settings = init(Object.assign({ process: 'nexrender-worker' }, settings, {
|
|
57
|
+
logger: console,
|
|
58
|
+
}))
|
|
59
|
+
|
|
60
|
+
settingsRef = settings;
|
|
61
|
+
active = true;
|
|
62
|
+
|
|
63
|
+
settings.logger.log('starting nexrender-worker with following settings:')
|
|
64
|
+
Object.keys(settings).forEach(key => {
|
|
65
|
+
settings.logger.log(` - ${key}: ${settings[key]}`)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
if (typeof settings.tagSelector == 'string') {
|
|
69
|
+
settings.tagSelector = settings.tagSelector.replace(/[^a-z0-9, ]/gi, '')
|
|
70
|
+
}
|
|
71
|
+
// if there is no setting for how many empty queues to tolerate, make one from the
|
|
72
|
+
// environment variable, or the default (which is zero)
|
|
73
|
+
if (!(typeof settings.tolerateEmptyQueues == 'number')) {
|
|
74
|
+
settings.tolerateEmptyQueues = NEXRENDER_TOLERATE_EMPTY_QUEUES;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
headers = headers || {};
|
|
78
|
+
headers['user-agent'] = ('nexrender-worker/' + pkg.version + ' ' + (headers['user-agent'] || '')).trim();
|
|
79
|
+
|
|
80
|
+
const client = createClient({ host, secret, headers, name: settings.name });
|
|
81
|
+
|
|
82
|
+
settings.track('Worker Started', {
|
|
83
|
+
worker_tags_set: !!settings.tagSelector,
|
|
84
|
+
worker_setting_tolerate_empty_queues: settings.tolerateEmptyQueues,
|
|
85
|
+
worker_setting_exit_on_empty_queue: settings.exitOnEmptyQueue,
|
|
86
|
+
worker_setting_polling: settings.polling,
|
|
87
|
+
worker_setting_stop_on_error: settings.stopOnError,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
do {
|
|
91
|
+
let job = await nextJob(client, settings);
|
|
92
|
+
|
|
93
|
+
// if the worker has been deactivated, exit this loop
|
|
94
|
+
if (!active) break;
|
|
95
|
+
|
|
96
|
+
settings.track('Worker Job Started', {
|
|
97
|
+
job_id: job.uid, // anonymized internally
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
job.state = 'started';
|
|
101
|
+
job.startedAt = new Date()
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
await client.updateJob(job.uid, job)
|
|
105
|
+
} catch (err) {
|
|
106
|
+
console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
|
|
107
|
+
console.log(`[${job.uid}] error stack: ${err.stack}`)
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
job.onRenderProgress = (job) => {
|
|
113
|
+
try {
|
|
114
|
+
/* send render progress to our server */
|
|
115
|
+
client.updateJob(job.uid, getRenderingStatus(job));
|
|
116
|
+
|
|
117
|
+
if (settings.onRenderProgress) {
|
|
118
|
+
settings.onRenderProgress(job);
|
|
119
|
+
}
|
|
120
|
+
} catch (err) {
|
|
121
|
+
if (settings.stopOnError) {
|
|
122
|
+
throw err;
|
|
123
|
+
} else {
|
|
124
|
+
console.log(`[${job.uid}] error occurred: ${err.stack}`)
|
|
125
|
+
console.log(`[${job.uid}] render proccess stopped with error...`)
|
|
126
|
+
console.log(`[${job.uid}] continue listening next job...`)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
job.onRenderError = (job, err /* on render error */) => {
|
|
132
|
+
job.error = [].concat(job.error || [], [err.toString()]);
|
|
133
|
+
|
|
134
|
+
if (settings.onRenderError) {
|
|
135
|
+
settings.onRenderError(job, err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
job = await render(job, settings); {
|
|
140
|
+
job.state = 'finished';
|
|
141
|
+
job.finishedAt = new Date();
|
|
142
|
+
if (settings.onFinished) {
|
|
143
|
+
settings.onFinished(job);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
settings.track('Worker Job Finished', { job_id: job.uid })
|
|
148
|
+
|
|
149
|
+
await client.updateJob(job.uid, getRenderingStatus(job))
|
|
150
|
+
} catch (err) {
|
|
151
|
+
job.error = [].concat(job.error || [], [err.toString()]);
|
|
152
|
+
job.errorAt = new Date();
|
|
153
|
+
job.state = 'error';
|
|
154
|
+
|
|
155
|
+
settings.track('Worker Job Error', { job_id: job.uid });
|
|
156
|
+
|
|
157
|
+
if (settings.onError) {
|
|
158
|
+
settings.onError(job, err);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
await client.updateJob(job.uid, getRenderingStatus(job))
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
|
|
166
|
+
console.log(`[${job.uid}] error stack: ${e.stack}`)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (settings.stopOnError) {
|
|
170
|
+
throw err;
|
|
171
|
+
} else {
|
|
172
|
+
console.log(`[${job.uid}] error occurred: ${err.stack}`)
|
|
173
|
+
console.log(`[${job.uid}] render proccess stopped with error...`)
|
|
174
|
+
console.log(`[${job.uid}] continue listening next job...`)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} while (active)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Stops worker "thread"
|
|
182
|
+
* @return {void}
|
|
183
|
+
*/
|
|
184
|
+
const stop = () => {
|
|
185
|
+
if (settingsRef) {
|
|
186
|
+
settingsRef.logger.log('stopping nexrender-worker')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
active = false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Returns the current status of the worker
|
|
194
|
+
* @return {Boolean}
|
|
195
|
+
*/
|
|
196
|
+
const isRunning = () => {
|
|
197
|
+
return active;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
start,
|
|
202
|
+
stop,
|
|
203
|
+
isRunning
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = {
|
|
208
|
+
createWorker,
|
|
209
|
+
}
|
package/test/manual.js
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
process.env.NEXRENDER_API_POLLING =
|
|
1
|
+
process.env.NEXRENDER_API_POLLING = 1000
|
|
2
|
+
const {createWorker} = require('../src/instance')
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
+
const instance1 = createWorker()
|
|
5
|
+
const instance2 = createWorker()
|
|
6
|
+
const instance3 = createWorker()
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (i++ > 5) {
|
|
9
|
-
return [{state: 'queued'}]
|
|
10
|
-
}
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
8
|
+
setTimeout(() => instance1.start('https://localhost:3000', 'secret', {name: 'worker 1'}), 0)
|
|
9
|
+
setTimeout(() => instance2.start('https://localhost:3000', 'secret', {name: 'worker 2'}), 1000)
|
|
10
|
+
setTimeout(() => instance3.start('https://localhost:3000', 'secret', {name: 'worker 3'}), 2000)
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const p = await nextJob(client)
|
|
18
|
-
console.log('got job', p)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
foo();
|
|
12
|
+
setTimeout(() => instance1.stop(), 4000)
|
|
13
|
+
setTimeout(() => instance2.stop(), 5000)
|
|
14
|
+
setTimeout(() => instance3.stop(), 6000)
|