Skip to content

Load queue depths on freebuff landing so picker doesn't flash "No wait"#532

Merged
jahooma merged 1 commit intomainfrom
jahooma/fix-waitlist-preload
Apr 22, 2026
Merged

Load queue depths on freebuff landing so picker doesn't flash "No wait"#532
jahooma merged 1 commit intomainfrom
jahooma/fix-waitlist-preload

Conversation

@jahooma
Copy link
Copy Markdown
Contributor

@jahooma jahooma commented Apr 22, 2026

Summary

  • returnToFreebuffLanding was applying bare {status:'none'} with no queueDepthByModel, and nextDelayMs returns null for 'none' so nothing refreshed — every model showed "No wait" until the user hit Enter and POST finally returned real depths.
  • Landing-mode restart now kicks off a fire-and-forget GET and extracts just queueDepthByModel (ignoring status, so a stale pre-DELETE row can't trip the takeover branch into a silent re-join).
  • Model picker renders blank hints instead of defaulting to 0 → "No wait" while the depth snapshot is missing.

Test plan

  • Open freebuff → picker shows real "N ahead" / "No wait" hints matching what POST returns on Enter.
  • Run /end-session or click the end-session button → landing picker shows accurate hints immediately, not stale zeros.
  • Click "Press Enter to rejoin" from the session-ended banner → same.

🤖 Generated with Claude Code

After returnToFreebuffLanding, the picker applied bare {status:'none'}
with no queueDepthByModel and nextDelayMs returns null for 'none', so
stale zeros showed until POST. Kick off a fire-and-forget GET in
landing mode that extracts just queueDepthByModel (ignoring status,
so a stale pre-DELETE row can't trip the takeover branch), and render
blank hints instead of "No wait" while the snapshot is missing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR fixes a UX bug where the freebuff model picker flashed "No wait" for every model whenever the landing screen was shown after a session ended. The root cause was that returnToFreebuffLanding applied { status: 'none' } with no queueDepthByModel, causing the picker to default depths to 0 ("No wait") rather than showing blank hints.

Key changes:

  • In landing mode, a fire-and-forget GET is kicked off immediately after apply({ status: 'none' }) to fetch real queue depths; once it resolves, only queueDepthByModel is extracted and applied.
  • The model selector now returns null (blank hints) instead of defaulting to {} when queueDepthByModel is absent.
  • Abort signal handling is correct: if the user presses Enter before the fire-and-forget returns, restart('rejoin') aborts fetchController.signal and the .then() callback exits early.

Confidence Score: 4/5

Safe to merge; logic is sound and race conditions are handled correctly via abort signals.

The fix is narrowly scoped, well-reasoned, and the abort/cancellation guards are correctly implemented. The one non-blocking nuance is that when the server still returns queued (pre-DELETE propagation), the depth for the user's own model includes their in-queue position, so the hint may be off-by-one — but this is an intentional, documented trade-off.

No files require special attention.

Important Files Changed

Filename Overview
cli/src/hooks/use-freebuff-session.ts Adds a fire-and-forget GET in landing mode to pre-fetch queue depths; abort signal handling and status-gated extraction are correctly implemented.
cli/src/components/freebuff-model-selector.tsx Returns null (blank hints) instead of defaulting queueDepthByModel to {} when the depth snapshot is missing in 'none' status, preventing the "No wait" flash.

Sequence Diagram

sequenceDiagram
    participant User
    participant Picker as FreebuffModelSelector
    participant Hook as useFreebuffSession
    participant Server

    User->>Hook: returnToFreebuffLanding()
    Hook->>Hook: abort in-flight request
    Hook->>Hook: apply({ status: 'none' }) — no queueDepthByModel
    Hook-->>Picker: session = { status: 'none' } → hints = null (blank)

    Hook->>Server: GET /api/v1/freebuff/session (fire-and-forget)
    Note over Hook,Server: signal = fetchController.signal

    alt Server responds with none or queued status
        Server-->>Hook: { status: 'none'/'queued', queueDepthByModel: {...} }
        Hook->>Hook: apply({ status: 'none', queueDepthByModel })
        Hook-->>Picker: hints show real depths
    else Server responds with active/ended/other
        Server-->>Hook: response ignored
        Hook-->>Picker: hints stay blank (prevents auto-rejoin)
    else User presses Enter before fetch returns
        User->>Hook: joinFreebuffQueue(model)
        Hook->>Hook: abort fetchController.signal
        Note over Hook: .then() checks signal.aborted → exits early
        Hook->>Server: POST /api/v1/freebuff/session
        Server-->>Hook: real session response
        Hook-->>Picker: full session state applied
    end
Loading

Reviews (1): Last reviewed commit: "Load queue depths on landing so picker d..." | Re-trigger Greptile

@jahooma jahooma merged commit 21b4706 into main Apr 22, 2026
34 checks passed
@jahooma jahooma deleted the jahooma/fix-waitlist-preload branch April 22, 2026 00:33
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.

1 participant