fix: guard generateResearch against POST failure, surface partial fetch errors
- Check error from POST /research/generate; only start pollTask on success to prevent unresolvable polling intervals - Surface contacts and fullJob fetch errors in fetchFor; silently ignore research 404 (expected when no research yet) - Remove redundant type assertions (as Contact[], as TaskStatus, as FullJobDetail) - Add @internal JSDoc to pollTask - Remove redundant vi.runAllTimersAsync() after vi.advanceTimersByTimeAsync(3000) in test
This commit is contained in:
parent
ff0dd8b3cd
commit
7693abf79d
2 changed files with 27 additions and 6 deletions
|
|
@ -123,7 +123,6 @@ describe('usePrepStore', () => {
|
||||||
|
|
||||||
store.pollTask(1)
|
store.pollTask(1)
|
||||||
await vi.advanceTimersByTimeAsync(3000)
|
await vi.advanceTimersByTimeAsync(3000)
|
||||||
await vi.runAllTimersAsync()
|
|
||||||
|
|
||||||
expect(store.research?.company_brief).toBe('Updated!')
|
expect(store.research?.company_brief).toBe('Updated!')
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,24 @@ export const usePrepStore = defineStore('prep', () => {
|
||||||
useApiFetch<FullJobDetail>(`/api/jobs/${jobId}`),
|
useApiFetch<FullJobDetail>(`/api/jobs/${jobId}`),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Research 404 is expected (no research yet) — only surface non-404 errors
|
||||||
|
if (researchResult.error && !(researchResult.error.kind === 'http' && researchResult.error.status === 404)) {
|
||||||
|
error.value = 'Failed to load research data'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (contactsResult.error) {
|
||||||
|
error.value = 'Failed to load contacts'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (jobResult.error) {
|
||||||
|
error.value = 'Failed to load job details'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
research.value = researchResult.data ?? null
|
research.value = researchResult.data ?? null
|
||||||
contacts.value = (contactsResult.data as Contact[]) ?? []
|
contacts.value = contactsResult.data ?? []
|
||||||
taskStatus.value = (taskResult.data as TaskStatus) ?? { status: null, stage: null, message: null }
|
taskStatus.value = taskResult.data ?? { status: null, stage: null, message: null }
|
||||||
fullJob.value = (jobResult.data as FullJobDetail) ?? null
|
fullJob.value = jobResult.data ?? null
|
||||||
|
|
||||||
// If a task is already running/queued, start polling
|
// If a task is already running/queued, start polling
|
||||||
const ts = taskStatus.value.status
|
const ts = taskStatus.value.status
|
||||||
|
|
@ -95,16 +109,24 @@ export const usePrepStore = defineStore('prep', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateResearch(jobId: number) {
|
async function generateResearch(jobId: number) {
|
||||||
await useApiFetch<unknown>(`/api/jobs/${jobId}/research/generate`, { method: 'POST' })
|
const { data, error: fetchError } = await useApiFetch<{ task_id: number; is_new: boolean }>(
|
||||||
|
`/api/jobs/${jobId}/research/generate`,
|
||||||
|
{ method: 'POST' }
|
||||||
|
)
|
||||||
|
if (fetchError || !data) {
|
||||||
|
error.value = 'Failed to start research generation'
|
||||||
|
return
|
||||||
|
}
|
||||||
pollTask(jobId)
|
pollTask(jobId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal — called by fetchFor and generateResearch; not for component use */
|
||||||
function pollTask(jobId: number) {
|
function pollTask(jobId: number) {
|
||||||
_clearInterval()
|
_clearInterval()
|
||||||
pollInterval = setInterval(async () => {
|
pollInterval = setInterval(async () => {
|
||||||
const { data } = await useApiFetch<TaskStatus>(`/api/jobs/${jobId}/research/task`)
|
const { data } = await useApiFetch<TaskStatus>(`/api/jobs/${jobId}/research/task`)
|
||||||
if (data) {
|
if (data) {
|
||||||
taskStatus.value = data as TaskStatus
|
taskStatus.value = data
|
||||||
if (data.status === 'completed' || data.status === 'failed') {
|
if (data.status === 'completed' || data.status === 'failed') {
|
||||||
_clearInterval()
|
_clearInterval()
|
||||||
if (data.status === 'completed') {
|
if (data.status === 'completed') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue