Skip to content

fix(autoplay): replenish queue on exhaustion + suppress recovery on stale snapshot - #691

Merged
LucasSantana-Dev merged 9 commits into
mainfrom
fix/autoplay-repeat-regression
Apr 17, 2026
Merged

LucasSantana-Dev merged 9 commits into
mainfrom
fix/autoplay-repeat-regression

Conversation

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Summary

Fixed critical autoplay regression affecting three symptoms:

  1. Queue exhaustion → repeats last song: When initial queue runs out, bot now replenishes instead of marking as stop
  2. Skip dup → bot leaves channel: Queue exhaustion after skip now suppresses watchdog recovery for 35s
  3. Watchdog rejoin with same song: Stale snapshots (only currentTrack, no queue) are now cleared to prevent re-enqueue

Root Causes

  • emptyQueue event marked stop but didn't replenish during autoplay
  • Skip on last track → queue empty → watchdog immediately restores snapshot with same song
  • Watchdog restore had skipCurrentTrack but upcomingTracks[0] could still be the just-played song

Changes

  • lifecycleHandlers.ts: emptyQueue now calls replenishQueue when autoplay enabled + currentTrack exists
  • trackHandlers.ts: Added setReplenishSuppressed(35s) + clearSnapshotIfStale() when queue becomes empty
  • sessionSnapshots.ts: New clearSnapshotIfStale() helper to delete stale snapshots (drained queue)
  • replenisher.ts: Improved debug logging for exhausted candidate pools
  • Tests: Added coverage for emptyQueue autoplay, replenish suppression, snapshot cleanup

Test Plan

  • All 2731 existing tests pass (trackHandlers, lifecycleHandlers, autoplay, replenish, watchdog, session modules)
  • Build passes (npm run build)
  • New test cases verify emptyQueue replenishment behavior
  • No behavior changes outside the 3 reported symptoms

Fixes: Queue stall, unexpected disconnect, unwanted rejoin with stale track

🤖 Generated with Claude Code

@vercel

vercel Bot commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Apr 17, 2026 11:04pm

Request Review

@coderabbitai

coderabbitai Bot commented Apr 17, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 25 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 11 minutes and 25 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad32001f-4c41-4f5c-be95-e0699bb5f04a

📥 Commits

Reviewing files that changed from the base of the PR and between f961dbf and 6ede5a9.

📒 Files selected for processing (9)
  • packages/bot/src/handlers/player/lifecycleHandlers.spec.ts
  • packages/bot/src/handlers/player/lifecycleHandlers.ts
  • packages/bot/src/handlers/player/queueExhaustion.spec.ts
  • packages/bot/src/handlers/player/queueExhaustion.ts
  • packages/bot/src/handlers/player/trackHandlers.spec.ts
  • packages/bot/src/handlers/player/trackHandlers.ts
  • packages/bot/src/utils/music/autoplay/replenisher.ts
  • packages/bot/src/utils/music/sessionSnapshots.spec.ts
  • packages/bot/src/utils/music/sessionSnapshots.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/autoplay-repeat-regression

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…tale snapshot

Root causes of autoplay regression:
1. Queue exhaustion during autoplay: emptyQueue event marked as intentional stop but didn't attempt replenishment. Now attempts replenish when autoplay is enabled and currentTrack exists.
2. Skip on last track → disconnect → watchdog rejoin: When queue emptied after skip/finish, no protection prevented watchdog orphan recovery from immediately rejecting. Added setReplenishSuppressed(35s) to prevent recovery until idle timeout fires.
3. Watchdog restores stale snapshot: restoreSnapshot had skipCurrentTrack but upcomingTracks[0] could still be the just-played song. Added clearSnapshotIfStale() to delete snapshot when only currentTrack exists (queue was drained).

Changes:
- lifecycleHandlers.ts: emptyQueue now calls replenishQueue instead of markIntentionalStop when autoplay is enabled
- trackHandlers.ts: added setReplenishSuppressed(35s) + clearSnapshotIfStale() when queue becomes empty after skip/finish
- sessionSnapshots.ts: added clearSnapshotIfStale() helper to clean stale snapshots
- replenisher.ts: improved debug logging for exhausted candidate pool
- lifecycleHandlers.spec.ts: added tests for emptyQueue autoplay replenishment
- trackHandlers.spec.ts: added mocks for replenishSuppressionStore and clearSnapshotIfStale

Integration: No behavior changes outside the 3 symptoms. All existing tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@LucasSantana-Dev
LucasSantana-Dev force-pushed the fix/autoplay-repeat-regression branch from e6f2a41 to 4609f9b Compare April 17, 2026 17:43
@LucasSantana-Dev
LucasSantana-Dev enabled auto-merge (squash) April 17, 2026 17:43
@github-actions github-actions Bot added size/m and removed dependencies Pull requests that update a dependency file size/xl labels Apr 17, 2026
- Create queueExhaustion.ts with shared handleQueueExhaustion function
- Refactor handlePlayerFinish and handlePlayerSkip to use shared handler
- Add unit tests for queueExhaustion module
- Reduces code duplication between finish and skip event handlers
- Maintains all existing behavior with 2735 tests passing
Adds 8 tests for redis error swallowing, missing key, clearStaleIfStale
no-ops, restoreSnapshot guards. Coverage 78.20% → 91.02% lines /
70.49% → 83.60% branches.
@LucasSantana-Dev
LucasSantana-Dev merged commit 1ed6bcd into main Apr 17, 2026
12 checks passed
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
70.4% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
…tale snapshot (#691)

* fix(autoplay): replenish queue on exhaustion + suppress recovery on stale snapshot

Root causes of autoplay regression:
1. Queue exhaustion during autoplay: emptyQueue event marked as intentional stop but didn't attempt replenishment. Now attempts replenish when autoplay is enabled and currentTrack exists.
2. Skip on last track → disconnect → watchdog rejoin: When queue emptied after skip/finish, no protection prevented watchdog orphan recovery from immediately rejecting. Added setReplenishSuppressed(35s) to prevent recovery until idle timeout fires.
3. Watchdog restores stale snapshot: restoreSnapshot had skipCurrentTrack but upcomingTracks[0] could still be the just-played song. Added clearSnapshotIfStale() to delete snapshot when only currentTrack exists (queue was drained).

Changes:
- lifecycleHandlers.ts: emptyQueue now calls replenishQueue instead of markIntentionalStop when autoplay is enabled
- trackHandlers.ts: added setReplenishSuppressed(35s) + clearSnapshotIfStale() when queue becomes empty after skip/finish
- sessionSnapshots.ts: added clearSnapshotIfStale() helper to clean stale snapshots
- replenisher.ts: improved debug logging for exhausted candidate pool
- lifecycleHandlers.spec.ts: added tests for emptyQueue autoplay replenishment
- trackHandlers.spec.ts: added mocks for replenishSuppressionStore and clearSnapshotIfStale

Integration: No behavior changes outside the 3 symptoms. All existing tests green.

* refactor: extract duplicate queue exhaustion logic into shared handler

- Create queueExhaustion.ts with shared handleQueueExhaustion function
- Refactor handlePlayerFinish and handlePlayerSkip to use shared handler
- Add unit tests for queueExhaustion module
- Reduces code duplication between finish and skip event handlers
- Maintains all existing behavior with 2735 tests passing

* test(autoplay): cover sessionSnapshots error paths and edge cases

Adds 8 tests for redis error swallowing, missing key, clearStaleIfStale
no-ops, restoreSnapshot guards. Coverage 78.20% → 91.02% lines /
70.49% → 83.60% branches.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@LucasSantana-Dev
LucasSantana-Dev deleted the fix/autoplay-repeat-regression branch May 23, 2026 02:21

This branch was successfully deployed

1 active deployment
Preview — 6ede5a98 Deployed Apr 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant