Skip to content

fix(chat-widget): retry health check so the widget doesn't vanish on a blip#450

Merged
web3jenks merged 1 commit into
mainfrom
fix/chat-widget-health-retry
Jul 13, 2026
Merged

fix(chat-widget): retry health check so the widget doesn't vanish on a blip#450
web3jenks merged 1 commit into
mainfrom
fix/chat-widget-health-retry

Conversation

@web3jenks

Copy link
Copy Markdown
Collaborator

Why

Users report the AI chat widget sometimes doesn't load at all (needs a page refresh). Root cause: both entry points (the floating bubble and the header "Ask Babylon AI" button) are gated on a single, no-retry /health fetch that defaults to hidden and fails closed:

  • isApiHealthy starts false; one fetch('/health') with a 5s abort runs on mount.
  • On any failure/timeout, isApiHealthy stays false and if (!isApiHealthy) return null renders nothing (and the header button's reveal-CSS is never injected).
  • No retry — so a cold pod, a 503 during warmup, a rolling deploy of the single replica, or any transient blip hides the widget until a full reload.

What

  • Retry on a front-loaded schedule: attempts at 0, +2s, +7s, +20s, +50s, +110s (6 checks within ~110s, under a 2-minute span), dense early and spreading out, then a slow 60s poll while still unhealthy. Stops the instant /health responds OK.
  • Re-check on tab focus (visibilitychange) so a pod that recovers while the tab was backgrounded shows the widget without a reload.
  • Per-attempt timeout tightened 5s → 4s; pending retries + listener cancelled on unmount.

Frontend-only; ships independently of the backend keepalive work (devex-ai-bot#63, actions#60), which reduces how often these retries even fire.

Notes

  • Commit is unsigned (authored headlessly) — resign with YubiKey before merge if required.
  • No API surface change; verified no dangling refs. Recommend letting CI run the Docusaurus typecheck/build.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🔐 Commit Signature Verification

All 1 commit(s) passed verification

Commit Author Signature Key Type Key Check
9528107e7b0d Jenks sk-ssh-ed25519

Summary

  • Commits verified: 1
  • Signature check: ✅ All passed
  • Key type enforcement: ✅ All sk-ssh-ed25519

Required key type: sk-ssh-ed25519 (FIDO2 hardware key)

Last verified: 2026-07-09 10:35 UTC

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes the chat widget retry its health check instead of hiding after one failed request. The main changes are:

  • Front-loaded retry delays followed by steady polling while unhealthy.
  • A shorter per-attempt health-check timeout.
  • A visibility-change recheck when the tab comes back into focus.
  • Cleanup for pending retry timers and the visibility listener.

Confidence Score: 5/5

The changed flow looks safe to merge after a small cleanup to avoid duplicate polling.

  • The retry loop fixes the main hidden-widget path.
  • A visibility-triggered retry can leave parallel health-check chains running.
  • No blocking correctness or security issue was found in the changed code.

src/components/ChatWidget.tsx

Important Files Changed

Filename Overview
src/components/ChatWidget.tsx Adds retrying health checks, visibility-triggered rechecks, and timer/listener cleanup for the chat widget.

Reviews (1): Last reviewed commit: "fix(chat-widget): retry health check so ..." | Re-trigger Greptile

Comment thread src/components/ChatWidget.tsx Outdated
@web3jenks

Copy link
Copy Markdown
Collaborator Author

✅ Retry logic unit-tested (faithful port, delays ÷100 to run fast)

A) recovers after 3 failures:
   attempt #0 fail, #1 fail, #2 fail, #3 HEALTHY
   -> visible=true, totalCalls=4   (stops retrying on success)

B) API stays down (old code = 1 try, hidden forever):
   attempts at 0/2/7/20/50/110s (shown ÷100) -> 6 calls in-window
   -> visible=false, still retrying   (old behaviour: calls=1, hidden until reload)

Confirms: retries on the front-loaded schedule (0/2/7/20/50/110s, then 60s poll), stops immediately when /health recovers, and keeps the widget hidden-but-recovering while the API is down instead of hidden-forever. The visibilitychange re-check additionally un-hides on tab focus without a reload.

This is frontend-only; the backend keepalive (devex-ai-bot#63, verified live: cold query 12.4s → 7.0s warmed) reduces how often these retries even fire.

@kkkk666 could you review? 🙏

@web3jenks
web3jenks requested a review from kkkk666 July 9, 2026 06:21
…a blip

The AI chat entry points (floating bubble + header button) were gated on a
single, no-retry /health fetch that defaults to hidden and fails closed:
one slow/failed/timed-out response (a cold pod, a 503 during warmup, a
rolling deploy, or any transient) left `isApiHealthy=false` and the whole
widget rendered null until a full page reload. This is the "sometimes it
doesn't load at all" symptom.

Now the health check retries on a front-loaded schedule — attempts at
0, +2s, +7s, +20s, +50s, +110s (6 checks within ~110s, under 2 min), then a
slow 60s poll while still unhealthy — and stops immediately once /health
responds. Also re-checks on tab focus (visibilitychange) so a pod that
recovers while the tab was backgrounded un-hides the widget without a reload.
Per-attempt timeout tightened 5s -> 4s; retries cancelled on unmount.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@web3jenks
web3jenks force-pushed the fix/chat-widget-health-retry branch from d04e22b to 9528107 Compare July 9, 2026 10:33
@web3jenks

Copy link
Copy Markdown
Collaborator Author

Addressed Greptile review (commit 9528107, signed):

  • Parallel retry chains → added a generation counter. Each (re)start bumps generation; an in-flight/scheduled attempt whose gen is stale bails out after its fetch resolves, so a tab-focus re-check can't leave an orphaned polling chain running alongside the current one.

Re-signed with YubiKey. tsc passes with no ChatWidget errors.

@kkkk666 kkkk666 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test pass.

@web3jenks
web3jenks merged commit 7ddf512 into main Jul 13, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants