Rewrites the internal/db/queries comments to rule 32 and regenerates dbq, whose doc comments and embedded SQL carry them. The bugs behind the tiered mixes, the md5 order seed, the score bands and the round-robin arms are restated as the constraint each one enforces; counts from one library and stale cross-references are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
79 lines
2.8 KiB
Go
79 lines
2.8 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
||
// versions:
|
||
// sqlc v1.31.1
|
||
// source: coplay.sql
|
||
|
||
package dbq
|
||
|
||
import (
|
||
"context"
|
||
)
|
||
|
||
const deleteArtistCoplayEdges = `-- name: DeleteArtistCoplayEdges :exec
|
||
|
||
DELETE FROM artist_similarity WHERE source = 'user_cooccurrence'
|
||
`
|
||
|
||
// Household co-play similarity. Minstrel is a
|
||
// single shared-library, multi-user server (no per-user library ACL), so the
|
||
// "household" is the whole instance's user set. These queries recompute
|
||
// artist–artist co-occurrence edges from play_events and store them in
|
||
// artist_similarity under the pre-provisioned source = 'user_cooccurrence'
|
||
// (whitelisted in the 0009 CHECK from day one). A periodic worker DELETEs then
|
||
// re-INSERTs so edges that fall below threshold disappear. Single-user servers
|
||
// produce no edges (the >= 2 co-player gate), so the arm is empty there.
|
||
func (q *Queries) DeleteArtistCoplayEdges(ctx context.Context) error {
|
||
_, err := q.db.Exec(ctx, deleteArtistCoplayEdges)
|
||
return err
|
||
}
|
||
|
||
const insertArtistCoplayEdges = `-- name: InsertArtistCoplayEdges :exec
|
||
WITH user_artists AS (
|
||
SELECT DISTINCT pe.user_id, t.artist_id
|
||
FROM play_events pe
|
||
JOIN tracks t ON t.id = pe.track_id
|
||
WHERE pe.was_skipped = false
|
||
AND pe.started_at > now() - interval '365 days'
|
||
),
|
||
artist_players AS (
|
||
SELECT artist_id, count(*)::float8 AS players
|
||
FROM user_artists
|
||
GROUP BY artist_id
|
||
),
|
||
pairs AS (
|
||
SELECT ua.artist_id AS a_id,
|
||
ub.artist_id AS b_id,
|
||
count(*)::float8 AS coplayers
|
||
FROM user_artists ua
|
||
JOIN user_artists ub
|
||
ON ua.user_id = ub.user_id AND ua.artist_id <> ub.artist_id
|
||
GROUP BY ua.artist_id, ub.artist_id
|
||
HAVING count(*) >= 2
|
||
),
|
||
scored AS (
|
||
SELECT p.a_id, p.b_id,
|
||
p.coplayers / (pa.players + pb.players - p.coplayers) AS score
|
||
FROM pairs p
|
||
JOIN artist_players pa ON pa.artist_id = p.a_id
|
||
JOIN artist_players pb ON pb.artist_id = p.b_id
|
||
)
|
||
INSERT INTO artist_similarity (artist_a_id, artist_b_id, score, source, fetched_at)
|
||
SELECT a_id, b_id, score, 'user_cooccurrence', now()
|
||
FROM scored
|
||
WHERE score >= $1
|
||
ON CONFLICT (artist_a_id, artist_b_id, source)
|
||
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at
|
||
`
|
||
|
||
// Two artists are "co-played" when the same users play both. score is the
|
||
// Jaccard of their distinct-player sets — coplayers / (playersA + playersB −
|
||
// coplayers) in (0,1] — which controls for globally-popular artists (an artist
|
||
// everyone plays would otherwise co-occur with everything). Only pairs with
|
||
// >= 2 distinct co-players AND Jaccard >= $1 (a floor that both prunes weak
|
||
// edges and self-limits hub artists, whose large denominators drag their
|
||
// Jaccard down) are kept. Completed plays only, 365-day window.
|
||
func (q *Queries) InsertArtistCoplayEdges(ctx context.Context, score float64) error {
|
||
_, err := q.db.Exec(ctx, insertArtistCoplayEdges, score)
|
||
return err
|
||
}
|