Tell people why the assistant failed - #5070
Conversation
|
Based on my analysis, let me determine which checks apply and verify them. Changed files:
Scoping analysis:
Other checks: |
ed7e3fd to
f742165
Compare
3683332 to
5a28e60
Compare
f742165 to
4cff9e9
Compare
5a28e60 to
1813938
Compare
Every failure looks the same to a user: the message goes red and offers a retry. Apollo being down, Apollo being slow, and a deploy interrupting the run are indistinguishable, so people retry a hard-down service forever and support cannot triage from a screenshot. The reasons already exist. handle_error_response builds strings written for a person to read, and they were logged and then dropped - the channel only ever sent a message id and the word error. They now live on the message as a category and a sentence. Columns rather than a broadcast, because the failure that matters most is a deploy interrupting a run, and that is exactly when the browser reconnects to a different node with the broadcast long gone. It is also frequently written by a different process than the one that failed. Two columns rather than one blob: the category is what the frontend switches on and what you group by when someone asks how many timeouts there were last week. The sentence is user-facing prose only. Raw error terms and upstream response bodies stay in the log, where they cannot leak an internal hostname or a stack trace to whoever is reading the chat panel. It is bounded, too. It is written through Ecto.Changeset.change/2, which applies no validation, and read back and re-sent on every channel join, so an unbounded string would be paid for on each one. The internal-failure branch no longer logs a second time. Whoever raised already logged the exception, and every extra Logger.error is another Sentry event for one failure. A returned reason is now a named type. The specs said String.t() | Ecto.Changeset.t(), which this change makes untrue - the internal tuple is neither - so they say stream_error() instead, and dialyzer can hold the callers to it.
1813938 to
d16eb79
Compare
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (77.8%) is below the target coverage (80.0%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## timeout-oban-lifecycle #5070 +/- ##
========================================================
- Coverage 90.6% 90.6% -0.0%
========================================================
Files 421 421
Lines 20014 20024 +10
========================================================
+ Hits 18136 18143 +7
- Misses 1878 1881 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Description
Every AI chat failure looked the same to the user, and to us. A hung Apollo, a dropped connection, a rate limit and a genuinely short answer all produced one generic error, so nobody could tell which had happened without digging through logs.
Messages now carry a
failure_categoryand afailure_message. The category is a small enum we can group and count on; the message is the sentence the user reads.Two other things came out of the same path.
Repo.get!becameRepo.get, because a message deleted while its job was in flight raised and left the job to retry against a row that would never come back. And a timeout is now logged at:warningrather than:error, since it isn't an application fault and was adding noise to Sentry.Closes #__
Validation steps
mix test test/lightning/ai_assistant/message_processor_test.exsAPOLLO_ENDPOINTat something that isn't listening, send a chat message, and check the saved message has a category rather than a bare error string.AI Usage
Pre-submission checklist