Record stdout and stderr from the worker. Add a more detailed example
This commit is contained in:
@@ -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')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,31 @@
|
|||||||
|
const threads = require('worker_threads')
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// The task to be run
|
||||||
|
const task = function() {
|
||||||
console.log('This is an example worker')
|
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) => {
|
new Promise((resolve, reject) => {
|
||||||
setTimeout((() => {
|
setTimeout((() => {
|
||||||
console.log('I did something (nothing) for 5 seconds!');
|
console.log('I did something (nothing) for 5 seconds!');
|
||||||
@@ -8,8 +33,25 @@ new Promise((resolve, reject) => {
|
|||||||
}).bind(this), 5000)
|
}).bind(this), 5000)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!module.parent) {
|
new Promise((resolve, reject) => {
|
||||||
console.log('not a module')
|
setTimeout((() => {
|
||||||
} else {
|
console.error('This is an error message after 6 seconds!');
|
||||||
console.log('loaded as a module')
|
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 (!threads.isMainThread) {
|
||||||
|
task()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
module.exports = taskInfo
|
||||||
|
module.task = task
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user