Comparing version 3.0.13 to 3.0.14
@@ -72,2 +72,6 @@ 'use strict'; | ||
worker.on('error', (error) => { | ||
impress.console.error(error.message); | ||
}); | ||
worker.on('exit', (code) => { | ||
@@ -104,17 +108,26 @@ if (code !== 0) startWorker(app, kind, port, id); | ||
invoke: async (msg) => { | ||
const { status, port, exclusive } = msg; | ||
if (status === 'done') return void app.pool.release(worker); | ||
const promisedThread = exclusive ? app.pool.capture() : app.pool.next(); | ||
const next = await promisedThread.catch(() => { | ||
const error = new Error('No thread available'); | ||
port.postMessage({ name: 'error', error }); | ||
const { from, to, exclusive } = msg; | ||
if (to) { | ||
const back = app.threads.get(to); | ||
return void back.postMessage(msg); | ||
} | ||
const promised = exclusive ? app.pool.capture() : app.pool.next(); | ||
const next = await promised.catch(() => { | ||
const error = { message: 'No thread available' }; | ||
const back = app.threads.get(from); | ||
const data = { id, status: 'error', error }; | ||
back.postMessage({ name: 'invoke', to: from, data }); | ||
return null; | ||
}); | ||
if (!next) return; | ||
next.postMessage(msg, [port]); | ||
next.postMessage(msg); | ||
}, | ||
terminate: (msg) => { | ||
process.emit('TERMINATE', msg.code); | ||
release: () => { | ||
app.pool.release(worker); | ||
}, | ||
terminate: ({ code }) => { | ||
process.emit('TERMINATE', code); | ||
}, | ||
}; | ||
@@ -121,0 +134,0 @@ |
@@ -118,3 +118,3 @@ 'use strict'; | ||
const { concurrency, size, timeout } = config.server.queue; | ||
this.semaphore = new Semaphore(concurrency, size, timeout); | ||
this.semaphore = new Semaphore({ concurrency, size, timeout }); | ||
this.initialization = false; | ||
@@ -121,0 +121,0 @@ sandbox.application.emit('started'); |
@@ -95,3 +95,5 @@ 'use strict'; | ||
node.fsp = node.fs.promises; | ||
node.timers.promises = require('node:timers/promises'); | ||
if (!node.timers.promises) { | ||
node.timers.promises = require('node:timers/promises'); | ||
} | ||
@@ -98,0 +100,0 @@ Object.freeze(node); |
'use strict'; | ||
const { node, metarhia, wt } = require('./deps.js'); | ||
const { Semaphore } = metarhia.metautil; | ||
@@ -144,3 +145,3 @@ class Planner { | ||
const { concurrency, size, timeout } = this.config; | ||
semaphore = new metarhia.metautil.Semaphore(concurrency, size, timeout); | ||
semaphore = new Semaphore({ concurrency, size, timeout }); | ||
this.topics.set(name, semaphore); | ||
@@ -147,0 +148,0 @@ } |
@@ -28,3 +28,3 @@ 'use strict'; | ||
const { Semaphore } = metarhia.metautil; | ||
this.semaphore = new Semaphore(concurrency, size, timeout); | ||
this.semaphore = new Semaphore({ concurrency, size, timeout }); | ||
} | ||
@@ -35,3 +35,4 @@ this.caption = exp.caption || ''; | ||
this.validate = exp.validate || null; | ||
this.timeout = exp.timeout || 0; | ||
const { timeouts } = application.config.server; | ||
this.timeout = (exp.timeout ?? timeouts.request) || 0; | ||
this.serializer = exp.serialize || null; | ||
@@ -46,3 +47,3 @@ this.protocols = exp.protocols || null; | ||
await this.application.semaphore.enter(); | ||
if (this.concurrency) { | ||
if (this.semaphore) { | ||
try { | ||
@@ -59,3 +60,3 @@ await this.semaphore.enter(); | ||
this.application.semaphore.leave(); | ||
if (this.concurrency) this.semaphore.leave(); | ||
if (this.semaphore) this.semaphore.leave(); | ||
} | ||
@@ -73,13 +74,5 @@ | ||
if (validate) await validate(args); | ||
let result; | ||
if (timeout) { | ||
const ac = new AbortController(); | ||
result = await Promise.race([ | ||
metarhia.metautil.timeout(timeout, ac.signal), | ||
method(args), | ||
]); | ||
ac.abort(); | ||
} else { | ||
result = await method(args); | ||
} | ||
let promise = method(args); | ||
if (timeout) promise = metarhia.metautil.timeoutify(promise, timeout); | ||
let result = await promise; | ||
if (metarhia.metautil.isError(result)) { | ||
@@ -86,0 +79,0 @@ if (result instanceof DomainError) result = result.toError(errors); |
'use strict'; | ||
const { node, metarhia, notLoaded, wt } = require('./deps.js'); | ||
const { MessageChannel, parentPort, threadId, workerData } = wt; | ||
const { parentPort, threadId, workerData } = wt; | ||
@@ -25,13 +25,17 @@ const application = require('./application.js'); | ||
let callId = 0; | ||
const calls = new Map(); | ||
const invoke = async ({ method, args, exclusive = false }) => { | ||
const { port1: port, port2 } = new MessageChannel(); | ||
const data = { method, args }; | ||
const msg = { name: 'invoke', exclusive, data, port }; | ||
const id = ++callId; | ||
const data = { type: 'call', id, method, args }; | ||
const msg = { name: 'invoke', from: threadId, exclusive, data }; | ||
return new Promise((resolve, reject) => { | ||
port2.on('message', ({ error, data }) => { | ||
port2.close(); | ||
const handler = ({ error, result }) => { | ||
calls.delete(id); | ||
if (error) reject(error); | ||
else resolve(data); | ||
}); | ||
parentPort.postMessage(msg, [port]); | ||
else resolve(result); | ||
}; | ||
calls.set(id, handler); | ||
parentPort.postMessage(msg); | ||
}); | ||
@@ -52,19 +56,32 @@ }; | ||
invoke: async ({ exclusive, data, port }) => { | ||
const { method, args } = data; | ||
const { sandbox } = application; | ||
invoke: async ({ from, to, exclusive, data }) => { | ||
if (to) { | ||
const { id, status, error, result } = data; | ||
const handler = calls.get(id); | ||
const err = status === 'error' ? new Error(error.message) : null; | ||
return void handler({ error: err, result }); | ||
} | ||
const { sandbox, config } = application; | ||
const msg = { name: 'invoke', to: from }; | ||
const { timeout } = config.server.workers; | ||
const { id, method, args } = data; | ||
const handler = metarhia.metautil.namespaceByPath(sandbox, method); | ||
if (!handler) { | ||
const error = new Error('Handler not found'); | ||
return void port.postMessage({ name: 'error', error }); | ||
const error = { message: 'Handler not found' }; | ||
const data = { id, status: 'error', error }; | ||
return void parentPort.postMessage({ ...msg, data }); | ||
} | ||
const msg = { name: 'invoke', status: 'done' }; | ||
try { | ||
const result = await handler(args); | ||
port.postMessage({ ...msg, data: result }); | ||
} catch (error) { | ||
port.postMessage({ name: 'error', error }); | ||
application.console.error(error.stack); | ||
let promise = handler(args); | ||
if (timeout) promise = metarhia.metautil.timeoutify(promise, timeout); | ||
const result = await promise; | ||
const data = { id, status: 'done', result }; | ||
parentPort.postMessage({ ...msg, data }); | ||
} catch (err) { | ||
const error = { message: err.message }; | ||
const data = { id, status: 'error', error }; | ||
parentPort.postMessage({ ...msg, data }); | ||
application.console.error(err.stack); | ||
} finally { | ||
if (exclusive) parentPort.postMessage(msg); | ||
if (exclusive) parentPort.postMessage({ name: 'release' }); | ||
} | ||
@@ -71,0 +88,0 @@ }, |
{ | ||
"name": "impress", | ||
"version": "3.0.13", | ||
"version": "3.0.14", | ||
"author": "Timur Shemsedinov <timur.shemsedinov@gmail.com>", | ||
@@ -54,3 +54,7 @@ "description": "Enterprise application server for Node.js", | ||
"types": "types/impress.d.ts", | ||
"files": ["lib/", "schemas/", "types/"], | ||
"files": [ | ||
"lib/", | ||
"schemas/", | ||
"types/" | ||
], | ||
"scripts": { | ||
@@ -63,25 +67,25 @@ "test": "npm run lint && npm run types && metatests test/", | ||
"engines": { | ||
"node": "18 || 20 || 21" | ||
"node": "^18.15 || 20 || 21" | ||
}, | ||
"dependencies": { | ||
"metacom": "^3.1.2", | ||
"metaconfiguration": "^2.1.11", | ||
"metalog": "^3.1.13", | ||
"metacom": "^3.2.1", | ||
"metaconfiguration": "^3.0.0", | ||
"metalog": "^3.1.14", | ||
"metaschema": "^2.1.5", | ||
"metautil": "^3.15.0", | ||
"metavm": "^1.4.0", | ||
"metawatch": "^1.1.1" | ||
"metautil": "^5.2.1", | ||
"metavm": "^1.4.1", | ||
"metawatch": "^1.2.1" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.5.0", | ||
"@types/ws": "^8.5.5", | ||
"eslint": "^8.47.0", | ||
"eslint-config-metarhia": "^8.2.1", | ||
"eslint-config-prettier": "^9.0.0", | ||
"eslint-plugin-import": "^2.28.0", | ||
"eslint-plugin-prettier": "^5.0.0", | ||
"@types/node": "^20.11.17", | ||
"@types/ws": "^8.5.10", | ||
"eslint": "^8.56.0", | ||
"eslint-config-metarhia": "^8.2.2", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"metatests": "^0.8.2", | ||
"prettier": "^3.0.1", | ||
"typescript": "^5.1.6" | ||
"prettier": "^3.2.5", | ||
"typescript": "^5.3.3" | ||
} | ||
} |
@@ -113,5 +113,5 @@ <div align="center"> | ||
Copyright (c) 2012-2023 Metarhia contributors. | ||
Copyright (c) 2012-2024 Metarhia contributors. | ||
See github for full [contributors list](https://github.com/metarhia/impress/graphs/contributors). | ||
Impress Application Server is [MIT licensed](./LICENSE). | ||
Project coordinator: <timur.shemsedinov@gmail.com> |
Sorry, the diff of this file is not supported yet
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
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
70106
1827
+ Addedmetaconfiguration@3.0.1(transitive)
- Removedmetaconfiguration@2.2.0(transitive)
- Removedmetautil@3.15.0(transitive)
Updatedmetacom@^3.2.1
Updatedmetaconfiguration@^3.0.0
Updatedmetalog@^3.1.14
Updatedmetautil@^5.2.1
Updatedmetavm@^1.4.1
Updatedmetawatch@^1.2.1