Pin durable AI source text and requirements across retries
This commit is contained in:
@@ -45,3 +45,41 @@ test('runner stores results independently of an HTTP connection',async()=>{
|
||||
assert.equal(jobs.getAiJob('runner',job.id).result.cevap,'Stored answer');
|
||||
} finally {runner.stop();}
|
||||
});
|
||||
|
||||
test('resolved source survives retry and preserves original idempotency and ownership',async()=>{
|
||||
const {resolveAiJobInput}=await import('../server/ai-job-source.mjs');
|
||||
const original={ikn:'2026/99',soru:'teslim',resolvedSource:{text:'untrusted'}};
|
||||
const created=jobs.createAiJob('source-owner','request-source','belge-sor',original);
|
||||
const worker=jobs.claimAiJob();let calls=0;
|
||||
const resolved=await resolveAiJobInput(worker,async()=>{calls++;return {text:'Source A',kaynak:'ilan metni'};},jobs.pinAiJobInput,undefined,()=>['Kalem A']);
|
||||
assert.deepEqual(resolved.gereklilikler,['Kalem A']);assert.equal(resolved.text,'Source A');assert.equal(resolved.resolvedSource.kaynak,'ilan metni');
|
||||
assert.equal(resolved.resolvedSource.hash.length,64);
|
||||
assert.equal(jobs.pinAiJobInput(worker.id,worker.runId,{text:'replacement'}),false);
|
||||
jobs.finishAiJob(worker.id,worker.runId,null,'provider failed');
|
||||
assert.equal(jobs.createAiJob('source-owner','request-source','belge-sor',original).id,created.id);
|
||||
assert.equal(jobs.getAiJob('other-owner',created.id),null);
|
||||
assert.equal(jobs.retryAiJob('source-owner',created.id),true);
|
||||
const next=jobs.claimAiJob();
|
||||
const reused=await resolveAiJobInput(next,async()=>{calls++;return {text:'Source B'};},jobs.pinAiJobInput);
|
||||
assert.equal(calls,1);assert.deepEqual(reused,resolved);
|
||||
assert.deepEqual(jobs.getAiJob('source-owner',created.id).input,resolved);
|
||||
jobs.cancelAiJob('source-owner',created.id);
|
||||
});
|
||||
|
||||
test('cancel during source fetch rejects late source, and empty resolution remains explicit',async()=>{
|
||||
const {resolveAiJobInput}=await import('../server/ai-job-source.mjs');
|
||||
const created=jobs.createAiJob('source-owner','request-cancel-source','teklif-taslak',{});
|
||||
const worker=jobs.claimAiJob();
|
||||
await assert.rejects(resolveAiJobInput(worker,async()=>{
|
||||
jobs.cancelAiJob('source-owner',created.id);return {text:'late source'};
|
||||
},jobs.pinAiJobInput),/artık etkin değil/);
|
||||
assert.deepEqual(jobs.getAiJob('source-owner',created.id).input,{});
|
||||
const empty=jobs.createAiJob('source-owner','request-empty-source','teklif-taslak',{});
|
||||
const emptyWorker=jobs.claimAiJob();
|
||||
const input=await resolveAiJobInput(emptyWorker,async()=>({text:'',kaynak:null}),jobs.pinAiJobInput);
|
||||
assert.equal(input.resolvedSource.text,'');assert.equal(input.resolvedSource.kaynak,null);
|
||||
jobs.finishAiJob(empty.id,emptyWorker.runId,null,'failed');jobs.retryAiJob('source-owner',empty.id);
|
||||
const retry=jobs.claimAiJob();
|
||||
assert.deepEqual(await resolveAiJobInput(retry,()=>assert.fail('must not refetch'),jobs.pinAiJobInput),input);
|
||||
jobs.cancelAiJob('source-owner',empty.id);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user