Skip to content

refactor(bot): move playlist service out of utils into services - #1982

Merged
LucasSantana-Dev merged 3 commits into
mainfrom
refactor/bot-collaborative-playlist-to-services
Aug 10, 2026
Merged

LucasSantana-Dev merged 3 commits into
mainfrom
refactor/bot-collaborative-playlist-to-services

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Aug 10, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #1981 (not yet merged) — both touch idleDisconnect.ts and leave.ts.

Summary

  • Second bounded slice of refactor(bot): utils/music/ (136 files, 10.5k LOC) contains stateful services mislabeled as utilities #1968: collaborativePlaylist.ts holds CollaborativePlaylistService, a stateful class with module-level Map state, mislabeled as a util. Zero internal imports of its own.
  • Moved to services/musicRecommendation/, updated 4 real import sites (idleDisconnect.ts, leave.ts, playlist.ts, playHandler.ts) plus 2 jest.mock() string-literal mocks (playlist.spec.ts, play/index.spec.ts) that a prior grep-only research pass for the watchdog slice missed — caught this time with a repo-wide grep before committing.

Verification

  • npm run type:check --workspace=@lucky/bot — clean
  • npm run test:bot — 242/243 suites (1 pre-existing skip, unchanged count)
  • npm run lint --workspace=@lucky/bot — 0 errors, 73 pre-existing warnings (unchanged)
  • Repo-wide grep for the old path after the move — zero remaining references

Summary by cubic

Moved the stateful collaborative playlist logic into a service under services/musicRecommendation to clarify module boundaries. No behavior changes.

  • Refactors
    • Relocated collaborativePlaylist.ts and its spec to services/musicRecommendation/collaborativePlaylist.
    • Updated imports in leave.ts, playlist.ts, play/handlers/playHandler.ts, and utils/music/idleDisconnect.ts.
    • Updated jest.mock paths in functions/music/commands/playlist.spec.ts and functions/music/commands/play/index.spec.ts.
    • Verified clean typecheck, tests, and lint in @lucky/bot.
    • Note: overlaps with the watchdog-to-services work; both touch idleDisconnect.ts and leave.ts.

Written for commit 3711449. Summary will update on new commits.

Review in cubic

First bounded slice of #1968: watchdog.ts holds a stateful class
(timers, private state Maps, recurring scan loop) mislabeled as a
util. Moves it to services/musicManagement/, updates the 13 import
sites, and deletes utils/misc/pathUtils.ts (confirmed zero import
sites, flagged safe-to-delete in the same audit).

The full split #1968 proposes (~20+ files into services/musicRecommendation/
and services/musicManagement/) is out of scope for this PR -- too large
for one mechanical move, per the issue's own recommendation to scope it.
This is the first unit; rest follows as separate PRs.
Second bounded slice of #1968: collaborativePlaylist.ts holds a
stateful class (CollaborativePlaylistService, module-level Map state)
mislabeled as a util, with zero internal coupling of its own. Moves
it to services/musicRecommendation/, updates 4 real import sites plus
2 jest.mock() string-literal mocks a prior grep-only pass missed.

Stacks on refactor/bot-watchdog-to-services (#1981, not yet merged) --
both touch idleDisconnect.ts and leave.ts.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@LucasSantana-Dev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 seconds

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 95ae611f-fc14-4664-b9a9-109e58b019bd

📥 Commits

Reviewing files that changed from the base of the PR and between 7238859 and 3711449.

📒 Files selected for processing (8)
  • packages/bot/src/functions/music/commands/leave.ts
  • packages/bot/src/functions/music/commands/play/handlers/playHandler.ts
  • packages/bot/src/functions/music/commands/play/index.spec.ts
  • packages/bot/src/functions/music/commands/playlist.spec.ts
  • packages/bot/src/functions/music/commands/playlist.ts
  • packages/bot/src/services/musicRecommendation/collaborativePlaylist.spec.ts
  • packages/bot/src/services/musicRecommendation/collaborativePlaylist.ts
  • packages/bot/src/utils/music/idleDisconnect.ts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


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.

@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Aug 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 8 files

Auto-approved: Pure structural refactor: file moved to services/ with only import/mock path updates and cosmetic formatting changes, no behavior change visible in the diff.

Re-trigger cubic

…ative-playlist-to-services

# Conflicts:
#	packages/bot/src/functions/music/commands/leave.ts
#	packages/bot/src/utils/music/idleDisconnect.ts
@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

@github-actions

Copy link
Copy Markdown
Warnings
⚠️

Big PR — 864 lines changed across 8 files. Consider splitting into smaller, reviewable chunks.

⚠️

User-facing change without a CHANGELOG.md update. Add a line under ## [Unreleased] if this should appear in release notes. (Or apply the skip-changelog label if this PR does not affect end users.)

Generated by 🚫 dangerJS against 3711449

@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 177fb2d into main Aug 10, 2026
43 of 44 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the refactor/bot-collaborative-playlist-to-services branch August 10, 2026 19:32
LucasSantana-Dev added a commit that referenced this pull request Aug 10, 2026
Stacked on #1982 (not yet merged).

## Summary
- Third bounded slice of #1968. Moves `sessionSnapshots.ts` to
`services/musicRecommendation/`, and `sessionStartupRestore.ts` +
`namedSessions.ts` to `services/musicManagement/`.
- Both `sessionStartupRestore.ts` and `namedSessions.ts` depend on
`sessionSnapshots.ts` — now a cross-service import
(`services/musicManagement/* ->
services/musicRecommendation/sessionSnapshots`), which just relocates
the same-directory coupling that already existed; not new architectural
coupling.
- Updates 11 external import sites plus `watchdog.ts`/`.spec.ts` (from
#1981), which also depends on `sessionSnapshots`.

## Side findings (filed separately, not fixed here)
- #1983 — `restoreSessionsOnStartup()` (in the file this PR moves) is
never called anywhere in the repo except its own test. Docstring claims
it runs on `clientReady`; it doesn't. Real regression, out of scope for
a move-only refactor.
- #1984 — `utils/music/index.ts` barrel has zero external consumers
repo-wide.

## Verification
- [x] `npm run type:check --workspace=@lucky/bot` — clean
- [x] `npm run test:bot` — 242/243 suites (same pre-existing skip,
unchanged count)
- [x] `npm run lint --workspace=@lucky/bot` — 0 errors, 73 pre-existing
warnings (unchanged)
- [x] Repo-wide grep after the move — only the 3 expected
self-referencing spec imports remain
- [x] Adversarial critic pass — ACCEPT, no issues

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Move the music session code from utils to services to align with domain
boundaries and clarify dependencies. No runtime behavior changes; only
import path and test mock updates.

- **Refactors**
- Moved `utils/music/sessionSnapshots.ts` to
`services/musicRecommendation/sessionSnapshots.ts` (now imports
`../../utils/music/trackFields`).
- Moved `utils/music/sessionStartupRestore.ts` and
`utils/music/namedSessions.ts` to `services/musicManagement/` (now
import `../musicRecommendation/sessionSnapshots`).
- Updated imports and jest.mocks across commands, player handlers,
watchdog, and tests; rebased on `main` and resolved conflicts in those
files.
- Kept a deliberate cross-service import: `services/musicManagement/*`
-> `services/musicRecommendation/sessionSnapshots`.

<sup>Written for commit c93cdac.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1985?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Refactor**
- Reorganized internal music session and recommendation services without
changing music playback, session management, restoration, or queue
behavior.
- Existing music commands and event handling continue to work as before.

- **Tests**
- Updated automated test coverage to follow the reorganized service
structure.
  - Test behavior and assertions remain unchanged.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
LucasSantana-Dev added a commit that referenced this pull request Sep 10, 2026
First slice of #1991. Does not close it: four subdirectories remain.

## Why this is not a utils module

`utils/music/trackUtils/` is a stateful service tree:

- `TrackUtils` (barrel) holds a `TrackProcessor`
- `TrackProcessor` owns a `TrackCacheManager` and a cleanup timer
(`startCacheCleanup`)
- `TrackCacheManager` wraps an `LRUCache`
- the barrel exports a module-level singleton: `export const trackUtils
= new TrackUtils()`

Same pattern as every finding in #1968, which established
`services/musicManagement/` as the destination across its 7 slices
(#1981, #1982, #1985, #1987, #1988, #1989, #1990).

## Surface

Only `getTrackInfo` escapes the directory, so the external surface is
four files:

| file | reference |
|---|---|
| `functions/music/commands/queue/queueDisplay.ts` | `import {
getTrackInfo }` |
| `functions/music/commands/queue/queueStats.ts` | `import {
getTrackInfo }` |
| `functions/music/commands/queue/queueDisplay.spec.ts` |
`jest.mock('...')` string literal |
| `functions/music/commands/queue/queueStats.spec.ts` |
`jest.mock('...')` string literal |

The `jest.mock()` string literals do not move with an import rewrite.
#1991 flags these as the most common miss in the #1968 slices, and the
same trap applied *inside* the moved specs, which mock
`'../titleComparison'` and `require()` it in five more places.

## Path arithmetic

Both directories sit three levels under `src/`, so relative depth is
unchanged. Only the one sibling import needed rewriting:

```
'../titleComparison'  ->  '../../../utils/music/titleComparison'
```

That is services depending on utils, which is the correct direction. The
inversion #1991 is about is utils depending on services, which this
avoids by moving the whole tree rather than `cacheManager.ts` alone.
`titleComparison` is itself on the #1991 list and moves in a later
slice.

## Verification

- `packages/bot` full suite: 273 suites passed, 3586 tests passed, 1
skipped, matching the pre-move baseline exactly (pure move, no test
added or removed)
- `npx tsc --noEmit`: clean
- `npx madge --circular --extensions ts packages/bot/src`: `No circular
dependency found!`
- `npm run build --workspace=packages/bot`: succeeds
- repo-wide grep for `utils/music/trackUtils` across
ts/tsx/js/json/yml/md: no remaining references

## Remaining in #1991

`search/engineManager.ts`, `search/providerHealth.ts` (8+ external
consumers, the largest slice), `titleComparison/service.ts`,
`youtubeErrorHandler/analyzer.ts`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Relocates the stateful `trackUtils` service from `utils/music/` to
`services/musicManagement/`, matching the destination established in
`#1968` and continuing the `#1991` refactor. Since only the queue
commands consume `getTrackInfo`, the external change is limited to
updating their imports and the `jest.mock()` path literals in their
specs.

**Notes**
- Moved specs also updated their `jest.mock('../titleComparison')` and
`require()` calls to the new relative path.
- `titleComparison` remains in `utils` and will move in a later slice;
`search/engineManager`, `search/providerHealth`, and
`youtubeErrorHandler/analyzer` are still pending.
- Full test suite and `tsc` pass with no circular dependencies.

<sup>Written for commit 5a734c9.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/2353?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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