Comparing version 0.0.5 to 0.1.0
{ | ||
"name": "microjob", | ||
"version": "0.0.5", | ||
"version": "0.1.0", | ||
"description": "A tiny wrapper for Node.js worker_threads lib", | ||
@@ -5,0 +5,0 @@ "main": "src/job.js", |
@@ -47,1 +47,7 @@ # Microjob | ||
Dive deep into the documentation to find more examples: **[API](API.md)** | ||
## Known Issues | ||
* **[sanitize worker context](API.md#job-context)** | ||
## Known Limitations | ||
* **[serialize worker data](API.md#job-data)** |
135
src/job.js
@@ -1,87 +0,80 @@ | ||
const { Worker } = require('worker_threads') | ||
const v8 = require('v8') | ||
const workerPool = require('./worker-pool') | ||
const MISSING_HANDLER_ERROR = `job needs a function.\nTry with:\n> job(() => {...}, config)` | ||
const WRONG_CONTEXT_ERROR = `job needs an object as ctx.\nTry with:\n> job(() => {...}, {ctx: {...}})` | ||
function job(handler, config = { ctx: {}, data: {} }) { | ||
return new Promise((resolve, reject) => { | ||
if (typeof handler !== 'function') return reject(new Error(MISSING_HANDLER_ERROR)) | ||
workerPool.on('tick', ({ work, worker }) => { | ||
const { handler, config, resolve, reject } = work | ||
try { | ||
let variables = '' | ||
for (const key in config.ctx) { | ||
if (!config.ctx.hasOwnProperty(key)) continue | ||
try { | ||
let variables = '' | ||
for (const key in config.ctx) { | ||
if (!config.ctx.hasOwnProperty(key)) continue | ||
let variable | ||
switch (typeof config.ctx[key]) { | ||
case 'string': | ||
variable = `'${config.ctx[key]}'` | ||
break | ||
case 'object': | ||
variable = JSON.stringify(config.ctx[key]) | ||
break | ||
default: | ||
variable = config.ctx[key] | ||
} | ||
variables += `let ${key} = ${variable}\n` | ||
let variable | ||
switch (typeof config.ctx[key]) { | ||
case 'string': | ||
variable = `'${config.ctx[key]}'` | ||
break | ||
case 'object': | ||
variable = JSON.stringify(config.ctx[key]) | ||
break | ||
default: | ||
variable = config.ctx[key] | ||
} | ||
variables += `let ${key} = ${variable}\n` | ||
} | ||
const workerStr = ` | ||
(async function () { | ||
const {parentPort, workerData} = require('worker_threads') | ||
${variables} | ||
const response = { | ||
err: null, | ||
data: null | ||
} | ||
try { | ||
response.data = await (${handler.toString()})(workerData) | ||
} catch (err) { | ||
response.error = { | ||
message: err.message, | ||
stack: err.stack | ||
} | ||
} | ||
const dataStr = JSON.stringify(config.data) | ||
const workerStr = ` | ||
async function __executor__() { | ||
${variables} | ||
return await (${handler.toString()})(JSON.parse('${dataStr}')) | ||
} | ||
` | ||
try { | ||
parentPort.postMessage(response) | ||
} catch (err) { | ||
response.data = null | ||
response.error = { | ||
message: err.message, | ||
stack: err.stack | ||
} | ||
parentPort.postMessage(response) | ||
} | ||
})() | ||
` | ||
// serialization precheck, due to this issue: https://github.com/nodejs/node/issues/22736 | ||
v8.serialize(config.data) | ||
// check for serialization's error, due to this issue: https://github.com/nodejs/node/issues/22736 | ||
v8.serialize(config.data) | ||
const worker = new Worker(workerStr, { | ||
eval: true, | ||
workerData: config.data | ||
}) | ||
worker.once('message', message => { | ||
workerPool.free(worker) | ||
worker.on('message', message => { | ||
if (message.error) { | ||
const error = new Error(message.error.message) | ||
error.stack = message.error.stack | ||
reject(error) | ||
} else resolve(message.data) | ||
if (typeof message.error === 'undefined' || message.error === null) return resolve(message.data) | ||
worker.unref() | ||
}) | ||
const error = new Error(message.error.message) | ||
error.stack = message.error.stack | ||
reject(error) | ||
}) | ||
worker.on('error', error => { | ||
reject(error) | ||
worker.unref() | ||
}) | ||
} catch (err) { | ||
reject(err) | ||
} | ||
worker.once('error', error => { | ||
workerPool.free(worker) | ||
reject(error) | ||
}) | ||
worker.postMessage(workerStr) | ||
} catch (err) { | ||
workerPool.free(worker) | ||
reject(err) | ||
} | ||
}) | ||
function job(handler, config = { ctx: {}, data: {} }) { | ||
return new Promise((resolve, reject) => { | ||
if (typeof handler !== 'function') return reject(new Error(MISSING_HANDLER_ERROR)) | ||
config.ctx = config.ctx || {} | ||
config.data = config.data || {} | ||
if (typeof config.ctx !== 'object') return reject(new Error(WRONG_CONTEXT_ERROR)) | ||
workerPool.enqueue({ handler, config, resolve, reject }) | ||
}) | ||
} | ||
module.exports = { job } | ||
function stop() { | ||
workerPool.teardown() | ||
} | ||
module.exports = { job, stop } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
8429
6
149
53
2