@nexrender/worker 1.49.4 → 1.50.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexrender/worker",
3
- "version": "1.49.4",
3
+ "version": "1.50.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": "7dfa1bf539d3a9d006a987ca7dbb59e4454bbaba"
32
+ "gitHead": "92724ffcf4f03a368007c137c216534306f05d85"
33
33
  }
package/src/index.js CHANGED
@@ -1,178 +1,5 @@
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')
1
+ const { createWorker } = require('./instance')
5
2
 
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
- var emptyReturns = 0;
3
+ const instance = createWorker()
9
4
 
10
- /* TODO: possibly add support for graceful shutdown */
11
- let active = true;
12
-
13
- const delay = amount => (
14
- new Promise(resolve => setTimeout(resolve, amount))
15
- )
16
-
17
- const nextJob = async (client, settings) => {
18
- do {
19
- try {
20
- let job = await (settings.tagSelector ?
21
- await client.pickupJob(settings.tagSelector) :
22
- await client.pickupJob()
23
- );
24
-
25
- if (job && job.uid) {
26
- emptyReturns = 0;
27
- return job
28
- } else {
29
- // no job was returned by the server. If enough checks have passed, and the exit option is set, deactivate the worker
30
- emptyReturns++;
31
- if (settings.exitOnEmptyQueue && emptyReturns > settings.tolerateEmptyQueues) active = false;
32
- }
33
-
34
- } catch (err) {
35
- if (settings.stopOnError) {
36
- throw err;
37
- } else {
38
- console.error(err)
39
- console.error("render proccess stopped with error...")
40
- console.error("continue listening next job...")
41
- }
42
- }
43
-
44
- if (active) await delay(settings.polling || NEXRENDER_API_POLLING)
45
- } while (active)
46
- }
47
-
48
- /**
49
- * Starts worker "thread" of continious loop
50
- * of fetching queued projects and rendering them
51
- * @param {String} host
52
- * @param {String} secret
53
- * @param {Object} settings
54
- * @return {Promise}
55
- */
56
- const start = async (host, secret, settings, headers) => {
57
- settings = init(Object.assign({ process: 'nexrender-worker' }, settings, {
58
- logger: console,
59
- }))
60
-
61
- settings.logger.log('starting nexrender-worker with following settings:')
62
- Object.keys(settings).forEach(key => {
63
- settings.logger.log(` - ${key}: ${settings[key]}`)
64
- })
65
-
66
- if (typeof settings.tagSelector == 'string') {
67
- settings.tagSelector = settings.tagSelector.replace(/[^a-z0-9, ]/gi, '')
68
- }
69
- // if there is no setting for how many empty queues to tolerate, make one from the
70
- // environment variable, or the default (which is zero)
71
- if (!(typeof settings.tolerateEmptyQueues == 'number')) {
72
- settings.tolerateEmptyQueues = NEXRENDER_TOLERATE_EMPTY_QUEUES;
73
- }
74
-
75
- headers = headers || {};
76
- headers['user-agent'] = ('nexrender-worker/' + pkg.version + ' ' + (headers['user-agent'] || '')).trim();
77
-
78
- const client = createClient({ host, secret, headers, name: settings.name });
79
-
80
- settings.track('Worker Started', {
81
- worker_tags_set: !!settings.tagSelector,
82
- worker_setting_tolerate_empty_queues: settings.tolerateEmptyQueues,
83
- worker_setting_exit_on_empty_queue: settings.exitOnEmptyQueue,
84
- worker_setting_polling: settings.polling,
85
- worker_setting_stop_on_error: settings.stopOnError,
86
- })
87
-
88
- do {
89
- let job = await nextJob(client, settings);
90
-
91
- // if the worker has been deactivated, exit this loop
92
- if (!active) break;
93
-
94
- settings.track('Worker Job Started', {
95
- job_id: job.uid, // anonymized internally
96
- })
97
-
98
- job.state = 'started';
99
- job.startedAt = new Date()
100
-
101
- try {
102
- await client.updateJob(job.uid, job)
103
- } catch (err) {
104
- console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
105
- console.log(`[${job.uid}] error stack: ${err.stack}`)
106
- continue;
107
- }
108
-
109
- try {
110
- job.onRenderProgress = (job) => {
111
- try {
112
- /* send render progress to our server */
113
- client.updateJob(job.uid, getRenderingStatus(job));
114
-
115
- if (settings.onRenderProgress) {
116
- settings.onRenderProgress(job);
117
- }
118
- } catch (err) {
119
- if (settings.stopOnError) {
120
- throw err;
121
- } else {
122
- console.log(`[${job.uid}] error occurred: ${err.stack}`)
123
- console.log(`[${job.uid}] render proccess stopped with error...`)
124
- console.log(`[${job.uid}] continue listening next job...`)
125
- }
126
- }
127
- }
128
-
129
- job.onRenderError = (job, err /* on render error */) => {
130
- job.error = [].concat(job.error || [], [err.toString()]);
131
-
132
- if (settings.onRenderError) {
133
- settings.onRenderError(job, err);
134
- }
135
- }
136
-
137
- job = await render(job, settings); {
138
- job.state = 'finished';
139
- job.finishedAt = new Date();
140
- if (settings.onFinished) {
141
- settings.onFinished(job);
142
- }
143
- }
144
-
145
- settings.track('Worker Job Finished', { job_id: job.uid })
146
-
147
- await client.updateJob(job.uid, getRenderingStatus(job))
148
- } catch (err) {
149
- job.error = [].concat(job.error || [], [err.toString()]);
150
- job.errorAt = new Date();
151
- job.state = 'error';
152
-
153
- settings.track('Worker Job Error', { job_id: job.uid });
154
-
155
- if (settings.onError) {
156
- settings.onError(job, err);
157
- }
158
-
159
- try {
160
- await client.updateJob(job.uid, getRenderingStatus(job))
161
- }
162
- catch (e) {
163
- console.log(`[${job.uid}] error while updating job state to ${job.state}. Job abandoned.`)
164
- console.log(`[${job.uid}] error stack: ${e.stack}`)
165
- }
166
-
167
- if (settings.stopOnError) {
168
- throw err;
169
- } else {
170
- console.log(`[${job.uid}] error occurred: ${err.stack}`)
171
- console.log(`[${job.uid}] render proccess stopped with error...`)
172
- console.log(`[${job.uid}] continue listening next job...`)
173
- }
174
- }
175
- } while (active)
176
- }
177
-
178
- module.exports = { start }
5
+ module.exports = instance
@@ -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 = 500;
1
+ process.env.NEXRENDER_API_POLLING = 1000
2
+ const {createWorker} = require('../src/instance')
2
3
 
3
- const { nextJob } = require('../src')
4
+ const instance1 = createWorker()
5
+ const instance2 = createWorker()
6
+ const instance3 = createWorker()
4
7
 
5
- let i = 0;
6
- const listJobs = async () => {
7
- console.log('listJobs')
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
- const client = { listJobs }
15
-
16
- const foo = async () => {
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)