Filter tracks with access_authorities#688
Conversation
| @@ -0,0 +1,9 @@ | |||
| BEGIN; | |||
There was a problem hiding this comment.
i wonder if an index on not null achieves the same thing here for us with storing less data (not sure, genuine Q)
| FROM tracks | ||
| WHERE isrc = ANY(@isrcs::text[]); No newline at end of file | ||
| WHERE isrc = ANY(@isrcs::text[]) | ||
| AND is_current = true |
| SELECT tr.track_id | ||
| FROM track_routes tr | ||
| JOIN tracks t ON t.track_id = tr.track_id AND t.is_current = true | ||
| AND t.access_authorities IS NULL |
There was a problem hiding this comment.
😢 sad we have to join tracks here now... Maybe we could filter later... we don't seem to be handling deleted tracks here for instance?
There was a problem hiding this comment.
oh good eye, yeah this will slow down all track pages for sure. i guess deleted tracks we still render a skeleton. for these... hmm
esindexer/esindexer.go
Outdated
| // For tracks: delete requested IDs from the index first, then re-index only those | ||
| // that still pass the filter (e.g. no access_authorities). So when a track gets | ||
| // access_authorities set, the next listen cycle removes it from search. | ||
| if collection == "tracks" { |
There was a problem hiding this comment.
oooh interesting edge case... haven't thought about changing things to/from programmable access
There was a problem hiding this comment.
per offline discussion we can actually cut the esindexer changes
There was a problem hiding this comment.
Pull request overview
Updates the API and notification audience selection to exclude “programmable distribution” tracks by filtering out rows where tracks.access_authorities is set, and adds regression tests plus a DB index intended to support the new filters.
Changes:
- Add
access_authoritiesto thetracksschema and exclude such tracks from chat blast remixer audience selection. - Filter several API queries (tracks fetch, resolve-by-permalink, ISRC lookup, genres metrics, events) to require
access_authorities IS NULL. - Add tests ensuring gated tracks are excluded from
/tracks,/resolve,/metrics/genres, and/events.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| sql/01_schema.sql | Schema sync: adds tracks.access_authorities and updates embedded chat_blast_audience function logic. |
| ddl/migrations/0191_tracks_access_authorities_partial_index.sql | Adds a partial index intended to support access_authorities IS NULL filtering. |
| ddl/functions/chat_blast_audience.sql | Excludes tracks with access_authorities from remixer audience selection. |
| api/v1_tracks_test.go | Adds test asserting /v1/full/tracks excludes gated tracks. |
| api/v1_resolve_test.go | Adds test asserting /v1/resolve returns 404 for gated tracks. |
| api/v1_metrics_genres_test.go | Adds test asserting genre metrics exclude gated tracks. |
| api/v1_events_test.go | Adds test asserting events for gated tracks are excluded. |
| api/dbv1/queries/get_tracks.sql | Filters GetTracks to require t.access_authorities IS NULL. |
| api/dbv1/queries/get_track_ids_by_permalink.sql | Filters permalink resolution to exclude gated tracks. |
| api/dbv1/queries/get_track_ids_by_isrc.sql | Filters ISRC lookup to current, ungated tracks. |
| api/dbv1/queries/get_genres.sql | Filters genre counts to exclude gated tracks. |
| api/dbv1/queries/get_events.sql | Filters track-typed events to exclude gated/deleted tracks via join conditions. |
| api/dbv1/models.go | Extends generated TrackRow model with AccessAuthorities. |
| api/dbv1/get_tracks.sql.go | Regenerated sqlc output reflecting GetTracks filter changes. |
| api/dbv1/get_track_ids_by_permalink.sql.go | Regenerated sqlc output reflecting permalink filter changes. |
| api/dbv1/get_track_ids_by_isrc.sql.go | Regenerated sqlc output reflecting ISRC filter changes. |
| api/dbv1/get_genres.sql.go | Regenerated sqlc output reflecting genres filter changes. |
| api/dbv1/get_events.sql.go | Regenerated sqlc output reflecting events filter changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| -- We index rows WHERE access_authorities IS NULL so our queries (which filter | ||
| -- access_authorities IS NULL) can use it. A partial index on IS NOT NULL would |
There was a problem hiding this comment.
The migration comment says “All track queries filter with access_authorities IS NULL”, but there are multiple non-sqlc queries in api/ that read from tracks and don’t currently apply that filter. This comment is misleading and could cause future changes to assume coverage that isn’t real; consider narrowing the wording (e.g., “dbv1 track queries used by …”) or ensuring the broader codebase is actually updated.
| -- We index rows WHERE access_authorities IS NULL so our queries (which filter | |
| -- access_authorities IS NULL) can use it. A partial index on IS NOT NULL would | |
| -- We index rows WHERE access_authorities IS NULL so queries that filter | |
| -- access_authorities IS NULL can use it. A partial index on IS NOT NULL would |
| -- access_authorities IS NULL) can use it. A partial index on IS NOT NULL would | ||
| -- store less but would never be used for those queries. | ||
| CREATE INDEX IF NOT EXISTS idx_tracks_access_authorities_null | ||
| ON tracks (track_id) |
There was a problem hiding this comment.
This partial index is on (track_id) only, which largely overlaps existing track_id-leading indexes (e.g. idx_track_status in schema) but adds extra write overhead. If the goal is to speed up the new access_authorities IS NULL filters, consider verifying with EXPLAIN that this index is actually chosen, or adjust the index to match the most expensive filtered queries (e.g. include additional columns / different leading columns) before adding another track_id index.
| ON tracks (track_id) | |
| ON tracks (access_authorities, track_id) |
| var before struct { | ||
| Data []struct { | ||
| Name string `json:"name"` | ||
| Count int64 `json:"count"` | ||
| } |
There was a problem hiding this comment.
This test unmarshals name, but TestMetricsGenres in the same file unmarshals genre and can silently pass without asserting anything. Update the older test to use the same response shape (name) and add a real assertion (e.g., expect at least one known genre) so the baseline coverage is meaningful.
| @@ -35,6 +35,8 @@ BEGIN | |||
| AND chat_blast.audience = 'remixer_audience' | |||
There was a problem hiding this comment.
The remixer_audience query filters on access_authorities IS NULL but doesn’t restrict t/og to is_current = true. Since tracks is versioned (has txhash+track_id PK and is_current), an older row with NULL access_authorities could match even when the current track is gated. Add t.is_current = true and og.is_current = true (preferably in the JOINs) so the exclusion applies to the current track state.
| AND og.owner_id = chat_blast.from_user_id | ||
| AND t.owner_id != chat_blast.from_user_id | ||
| AND t.access_authorities IS NULL | ||
| AND og.access_authorities IS NULL |
There was a problem hiding this comment.
Same as in ddl/functions/chat_blast_audience.sql: the remixer_audience audience selection filters on access_authorities IS NULL but does not restrict to is_current = true. If historical rows exist, a gated track could still pass via an older is_current=false row with NULL access_authorities. Add t.is_current = true and og.is_current = true so gated tracks can’t be included via stale rows.
| AND og.access_authorities IS NULL | |
| AND og.access_authorities IS NULL | |
| AND t.is_current = true | |
| AND og.is_current = true |
| @@ -209,5 +209,6 @@ LEFT JOIN aggregate_plays on play_item_id = t.track_id | |||
| LEFT JOIN track_routes on t.track_id = track_routes.track_id and track_routes.is_current = true | |||
| WHERE (is_unlisted = false OR t.owner_id = @my_id OR @include_unlisted::bool = TRUE) | |||
| AND t.track_id = ANY(@ids::int[]) | |||
There was a problem hiding this comment.
GetTracks filters out gated tracks with t.access_authorities IS NULL, but it doesn’t filter t.is_current = true. Since tracks is versioned (PK includes txhash and has is_current), a track whose current row is gated could still be returned via an older is_current=false row where access_authorities is NULL. Add AND t.is_current = true (and ensure joins/selects are consistent) so the exclusion can’t be bypassed via historical rows.
| AND t.track_id = ANY(@ids::int[]) | |
| AND t.track_id = ANY(@ids::int[]) | |
| AND t.is_current = true |
No description provided.