mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-14 12:15:29 +02:00
Preserve the original contributor histories and apply the exact independently reviewed repair.
Source-Parent: 5785183108
Review-Manifest-SHA256: e223d98c24e357715527b786257901d2ef0bebadb75ac61e5c000fe60da10f9a
58 lines
2.3 KiB
JavaScript
58 lines
2.3 KiB
JavaScript
'use strict';
|
|
|
|
const path = require('path');
|
|
const { Worker } = require('worker_threads');
|
|
|
|
const MAX_ACTIVE_MUTATIONS = 2;
|
|
let activeMutations = 0;
|
|
|
|
/** Bound workers in this loaded runner/isolate; reject excess work without queuing. */
|
|
function runWorkItemMutation(dbPath, action, args) {
|
|
return new Promise((resolve, reject) => {
|
|
if (activeMutations >= MAX_ACTIVE_MUTATIONS) {
|
|
reject(Object.assign(new Error('Too many work-item mutations are running. Retry after an operation finishes.'),
|
|
{ code: 'STATE_STORE_BUSY' }));
|
|
return;
|
|
}
|
|
activeMutations += 1;
|
|
let worker;
|
|
try {
|
|
worker = new Worker(path.join(__dirname, 'work-item-worker.js'), {
|
|
workerData: { dbPath, action, args }
|
|
});
|
|
} catch (error) {
|
|
activeMutations -= 1;
|
|
reject(error);
|
|
return;
|
|
}
|
|
let response;
|
|
let workerError;
|
|
let failed = false;
|
|
worker.once('message', message => { response = message; });
|
|
worker.once('error', error => { failed = true; workerError = error; });
|
|
worker.once('exit', code => {
|
|
// Keep the slot until the thread is gone, even after a message/error.
|
|
activeMutations -= 1;
|
|
if (failed) { reject(workerError); return; }
|
|
if (code !== 0 || response === undefined) {
|
|
reject(new Error(`Work-item worker exited without a successful result (${code})`));
|
|
return;
|
|
}
|
|
// Worker messages are structured clones from our own helper, but malformed
|
|
// results still must reject instead of throwing outside the Promise executor.
|
|
if (!response || typeof response !== 'object' || Array.isArray(response)
|
|
|| typeof response.ok !== 'boolean'
|
|
|| (response.ok === false && (!response.error || typeof response.error !== 'object'
|
|
|| typeof response.error.message !== 'string'
|
|
|| (response.error.code !== undefined && typeof response.error.code !== 'string')))) {
|
|
reject(new Error('Invalid work-item worker response'));
|
|
} else if (response.ok) resolve(response.result);
|
|
else reject(Object.assign(new Error(response.error.message), { code: response.error.code }));
|
|
});
|
|
// Let the worker exit naturally after closing the store. Terminating it on
|
|
// a client disconnect could interrupt a write and abandon its file lock.
|
|
});
|
|
}
|
|
|
|
module.exports = { runWorkItemMutation };
|