release / web (push) Successful in 1m24s
release / go (push) Successful in 1m47s
release / govulncheck (push) Successful in 25s
release / integration (push) Failing after 4m38s
release / android (push) Successful in 4m3s
release / Build signed APK (push) Successful in 4m34s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
A new system playlist kind, genre_mix: up to 10 "{Genre} mix" playlists per
user, rebuilt daily with the other system mixes.
Which genres: library genres with at least 25 playable tracks across 3
artists, ranked in tiers — taste-profile genres first (matched
case-insensitively, so ID3 "Post-Punk" and folksonomy "post-punk" are one),
then genres the user has played or liked, then the rest of the library, which
only tops a short shelf up to 4. A genre whose artist set is a near
duplicate of one already picked (Jaccard >= 0.5) is skipped, so "Lo-Fi" and
"Lo-Fi Hip Hop" don't both appear but "Alternative Rock" survives "Rock". A
genre that can't fill 15 tracks gives way to the next.
Each mix is 50 tracks: 3 in 5 the user already knows (played through or
liked), the rest unheard in that genre, interleaved, with the usual
per-album/per-artist caps. Tracks skipped twice and more often than played
are left out. The order changes daily and holds within a day. Picks are
stamped taste / taste_unheard, and genre_mix plays count toward rotation and
the recommendation metrics.
Migration 0102 adds genre_mix to the playlists variant constraints.
Web and Android each get a "Your genres" row in name order, hidden until a
mix exists. Kinds with several playlists per user now play by playlist id
wherever the client used to test seed_artist_id (web card, detail page
self-heal), keyed on the server's refreshable flag; on Android genre_mix
joins songs_like_artist as not refreshable. The web detail page's
"mix was rebuilt" reload now finds a Songs-like or genre mix by name instead
of calling the by-kind shuffle, which those kinds don't have.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
1.8 KiB
SQL
44 lines
1.8 KiB
SQL
-- Genre mixes: one daily system playlist per genre the user listens to
|
|
-- ("Post-Punk mix", "Jazz mix", ...). Several per user, like
|
|
-- songs_like_artist, but seedless: the genre lives in the playlist name and
|
|
-- seed_artist_id is NULL.
|
|
--
|
|
-- Postgres has no ALTER CONSTRAINT for CHECK, so both constraints are
|
|
-- dropped and re-added with 'genre_mix' in the accepted set.
|
|
|
|
ALTER TABLE playlists DROP CONSTRAINT IF EXISTS playlists_kind_variant_consistent;
|
|
ALTER TABLE playlists
|
|
ADD CONSTRAINT playlists_kind_variant_consistent CHECK (
|
|
(kind = 'user' AND system_variant IS NULL)
|
|
OR
|
|
(kind = 'system' AND system_variant IN (
|
|
'for_you', 'songs_like_artist', 'discover',
|
|
'deep_cuts', 'rediscover', 'new_for_you',
|
|
'on_this_day', 'first_listens', 'genre_mix'
|
|
))
|
|
);
|
|
|
|
ALTER TABLE playlists DROP CONSTRAINT IF EXISTS playlists_seed_consistent;
|
|
ALTER TABLE playlists
|
|
ADD CONSTRAINT playlists_seed_consistent CHECK (
|
|
(system_variant IS NULL AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'for_you' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'discover' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'deep_cuts' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'rediscover' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'new_for_you' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'on_this_day' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'first_listens' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'genre_mix' AND seed_artist_id IS NULL)
|
|
OR
|
|
(system_variant = 'songs_like_artist' AND seed_artist_id IS NOT NULL)
|
|
);
|