AI Feilhåndtering
Dokumentasjon av hvordan Impulse AI håndterer feil i AI-workloads — fra Anthropic API-overload (529) til nettverksproblemer. Designprinsipp: AI-feil skal aldri fryse appen. Brukeren skal alltid forstå hva som skjer og kunne handle.
Feilkategorier
heading.anchorLabelAI-feil klassifiseres i to kategorier i apps/api/src/queues/base/error-handling.ts:
| Kategori | HTTP-koder | Handling |
|---|---|---|
| Retryable | 429, 503, 529 | Automatisk retry med backoff |
| Non-retryable | 400, 401, 500 | Umiddelbar feil til bruker |
Meldingsbasert deteksjon fanger også: overloaded, rate limit, too many requests, temporarily unavailable, timeout.
Retry-arkitektur (to lag)
heading.anchorLabelAI-workloads har to uavhengige retry-lag som kjører i serie:
Lag 1: AI SDK (HTTP-nivå)
heading.anchorLabelKonfigurert i apps/api/src/ai/infrastructure/anthropic/config.ts:
- Max retries: 3 (totalt 4 forsøk)
- Backoff: Eksponentiell (AI SDK default)
- Timeout: 30s per forsøk (standard), 60s for langvarige
Hvis alle 4 forsøk feiler, kastes feilen videre til køen.
Lag 2: BullMQ (kø-nivå)
heading.anchorLabelKonfigurert i apps/api/src/queues/base/bullmq-job-queue.ts:
- Max attempts: 3
- Backoff-delays: 30s, 60s, 120s
- Total worst case: 4 × 3 = 12 API-kall over ~4 minutter
Forsøk 1: AI SDK prøver 4 ganger → feiler ↓ (venter 30s)Forsøk 2: AI SDK prøver 4 ganger → feiler ↓ (venter 60s)Forsøk 3: AI SDK prøver 4 ganger → feiler → Endelig feil → SSE sender error-eventSSE-kommunikasjon til klient
heading.anchorLabelRetry-status kommuniseres til iOS via Server-Sent Events. Endepunkt: GET /api/v1/sessions/:id/summary/status.
Event-typer
heading.anchorLabel| Event | Betydning | Klient-handling |
|---|---|---|
queued | Jobb venter i kø | Spinner |
processing | AI genererer | Spinner |
retrying | Midlertidig feil, prøver igjen | Spinner + statusmelding |
completed | Dokument klart | Vis sammendrag |
error | Endelig feil etter alle retries | Feilmelding + retry-knapp |
idle | Ingen jobb funnet | Re-subscribe etter 2s |
SSE retrying-event (data)
heading.anchorLabel{ "session_id": "abc-123", "attempt": 1, "next_retry_at": "2026-04-07T12:01:30.000Z", "message": "Retrying in 60s (attempt 2/3)..."}iOS UX-flyt
heading.anchorLabelImplementert i iosApp/Features/Sessions/Unified/UnifiedSessionView.swift.
Tilstander i completing-laget
heading.anchorLabel┌─────────────────────────────────────┐│ Normal: Spinner + "Sammenstiller ││ innsiktene" ││ ││ Retry: Spinner + "AI-tjenesten ││ er opptatt. Prøver igjen ││ automatisk..." ││ ││ Error: Feilmelding + "Prøv ││ igjen"-knapp ││ ││ Alltid: "Jeg ser dette senere" ││ (dismiss-knapp) │└─────────────────────────────────────┘Timeout og dismiss
heading.anchorLabel- 30s hard timeout: Etter 30s stopper spinneren, men SSE-forbindelsen holdes åpen
- “Jeg ser dette senere”: Dismisser til impulsdetal. SSE fortsetter i bakgrunnen — når dokumentet er klart, er det tilgjengelig fra impulsdetal-visningen
- Manuell retry:
POST /api/v1/sessions/:id/summary/retryre-køer jobben
State-variabler
heading.anchorLabel@State private var isSummaryLoading: Bool // Spinner synlig@State private var summaryError: Bool // Feilvisning aktiv@State private var summaryRetryAttempt: Int? // Retry-nummer (nil = normal)Feilvisning (AIWorkloadErrorView)
heading.anchorLabelGjenbrukbar komponent i iosApp/Components/AIWorkloadErrorView.swift.
Brukes av session summary, step guidance og classification. Viser:
- Advarselikon
- Kontekstspesifikk melding
- Ghost CTA retry-knapp (accent-farget)
Lokalisering
heading.anchorLabelFeilmeldinger er lokalisert i alle 16 språk:
| Nøkkel | EN | NB |
|---|---|---|
ai_workload_summary_error | We couldn’t create your session summary… | Vi klarte ikke å lage sammendraget ditt… |
ai_workload_guidance_error | We couldn’t generate the guidance… | Vi klarte ikke å generere veiledningen… |
ai_service_busy_retrying | The AI service is busy. Retrying automatically… | AI-tjenesten er opptatt. Prøver igjen automatisk… |
ai_workload_retry_button | Try again | Prøv igjen |
session_see_later | I’ll see this later | Jeg ser dette senere |
Nøkkelfiler
heading.anchorLabel| Fil | Ansvar |
|---|---|
apps/api/src/queues/base/error-handling.ts | Feilklassifisering og retry-config |
apps/api/src/queues/base/bullmq-job-queue.ts | BullMQ retry-logikk og SSE-bridge |
apps/api/src/queues/sessions/session-summary.ts | Session summary worker |
apps/api/src/routes/sessions/summary-status.ts | SSE-endepunkt |
shared/.../models/SSEEvent.kt | KMP SSE-modeller (inkl. Retrying) |
shared/.../parsers/SummarySSEEventParser.kt | KMP SSE-parser |
iosApp/Services/APIService.swift | iOS SSE wrapper |
iosApp/Features/Sessions/Unified/UnifiedSessionView.swift | iOS completing-lag |
iosApp/Components/AIWorkloadErrorView.swift | Gjenbrukbar feilvisning |
Designprinsipper
heading.anchorLabel- Aldri frys UI: Brukeren skal alltid kunne handle (dismiss, retry)
- Transparent kommunikasjon: Vis hva som skjer (“prøver igjen automatisk”)
- Bakgrunnsprosessering: AI fortsetter i bakgrunnen selv etter dismiss
- Progressiv forverring: Normal → retry-info → feilmelding → manuell retry
- SSE som sanntidskanal: Alle statusoverganger kommuniseres i sanntid