Files
safetynet/apps/network-broker/work-admission.cjs
T

31 lines
1.6 KiB
JavaScript

'use strict';
// A deadline race cannot stop an underlying worker. Keep its admission slot
// until its real promise settles; unresponsive work consumes capacity and
// subsequent work fails closed. Worker termination requires separate proof.
class WorkAdmissionError extends Error{
constructor(code){super(code);this.name='WorkAdmissionError';this.code=code;}
}
function createWorkAdmission({maxJobs=8}={}){
if(!Number.isSafeInteger(maxJobs)||maxJobs<1||maxJobs>64)throw new WorkAdmissionError('work_configuration_invalid');
let active=0,closed=false;
return Object.freeze({
run(fn,{payload}={}){
if(typeof fn!=='function'||(payload!==undefined&&!Buffer.isBuffer(payload)))throw new WorkAdmissionError('work_configuration_invalid');
if(closed){payload?.fill(0);throw new WorkAdmissionError('work_admission_closed');}
if(active>=maxJobs){payload?.fill(0);throw new WorkAdmissionError('work_capacity_exhausted');}
active++;
let settled=false;
const release=()=>{if(settled)return;settled=true;try{payload?.fill(0);}finally{active--;}};
try{
// The private payload is transferred to this admission job. Caller
// must not reuse it; scanner may use it until underlying settlement.
const result=fn();
return Promise.resolve(result).then(value=>{release();return value;},error=>{release();throw error;});
}catch(error){release();throw error;}
},
status:()=>Object.freeze({active,maxJobs,closed,available:closed?0:maxJobs-active}),
close(){closed=true;}
});
}
module.exports={createWorkAdmission,WorkAdmissionError};