fix(PBI-59): map jobs_initial SSE payload by job_id, not id (#155)
De server-route stuurt JobPayload[] (met `job_id`), maar de client deed `initJobs(jobs, ...)` waardoor alle entries in activeJobs `id: undefined` kregen — wat React-key warnings opleverde: Each child in a list should have a unique "key" prop. Fix: SSE jobs_initial niet meer als overwrite gebruiken; SSR-fetch heeft de volledige JobWithRelations al in de store gezet. We reconcileren nu per job met upsertJob (status/branch/error/summary updaten van bekende jobs, onbekende jobs als partials toevoegen — zelfde gedrag als gewone 'message' SSE events). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
00dbbb4f94
commit
883534a521
1 changed files with 17 additions and 5 deletions
|
|
@ -18,7 +18,6 @@ interface JobStatusPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useJobsRealtime() {
|
export default function useJobsRealtime() {
|
||||||
const initJobs = useJobsStore(s => s.initJobs)
|
|
||||||
const upsertJob = useJobsStore(s => s.upsertJob)
|
const upsertJob = useJobsStore(s => s.upsertJob)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -32,10 +31,23 @@ export default function useJobsRealtime() {
|
||||||
es = new EventSource('/api/realtime/jobs')
|
es = new EventSource('/api/realtime/jobs')
|
||||||
|
|
||||||
es.addEventListener('jobs_initial', (event) => {
|
es.addEventListener('jobs_initial', (event) => {
|
||||||
|
// De server stuurt JobPayload[] (met `job_id`), niet JobWithRelations[].
|
||||||
|
// Daarom geen initJobs-overwrite — de SSR-fetch heeft de volledige
|
||||||
|
// shape al in de store geplaatst. We reconcileren alleen status/branch
|
||||||
|
// van bekende jobs en pushen onbekende jobs (nieuw aangemaakt tussen
|
||||||
|
// SSR en SSE-connect) als partials.
|
||||||
try {
|
try {
|
||||||
const jobs = JSON.parse(event.data)
|
const payload = JSON.parse(event.data)
|
||||||
if (Array.isArray(jobs)) {
|
if (!Array.isArray(payload)) return
|
||||||
initJobs(jobs, useJobsStore.getState().doneJobs)
|
for (const p of payload as JobStatusPayload[]) {
|
||||||
|
if (!p.job_id) continue
|
||||||
|
upsertJob({
|
||||||
|
id: p.job_id,
|
||||||
|
status: p.status as ClaudeJobStatus,
|
||||||
|
branch: p.branch ?? null,
|
||||||
|
error: p.error ?? null,
|
||||||
|
summary: p.summary ?? null,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// malformed JSON
|
// malformed JSON
|
||||||
|
|
@ -75,5 +87,5 @@ export default function useJobsRealtime() {
|
||||||
if (reconnectTimer) clearTimeout(reconnectTimer)
|
if (reconnectTimer) clearTimeout(reconnectTimer)
|
||||||
es?.close()
|
es?.close()
|
||||||
}
|
}
|
||||||
}, [initJobs, upsertJob])
|
}, [upsertJob])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue