Persist offer assistant jobs and recover results across closed views
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import {claimAiJob,heartbeatAiJob,finishAiJob} from './ai-job-store.mjs';
|
||||
|
||||
export function startAiJobRunner(execute,{intervalMs=2000,concurrency=2}={}) {
|
||||
const active=new Map();let stopped=false;
|
||||
async function run(job) {
|
||||
const controller=new AbortController();active.set(job.id,controller);
|
||||
const heartbeat=setInterval(()=>{
|
||||
try {if(!heartbeatAiJob(job.id,job.runId))controller.abort();}catch {controller.abort();}
|
||||
},10000);
|
||||
const timeout=setTimeout(()=>controller.abort(new Error('AI işi süre sınırına ulaştı. Yeniden deneyin.')),30*60*1000);
|
||||
try {
|
||||
const result=await execute(job,{signal:controller.signal});
|
||||
controller.signal.throwIfAborted();
|
||||
finishAiJob(job.id,job.runId,result);
|
||||
}catch(error){
|
||||
try {finishAiJob(job.id,job.runId,null,String(error.message || 'AI işi tamamlanamadı.'));}catch { /* lease expiry exposes interrupted work */ }
|
||||
}finally {clearInterval(heartbeat);clearTimeout(timeout);active.delete(job.id);}
|
||||
}
|
||||
const tick=()=>{
|
||||
if(stopped)return;
|
||||
try {while(active.size<concurrency){const job=claimAiJob();if(!job)break;void run(job);}}
|
||||
catch { /* keep durable work queued until the store is available */ }
|
||||
};
|
||||
const timer=setInterval(tick,intervalMs);timer.unref();
|
||||
return {wake:tick,cancel:id=>active.get(id)?.abort(),stop:()=>{stopped=true;clearInterval(timer);for(const controller of active.values())controller.abort();}};
|
||||
}
|
||||
Reference in New Issue
Block a user