whisper-money/resources/js/components/onboarding
Víctor Falcón d3ec96b845
fix(onboarding): stop the AI rule-suggestion step from hanging forever (#705)
## Problem

A user reported being stuck forever on the onboarding "Looking for
patterns" step (the "Polishing your suggestions…" spinner). Confirmed in
prod: their `suggestion_runs` row has been stuck in `processing` for a
week, and `failed_jobs` shows `TimeoutExceededException:
GenerateRuleSuggestionsJob has timed out`.

### Root cause

- The user has 4,163 transactions — the largest onboarding dataset (max
with a completed run was 3,481). The Gemini generation exceeded the
job's `$timeout = 120`.
- The worker timeout is raised **outside** the `try/catch` in
`GenerateRuleSuggestions::run()`, so the code that sets `status =
Failed` never ran.
- `GenerateRuleSuggestionsJob` had **no `failed()` handler** (5 other
jobs do), so nothing flipped the run to `Failed`. It stayed
`processing`, `show()` kept returning `processing`, and the client
polled every 3s forever.
- The timeout never reached Sentry, so it was invisible. Only 1 user
affected, but it's a latent bug that recurs on any large account.

## Fix

**Backend** — add `failed()` to `GenerateRuleSuggestionsJob`: mark the
run `Failed` (only if not already terminal) and `report()` the exception
so these surface in Sentry.

**Frontend** (`step-ai-suggestions.tsx`) — belt-and-suspenders so the
client never spins forever even if the worker dies before it can mark
the run:
- `poll()` now guards against transient errors (network blip / expired
session / 5xx) instead of silently dying.
- A client-side deadline (3 min, just beyond the "up to two minutes"
copy) surfaces the existing "couldn't generate" screen with **Try again
/ Skip**.

Not included: raising the timeout / capping the number of groups sent to
Gemini so large accounts *complete* instead of just being able to skip.
Follow-up if we want big accounts to get suggestions.

## Tests

- `tests/Feature/Ai/GenerateRuleSuggestionsJobTest.php` — `failed()`
marks the run `Failed` + reports; doesn't overwrite an already-terminal
run.
-
`resources/js/components/onboarding/step-ai-suggestions-timeout.test.tsx`
— after the deadline the spinner gives way to the failed screen.

Green locally: pint, prettier, eslint, backend + frontend tests.
2026-07-20 18:10:51 +00:00
..
ai-suggestion-card.tsx feat(ai): suggest automation rules during onboarding (#523) 2026-06-13 22:51:15 +02:00
step-account-types.tsx refactor(real-estate): remove Pennant gating (#308) 2026-04-20 13:31:49 +01:00
step-ai-suggestions-timeout.test.tsx fix(onboarding): stop the AI rule-suggestion step from hanging forever (#705) 2026-07-20 18:10:51 +00:00
step-ai-suggestions-upgrade.test.tsx feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
step-ai-suggestions.test.tsx feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
step-ai-suggestions.tsx fix(onboarding): stop the AI rule-suggestion step from hanging forever (#705) 2026-07-20 18:10:51 +00:00
step-button.tsx User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
step-categorize-transactions.tsx feat(onboarding): clarify the "categorize at least 5" goal in the categorizer (#616) 2026-07-01 08:34:51 +02:00
step-category-types.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
step-complete.tsx feat(subscription): allow free plan for open banking users without connected banks (#188) 2026-03-03 22:28:50 +00:00
step-create-account.tsx refactor(js): extract shared getCsrfToken util (#475) 2026-06-03 17:26:09 +02:00
step-customize-categories.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
step-header.tsx User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
step-import-balances.tsx fix(balances): allow saving a zero balance (#664) 2026-07-10 15:02:38 +02:00
step-import-transactions.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
step-smart-rules.tsx feat: (Onboarding) add categorization intro screen with benefit cards (#201) 2026-03-05 11:47:12 +01:00
step-syncing.tsx fix(browser-test): reload transactions in syncing step and fix Skip button selector (#203) 2026-03-05 11:29:06 +00:00
step-welcome.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00