Skip to content

feat(subsonic): balance the similar-songs draw across artists - #274

Merged
InstaZDLL merged 2 commits into
mainfrom
feat/similar-songs-balanced
Oct 15, 2026
Merged

InstaZDLL merged 2 commits into
mainfrom
feat/similar-songs-balanced

Conversation

@InstaZDLL

@InstaZDLL InstaZDLL commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Summary

A follow-up to #273 (step E, #267). The similar-songs draw took tracks at random from one pool, so an artist with two hundred tracks beside three neighbours with ten each filled about 43 of the 50 places with their own songs. That conforms to the specification ("a random collection"), but it is not what a client asking for similar songs means.

  • Artists take turns (DomainServices::similar_songs, src/services/artist_enrichment.rs). Inside each artist, tracks are ranked at random. The draw then takes rank 1 of every artist, then rank 2, and so on. An artist that runs out leaves its turns to the others, so count is still reached while tracks remain. The result is shuffled, so it does not play artist by artist.
  • A track counts for the artist that brought it into the draw: its first track artist among the names, otherwise its album's first album artist among them. Filing by the first track artist alone, as the first commit did, made an album of guests on a neighbour's record into one extra artist per guest. CodeRabbit raised this locally. The filing joins come after the projection in the SQL, so the user id stays the first bind. Each join keeps one row per track or album with SQLite's bare column beside MIN, which returns the row holding the minimum.
  • Docs: RFC-002, subsonic-api-guide.md (which now also says that getSimilarSongs2 documents only an artist id and accepts all three), the handler's doc comment, and a revision note on RFC-011 decision 7.

How I tested

  • cargo test --all-features: every target passes. enrichment grows from 18 to 20 tests. Its fixture gains library_with, which gives a track an artist different from its album's.
  • cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --all --check.
  • Each new test was made to fail under the change it guards:
test inversion
a_prolific_artist_does_not_crowd_out_the_neighbours (60 tracks beside 5, 20 drawn: all 5 are in) one pool (ORDER BY RANDOM() without the rank)
a_neighbour_s_album_of_guests_takes_one_share (60 beside a 10-guest album, 4 drawn: exactly 2 are Björk's) filed by first track artist (PARTITION BY s.artist_id)
  • Both assertions are deterministic under the balanced draw. Under the pooled one, the first has about a one in five hundred chance of passing by luck (all five drawn), and the second cannot pass at all, since filing by guest gives Björk a single turn in the first round.
  • Local CodeRabbit review: two findings on the first commit, both addressed above. No findings on the second.

Summary by CodeRabbit

  • Documentation
    • Précisé que les résultats de chansons similaires sont répartis entre l’artiste demandé et ses artistes voisins, afin qu’un artiste prolifique ne domine pas la sélection.
    • Clarifié que le nombre de résultats est plafonné par le paramètre count (50 par défaut) et que la recherche accepte aussi des identifiants d’album ou de morceau.
  • Tests
    • Vérifié que la sélection reste équilibrée entre les artistes, y compris lorsque plusieurs artistes invités apparaissent sur un même album.

One pool of tracks let an artist with many tracks fill most of the answer with their own songs. Artists now take turns, one track each at random, and one that runs out leaves its turns to the others; the result is shuffled.

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
@github-actions github-actions Bot added scope: server Server core (Rust) scope: docs Docs, README, assets type: feat New feature size: m 50-200 lines labels Oct 15, 2026
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: InstaZDLL/waveflow-server/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 7a2972d7-da70-493e-9d14-03198f6528f8
📥 Commits

Reviewing files that changed from the base of the PR and between fd32ed6 and f8636c7.

📒 Files selected for processing: 6
  • docs/rfcs/RFC-002-waveflow-server-v2.md
  • docs/rfcs/RFC-011-metadata-enrichment.md
  • docs/subsonic-api-guide.md
  • src/services/artist_enrichment.rs
  • src/subsonic/browse.rs
  • tests/enrichment.rs

Limit details: You’ve used the included review currently available. Your 89 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

📝 Walkthrough

La sélection de getSimilarSongs et getSimilarSongs2 répartit les titres entre l’artiste demandé et ses artistes similaires. La requête associe chaque piste à un artiste, puis limite et mélange les résultats. Les tests couvrent les artistes prolifiques et les artistes invités.

Changes: Sélection des titres similaires

Layer / File(s) Summary
Répartition des titres et validation
src/services/artist_enrichment.rs, src/subsonic/browse.rs, tests/enrichment.rs, docs/rfcs/RFC-002-waveflow-server-v2.md, docs/rfcs/RFC-011-metadata-enrichment.md, docs/subsonic-api-guide.md
La requête répartit les pistes visibles par artiste associé, les classe aléatoirement au sein de chaque groupe, puis limite et mélange les résultats. Les tests vérifient la présence d’un artiste moins représenté et regroupent les artistes invités selon leur artiste d’album. Les commentaires et documents décrivent la répartition et les identifiants acceptés.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to f8636

The change balances similar-song selection across artists, and no concrete merge-blocking issue was found.

Security architecture risk: ⚪ Minimal · up to f8636

The change balances recommendations among tracks the caller could already access. The reviewed changes do not expand permissions, provider authority, or persistent state changes, and no material security issue was identified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed result composition remains contained to available tracks across libraries accessible to the authenticated caller. The unscoped participant classifications do not themselves admit tracks from inaccessible libraries because their left joins are keyed to already-filtered song rows.

Trust Boundaries and Controls

  • observed — The handler supplies the authenticated principal's identity and parsed entity identifier. Tenant-scoped entity resolution occurs before enrichment access, and provider-derived names remain bound SQL data rather than executable query text. These controls and their exposure are unchanged from the PR base.
Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed Le titre décrit précisément le changement principal : équilibrer la sélection de morceaux similaires entre artistes.
Description check Passed La description explique le problème, le comportement modifié, les tests ajoutés et les validations exécutées. Elle ne reprend pas les sections « Changes » et « Test plan » ni la confirmation DCO, mais…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. (3 skipped: 3 …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

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

@github-actions github-actions Bot added type: feat New feature and removed type: feat New feature labels Oct 15, 2026
@InstaZDLL
InstaZDLL merged commit cd05ddd into main Oct 15, 2026
15 checks passed
@InstaZDLL
InstaZDLL deleted the feat/similar-songs-balanced branch October 15, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: docs Docs, README, assets scope: server Server core (Rust) size: m 50-200 lines type: feat New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant