Record stdout and stderr from the worker. Add a more detailed example

This commit is contained in:
2020-11-02 12:03:44 +00:00
parent 56ab028762
commit 4e1377241f
3 changed files with 88 additions and 11 deletions

View File

@@ -1,3 +1,4 @@
const dotenv = require('dotenv')
const EventEmitter = require('events') const EventEmitter = require('events')
const threads = require('worker_threads') const threads = require('worker_threads')
const path = require('path') const path = require('path')
@@ -6,6 +7,8 @@ const fs = require('fs')
const Exceptions = require('./exceptions.js') const Exceptions = require('./exceptions.js')
const CalcTask = require('./CalcTask.js') const CalcTask = require('./CalcTask.js')
dotenv.config()
// Basic utility functions to help the queue manager // Basic utility functions to help the queue manager
const CalcQueueUtils = { const CalcQueueUtils = {
getCalcWorker: function(calcFn) { getCalcWorker: function(calcFn) {
@@ -28,8 +31,21 @@ const CalcQueueUtils = {
const task = this.queue.shift() const task = this.queue.shift()
task._worker = new threads.Worker(task.workerPath()) task._worker = new threads.Worker(
task.workerPath(),
{
stderr: true,
stdout: true,
workerData: { 'id': task._id }
}
)
task._worker.stdout.on('data', (chunk) => {
task._stdout = task._stdout.concat(chunk)
})
task._worker.stderr.on('data', (chunk) => {
task._stderr = task._stderr.concat(chunk)
})
task._worker.on('message', (msg) => { task._worker.on('message', (msg) => {
task._messages.push(msg) task._messages.push(msg)
}) })
@@ -97,8 +113,19 @@ CalcQueue.prototype = {
'id': q.id(), 'id': q.id(),
'calcFn': q.calcFn(), 'calcFn': q.calcFn(),
'result': q.result(), 'result': q.result(),
'stdout': q.stdout().trim().split('\n'),
'stderr': q.stderr().trim().split('\n'),
'messages': q.messages(), 'messages': q.messages(),
'error': (q.error() == null ? null : q.error().message) 'error': (
q.error() == null
? null
: q.error().name + ': ' + q.error().message
),
'errorStack': (
process.env.NODE_ENV !== 'development' || q.error() == null
? null
: q.error().stack.split('\n')
)
} }
}) })
}, },

View File

@@ -12,6 +12,8 @@ const CalcTask = function(id, calcFn, workerPath) {
this._calcFn = calcFn this._calcFn = calcFn
this._workerPath = workerPath this._workerPath = workerPath
this._result = null this._result = null
this._stderr = ''
this._stdout = ''
this._messages = [] this._messages = []
this._error = null this._error = null
this._worker = null this._worker = null
@@ -36,6 +38,12 @@ CalcTask.prototype = {
return this._result != null return this._result != null
}, },
stdout: function() {
return this._stdout
},
stderr: function() {
return this._stderr
},
messages: function() { messages: function() {
return this._messages return this._messages
}, },

View File

@@ -1,15 +1,57 @@
const threads = require('worker_threads')
console.log('This is an example worker') // Worker task info
/* maxParallel: [0,1,n] 0 = auto (usually nproc), 1 = single instance,
* n = max 'n' instances
* shareParallel: [true/false] indicates if the worker can be run in parallel
* with other workers.
* usesGPU: [true/false] indicates if the worker requires the GPU
*/
const taskInfo = {
maxParallel: 0,
shareParallel: true,
usesGPU: false
}
new Promise((resolve, reject) => { // The task to be run
const task = function() {
console.log('This is an example worker')
console.log('This is the data from the calling thread:')
console.log(threads.workerData)
threads.parentPort.postMessage('This is a message')
threads.parentPort.postMessage({
color: 'red',
text: '$color is my favourite'
})
new Promise((resolve, reject) => {
setTimeout((() => { setTimeout((() => {
console.log('I did something (nothing) for 5 seconds!'); console.log('I did something (nothing) for 5 seconds!');
resolve() resolve()
}).bind(this), 5000) }).bind(this), 5000)
}) })
new Promise((resolve, reject) => {
setTimeout((() => {
console.error('This is an error message after 6 seconds!');
resolve()
}).bind(this), 6000)
})
new Promise((resolve, reject) => {
setTimeout((() => {
throw new Error('Exceptions in the worker are logged in the parent')
}).bind(this), 7000)
})
}
if (!module.parent) { if (!module.parent) {
console.log('not a module') if (!threads.isMainThread) {
task()
}
} else { } else {
console.log('loaded as a module') module.exports = taskInfo
module.task = task
} }