@nexrender/worker 1.54.5 → 1.56.0
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 +2 -2
- package/readme.md +1 -1
- package/src/bin.js +15 -7
- package/src/instance.js +72 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexrender/worker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.0",
|
|
4
4
|
"author": "inlife",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"homepage": "https://www.nexrender.com",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "1387723d3320220f66ead9e9ca081cb287a8d9b4"
|
|
33
33
|
}
|
package/readme.md
CHANGED
|
@@ -96,4 +96,4 @@ Available settings (almost same as for `nexrender-core`):
|
|
|
96
96
|
* `actions` - an object with keys corresponding to the `module` field when defining an action, value should be a function matching expected signature of an action. Used for defining actions programmatically without needing to package the action as a separate package
|
|
97
97
|
* `cache` - boolean or string. Set the cache folder used by HTTP assets. If `true` will use the default path of `${workpath}/http-cache`, if set to a string it will be interpreted as a filesystem path to the cache folder.
|
|
98
98
|
* `name` - string. An unique name (or not) to the `nexrender-worker`, and it will be identified in the `nexrender-server`. It can be used as an executor name on picked job(s) as well.
|
|
99
|
-
|
|
99
|
+
* `handleInterruption` - boolean, if set to true, enables handling of interruption signals (SIGINT, SIGTERM). When an interruption signal is received, the worker will attempt to update the current job's state to 'queued' before shutting down. (false by default)
|
package/src/bin.js
CHANGED
|
@@ -29,6 +29,7 @@ const args = arg({
|
|
|
29
29
|
'--tolerate-empty-queues': Number,
|
|
30
30
|
'--stop-at-time': String,
|
|
31
31
|
'--stop-days': String,
|
|
32
|
+
'--wait-between-jobs': Number,
|
|
32
33
|
|
|
33
34
|
'--skip-cleanup': Boolean,
|
|
34
35
|
'--skip-render': Boolean,
|
|
@@ -48,6 +49,8 @@ const args = arg({
|
|
|
48
49
|
'--aerender-parameter': [String],
|
|
49
50
|
'--language': String,
|
|
50
51
|
|
|
52
|
+
'--handle-interruption': Boolean,
|
|
53
|
+
|
|
51
54
|
// Aliases
|
|
52
55
|
'-v': '--version',
|
|
53
56
|
'-t': '--tag-selector',
|
|
@@ -126,15 +129,15 @@ if (args['--help']) {
|
|
|
126
129
|
--tolerate-empty-queues worker will check an empty queue this many times before exiting (if that option has
|
|
127
130
|
been set using --exit-on-empty-queues). Defaults to zero. If specified will be used instead of
|
|
128
131
|
NEXRENDER_TOLERATE_EMPTY_QUEUES env variable
|
|
129
|
-
|
|
132
|
+
|
|
130
133
|
--stop-at-time worker will exit at the given time if given.
|
|
131
|
-
example: 5:00 will stop at 5 am local time.
|
|
132
|
-
|
|
134
|
+
example: 5:00 will stop at 5 am local time.
|
|
135
|
+
|
|
133
136
|
--stop-days comma separated list of weekdays when to stop. Must be used together with --stop-at-time
|
|
134
137
|
0 is sunday, 6 is saturday
|
|
135
138
|
example: --stop-at-time=5:00 stop-days=1,2,3,4,5
|
|
136
|
-
will stop at 5 am but not on weekend
|
|
137
|
-
|
|
139
|
+
will stop at 5 am but not on weekend
|
|
140
|
+
|
|
138
141
|
--no-license prevents creation of the ae_render_only_node.txt file (enabled by default),
|
|
139
142
|
which allows free usage of trial version of Adobe After Effects
|
|
140
143
|
|
|
@@ -152,6 +155,8 @@ if (args['--help']) {
|
|
|
152
155
|
--polling amount of miliseconds to wait before checking queued projects from the api,
|
|
153
156
|
if specified will be used instead of NEXRENDER_API_POLLING env variable
|
|
154
157
|
|
|
158
|
+
--wait-between-jobs amount of miliseconds to wait before checking queued projects from the api
|
|
159
|
+
|
|
155
160
|
--header Define custom header that the worker will use to communicate with nexrender-server.
|
|
156
161
|
Accepted format follows curl or wget request header definition,
|
|
157
162
|
eg. --header="Some-Custom-Header: myCustomValue".
|
|
@@ -178,8 +183,8 @@ if (args['--help']) {
|
|
|
178
183
|
--aerender-parameter, --ae forward parameter to aerender (see Adobe site). Parameters with arguments have to be
|
|
179
184
|
enclosed in single quotes. For example:
|
|
180
185
|
nexrender --aerender-parameter 'close SAVE_CHANGES' --ae 'i 10' job.json
|
|
181
|
-
|
|
182
|
-
--language language of local after effects installation. currently only en and de are supported
|
|
186
|
+
|
|
187
|
+
--language language of local after effects installation. currently only en and de are supported
|
|
183
188
|
|
|
184
189
|
|
|
185
190
|
{bold ENV VARS}
|
|
@@ -190,6 +195,7 @@ if (args['--help']) {
|
|
|
190
195
|
|
|
191
196
|
{bold $} NEXRENDER_API_POLLING=1000 {cyan nexrender-worker}
|
|
192
197
|
`);
|
|
198
|
+
|
|
193
199
|
process.exit(2);
|
|
194
200
|
}
|
|
195
201
|
|
|
@@ -234,6 +240,7 @@ opt('tolerateEmptyQueues', '--tolerate-empty-queues');
|
|
|
234
240
|
opt('exitOnEmptyQueue', '--exit-on-empty-queue');
|
|
235
241
|
opt('stopAtTime', '--stop-at-time');
|
|
236
242
|
opt('stopDays', '--stop-days');
|
|
243
|
+
opt('waitBetweenJobs', '--wait-between-jobs');
|
|
237
244
|
opt('maxMemoryPercent', '--max-memory-percent');
|
|
238
245
|
opt('imageCachePercent', '--image-cache-percent');
|
|
239
246
|
opt('polling', '--polling');
|
|
@@ -241,6 +248,7 @@ opt('wslMap', '--wsl-map');
|
|
|
241
248
|
opt('aeParams', '--aerender-parameter');
|
|
242
249
|
opt('tagSelector', '--tag-selector');
|
|
243
250
|
opt('language', '--language');
|
|
251
|
+
opt('handleInterruption', '--handle-interruption');
|
|
244
252
|
|
|
245
253
|
if(args['--cache-path']){
|
|
246
254
|
opt('cache', '--cache-path');
|
package/src/instance.js
CHANGED
|
@@ -13,13 +13,32 @@ const createWorker = () => {
|
|
|
13
13
|
let active = false;
|
|
14
14
|
let settingsRef = null;
|
|
15
15
|
let stop_datetime = null;
|
|
16
|
+
let currentJob = null;
|
|
17
|
+
let client = null;
|
|
18
|
+
|
|
19
|
+
// New function to handle interruption
|
|
20
|
+
const handleInterruption = async () => {
|
|
21
|
+
if (currentJob) {
|
|
22
|
+
settingsRef.logger.log(`[${currentJob.uid}] Interruption signal received. Updating job state to 'queued'...`);
|
|
23
|
+
currentJob.onRenderProgress = null;
|
|
24
|
+
currentJob.state = 'queued';
|
|
25
|
+
try {
|
|
26
|
+
await client.updateJob(currentJob.uid, getRenderingStatus(currentJob));
|
|
27
|
+
settingsRef.logger.log(`[${currentJob.uid}] Job state updated to 'queued' successfully.`);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
settingsRef.logger.error(`[${currentJob.uid}] Failed to update job state: ${err.message}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
active = false;
|
|
33
|
+
process.exit(0);
|
|
34
|
+
};
|
|
16
35
|
|
|
17
36
|
const nextJob = async (client, settings) => {
|
|
18
37
|
do {
|
|
19
38
|
try {
|
|
20
39
|
if (stop_datetime !== null && new Date() > stop_datetime) {
|
|
21
40
|
active = false;
|
|
22
|
-
return
|
|
41
|
+
return null
|
|
23
42
|
}
|
|
24
43
|
|
|
25
44
|
let job = await (settings.tagSelector ?
|
|
@@ -63,6 +82,7 @@ const createWorker = () => {
|
|
|
63
82
|
process: 'nexrender-worker',
|
|
64
83
|
stopOnError: false,
|
|
65
84
|
logger: console,
|
|
85
|
+
handleInterruption: false,
|
|
66
86
|
}, settings))
|
|
67
87
|
|
|
68
88
|
settingsRef = settings;
|
|
@@ -85,7 +105,7 @@ const createWorker = () => {
|
|
|
85
105
|
headers = headers || {};
|
|
86
106
|
headers['user-agent'] = ('nexrender-worker/' + pkg.version + ' ' + (headers['user-agent'] || '')).trim();
|
|
87
107
|
|
|
88
|
-
|
|
108
|
+
client = createClient({ host, secret, headers, name: settings.name });
|
|
89
109
|
|
|
90
110
|
settings.track('Worker Started', {
|
|
91
111
|
worker_tags_set: !!settings.tagSelector,
|
|
@@ -114,95 +134,111 @@ const createWorker = () => {
|
|
|
114
134
|
}
|
|
115
135
|
}
|
|
116
136
|
|
|
117
|
-
|
|
137
|
+
// Set up interruption handlers if enabled
|
|
138
|
+
if (settings.handleInterruption) {
|
|
139
|
+
process.on('SIGINT', handleInterruption);
|
|
140
|
+
process.on('SIGTERM', handleInterruption);
|
|
141
|
+
settingsRef.logger.log('Interruption handling enabled.');
|
|
142
|
+
}
|
|
118
143
|
|
|
119
|
-
|
|
144
|
+
do {
|
|
145
|
+
currentJob = await nextJob(client, settings);
|
|
120
146
|
|
|
121
147
|
// if the worker has been deactivated, exit this loop
|
|
122
148
|
if (!active) break;
|
|
123
149
|
|
|
124
150
|
settings.track('Worker Job Started', {
|
|
125
|
-
job_id:
|
|
151
|
+
job_id: currentJob.uid, // anonymized internally
|
|
126
152
|
})
|
|
127
153
|
|
|
128
|
-
|
|
129
|
-
|
|
154
|
+
currentJob.state = 'started';
|
|
155
|
+
currentJob.startedAt = new Date()
|
|
130
156
|
|
|
131
157
|
try {
|
|
132
|
-
await client.updateJob(
|
|
158
|
+
await client.updateJob(currentJob.uid, currentJob)
|
|
133
159
|
} catch (err) {
|
|
134
|
-
console.log(`[${
|
|
135
|
-
console.log(`[${
|
|
160
|
+
console.log(`[${currentJob.uid}] error while updating job state to ${currentJob.state}. Job abandoned.`)
|
|
161
|
+
console.log(`[${currentJob.uid}] error stack: ${err.stack}`)
|
|
136
162
|
continue;
|
|
137
163
|
}
|
|
138
164
|
|
|
139
165
|
try {
|
|
140
|
-
|
|
166
|
+
currentJob.onRenderProgress = (currentJob) => {
|
|
141
167
|
try {
|
|
142
168
|
/* send render progress to our server */
|
|
143
|
-
client.updateJob(
|
|
169
|
+
client.updateJob(currentJob.uid, getRenderingStatus(currentJob));
|
|
144
170
|
|
|
145
171
|
if (settings.onRenderProgress) {
|
|
146
|
-
settings.onRenderProgress(
|
|
172
|
+
settings.onRenderProgress(currentJob);
|
|
147
173
|
}
|
|
148
174
|
} catch (err) {
|
|
149
175
|
if (settings.stopOnError) {
|
|
150
176
|
throw err;
|
|
151
177
|
} else {
|
|
152
|
-
console.log(`[${
|
|
153
|
-
console.log(`[${
|
|
154
|
-
console.log(`[${
|
|
178
|
+
console.log(`[${currentJob.uid}] error occurred: ${err.stack}`)
|
|
179
|
+
console.log(`[${currentJob.uid}] render proccess stopped with error...`)
|
|
180
|
+
console.log(`[${currentJob.uid}] continue listening next job...`)
|
|
155
181
|
}
|
|
156
182
|
}
|
|
157
183
|
}
|
|
158
184
|
|
|
159
|
-
|
|
160
|
-
|
|
185
|
+
currentJob.onRenderError = (currentJob, err /* on render error */) => {
|
|
186
|
+
currentJob.error = [].concat(currentJob.error || [], [err.toString()]);
|
|
161
187
|
|
|
162
188
|
if (settings.onRenderError) {
|
|
163
|
-
settings.onRenderError(
|
|
189
|
+
settings.onRenderError(currentJob, err);
|
|
164
190
|
}
|
|
165
191
|
}
|
|
166
192
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
193
|
+
currentJob = await render(currentJob, settings); {
|
|
194
|
+
currentJob.state = 'finished';
|
|
195
|
+
currentJob.finishedAt = new Date();
|
|
170
196
|
if (settings.onFinished) {
|
|
171
|
-
settings.onFinished(
|
|
197
|
+
settings.onFinished(currentJob);
|
|
172
198
|
}
|
|
173
199
|
}
|
|
174
200
|
|
|
175
|
-
settings.track('Worker Job Finished', { job_id:
|
|
201
|
+
settings.track('Worker Job Finished', { job_id: currentJob.uid })
|
|
176
202
|
|
|
177
|
-
await client.updateJob(
|
|
203
|
+
await client.updateJob(currentJob.uid, getRenderingStatus(currentJob))
|
|
178
204
|
} catch (err) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
205
|
+
currentJob.error = [].concat(currentJob.error || [], [err.toString()]);
|
|
206
|
+
currentJob.errorAt = new Date();
|
|
207
|
+
currentJob.state = 'error';
|
|
182
208
|
|
|
183
|
-
settings.track('Worker Job Error', { job_id:
|
|
209
|
+
settings.track('Worker Job Error', { job_id: currentJob.uid });
|
|
184
210
|
|
|
185
211
|
if (settings.onError) {
|
|
186
|
-
settings.onError(
|
|
212
|
+
settings.onError(currentJob, err);
|
|
187
213
|
}
|
|
188
214
|
|
|
189
215
|
try {
|
|
190
|
-
await client.updateJob(
|
|
216
|
+
await client.updateJob(currentJob.uid, getRenderingStatus(currentJob))
|
|
191
217
|
}
|
|
192
218
|
catch (e) {
|
|
193
|
-
console.log(`[${
|
|
194
|
-
console.log(`[${
|
|
219
|
+
console.log(`[${currentJob.uid}] error while updating job state to ${currentJob.state}. Job abandoned.`)
|
|
220
|
+
console.log(`[${currentJob.uid}] error stack: ${e.stack}`)
|
|
195
221
|
}
|
|
196
222
|
|
|
197
223
|
if (settings.stopOnError) {
|
|
198
224
|
throw err;
|
|
199
225
|
} else {
|
|
200
|
-
console.log(`[${
|
|
201
|
-
console.log(`[${
|
|
202
|
-
console.log(`[${
|
|
226
|
+
console.log(`[${currentJob.uid}] error occurred: ${err.stack}`)
|
|
227
|
+
console.log(`[${currentJob.uid}] render proccess stopped with error...`)
|
|
228
|
+
console.log(`[${currentJob.uid}] continue listening next job...`)
|
|
203
229
|
}
|
|
204
230
|
}
|
|
231
|
+
|
|
232
|
+
if (settings.waitBetweenJobs) {
|
|
233
|
+
await delay(settings.waitBetweenJobs);
|
|
234
|
+
}
|
|
205
235
|
} while (active)
|
|
236
|
+
|
|
237
|
+
// Clean up interruption handlers
|
|
238
|
+
if (settings.handleInterruption) {
|
|
239
|
+
process.removeListener('SIGINT', handleInterruption);
|
|
240
|
+
process.removeListener('SIGTERM', handleInterruption);
|
|
241
|
+
}
|
|
206
242
|
}
|
|
207
243
|
|
|
208
244
|
/**
|