Persist offer assistant jobs and recover results across closed views
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import test,{after} from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {mkdtempSync,rmSync} from 'node:fs';
|
||||
import {join} from 'node:path';
|
||||
import {tmpdir} from 'node:os';
|
||||
const dir=mkdtempSync(join(tmpdir(),'ihaleist-jobs-'));process.env.IHALEIST_USER_DATA_DIR=dir;
|
||||
const jobs=await import('../server/ai-job-store.mjs');
|
||||
after(()=>rmSync(dir,{recursive:true,force:true}));
|
||||
test('durable jobs are idempotent and account scoped',()=>{
|
||||
const first=jobs.createAiJob('a','request-1','teklif-denetim',{ikn:'2026/1',taslak:'private'});
|
||||
assert.equal(jobs.createAiJob('a','request-1','teklif-denetim',{ikn:'2026/1',taslak:'private'}).id,first.id);
|
||||
assert.throws(()=>jobs.createAiJob('a','request-1','teklif-denetim',{taslak:'other'}),/farklı kaynak/);
|
||||
assert.equal(jobs.getAiJob('b',first.id),null);assert.deepEqual(jobs.listAiJobs('b'),[]);
|
||||
assert.equal(jobs.cancelAiJob('b',first.id),false);
|
||||
const claimed=jobs.claimAiJob();assert.equal(claimed.input.taslak,'private');
|
||||
assert.equal(jobs.finishAiJob(first.id,'wrong',{success:true}),false);
|
||||
assert.equal(jobs.finishAiJob(first.id,claimed.runId,{success:true,answer:'done'}),true);
|
||||
assert.equal(jobs.getAiJob('a',first.id).result.answer,'done');
|
||||
assert.equal(jobs.getAiJob('a',first.id).input.taslak,'private');
|
||||
assert.equal(jobs.listAiJobs('a')[0].input,undefined);
|
||||
});
|
||||
test('lost workers become interrupted without automatic provider replay; retry and cancellation reject late results',()=>{
|
||||
const first=jobs.createAiJob('a','request-2','teklif-taslak',{ikn:'2026/2'});
|
||||
const claimed=jobs.claimAiJob(Date.now()-120000);
|
||||
assert.equal(jobs.claimAiJob(),null);
|
||||
assert.equal(jobs.getAiJob('a',first.id).state,'interrupted');
|
||||
assert.equal(jobs.finishAiJob(first.id,claimed.runId,{success:true}),false);
|
||||
assert.equal(jobs.retryAiJob('a',first.id),true);
|
||||
const restarted=jobs.claimAiJob();assert.notEqual(restarted.runId,claimed.runId);
|
||||
assert.equal(jobs.cancelAiJob('a',first.id),true);
|
||||
assert.equal(jobs.heartbeatAiJob(first.id,restarted.runId),false);
|
||||
assert.equal(jobs.finishAiJob(first.id,restarted.runId,{success:true}),false);
|
||||
assert.equal(jobs.getAiJob('a',first.id).state,'cancelled');
|
||||
});
|
||||
|
||||
test('runner stores results independently of an HTTP connection',async()=>{
|
||||
const {startAiJobRunner}=await import('../server/ai-job-runner.mjs');
|
||||
const job=jobs.createAiJob('runner','request-run','belge-sor',{ikn:'2026/8',soru:'teslim'});
|
||||
let finish;
|
||||
const runner=startAiJobRunner(async()=>new Promise(resolve=>{finish=resolve;}),{intervalMs:100000});
|
||||
try {
|
||||
runner.wake();assert.equal(jobs.getAiJob('runner',job.id).state,'running');
|
||||
finish({success:true,cevap:'Stored answer'});
|
||||
await new Promise(resolve=>setImmediate(resolve));
|
||||
assert.equal(jobs.getAiJob('runner',job.id).result.cevap,'Stored answer');
|
||||
} finally {runner.stop();}
|
||||
});
|
||||
Reference in New Issue
Block a user