Persist offer assistant jobs and recover results across closed views

This commit is contained in:
2026-09-06 12:35:30 +03:00
parent 2e16a68565
commit f830625b60
12 changed files with 297 additions and 3 deletions
+23
View File
@@ -0,0 +1,23 @@
import {accountRequest} from './accountRequest.js';
import {awaitWithAbort} from './abortable.js';
export const listAiJobs=ikn=>accountRequest('/api/me/ai-jobs?'+new URLSearchParams({ikn}));
export const getAiJob=id=>accountRequest('/api/me/ai-jobs?'+new URLSearchParams({id}));
export const cancelAiJob=id=>accountRequest('/api/me/ai-jobs?'+new URLSearchParams({id}),{method:'DELETE'});
export const retryAiJob=id=>accountRequest('/api/me/ai-jobs?'+new URLSearchParams({id}),{method:'POST',body:JSON.stringify({action:'retry'})});
export async function runDurableAiJob(operation,input,{signal,check,onProgress=()=>{},request=accountRequest,pollMs=1500}={}) {
check();
const started=await request('/api/me/ai-jobs',{method:'POST',signal,body:JSON.stringify({operation,input,requestId:crypto.randomUUID()})});
let job=started.job;
while(true) {
check();
if(!job || !['queued','running','completed','failed','interrupted','cancelled'].includes(job.state))throw new Error('AI iş durumu geçersiz. Kayıtlı işler bölümünden kontrol edin.');
onProgress(job);
if(job.state==='completed')return job.result;
if(['failed','interrupted','cancelled'].includes(job.state))throw new Error(job.error || 'AI işi iptal edildi.');
let timer;
try {await awaitWithAbort(new Promise(resolve=>{timer=setTimeout(resolve,pollMs);}),signal,()=>clearTimeout(timer));}
finally {clearTimeout(timer);}
check();
job=(await request('/api/me/ai-jobs?'+new URLSearchParams({id:job.id}),{signal})).job;
}
}
+6 -1
View File
@@ -1,6 +1,7 @@
import { runDurableAiJob } from './aiJobs.js';
import { validateOfferResponse } from './offerResponse.js';
/** Bind the entire multi-step request to its starting account and mounted view. */
export async function requestOfferAssistant({url, body, readToken, isCurrent = () => true, listDocuments, fetcher = fetch, timeoutMs = 120000, signal}) {
export async function requestOfferAssistant({url, body, readToken, isCurrent = () => true, listDocuments, fetcher = fetch, timeoutMs = 120000, signal, background = false, onProgress}) {
const token = readToken();
const check = () => {
signal?.throwIfAborted();
@@ -19,6 +20,10 @@ export async function requestOfferAssistant({url, body, readToken, isCurrent = (
.map(b => ({ad:b.ad, kategori:b.kategori}))};
}
check();
if(background) {
const data=await runDurableAiJob(url.split('/').at(-1),payload,{signal,check,onProgress});
check();return validateOfferResponse(url,data);
}
const controller = new AbortController();
const cancel = () => controller.abort();
signal?.addEventListener('abort',cancel,{once:true});