Refactor included handling

This commit is contained in:
Deluan 2023-05-23 21:15:54 -04:00 committed by Deluan
parent 40f7170930
commit 7cf98af9da
3 changed files with 109 additions and 70 deletions

View file

@ -1,7 +1,6 @@
package model
import (
"strings"
"time"
"github.com/navidrome/navidrome/utils/slice"
@ -61,6 +60,10 @@ func (a Album) CoverArtID() ArtworkID {
return artworkIDFromAlbum(a)
}
func (a Album) ArtistIDs() []string {
return []string{a.ArtistID, a.AlbumArtistID}
}
type DiscID struct {
AlbumID string `json:"albumId"`
ReleaseDate string `json:"releaseDate"`
@ -95,7 +98,7 @@ func (als Albums) ToAlbumArtist() Artist {
func (als Albums) ArtistIDs() []string {
var ids []string
for _, al := range als {
ids = append(ids, strings.Split(al.AllArtistIDs, " ")...)
ids = append(ids, al.ArtistIDs()...)
}
return ids
}

View file

@ -73,21 +73,18 @@ func (a *Router) GetTracks(ctx context.Context, request GetTracksRequestObject)
}
baseUrl := baseResourceUrl(ctx, "tracks")
links, meta := buildPaginationLinksAndMeta(int32(cnt), request.Params, baseUrl)
resources := includedResources{ctx: ctx, ds: a.ds, includes: request.Params.Include}
err = resources.AddArtists(mfs.ArtistIDs()...)
if err != nil {
return nil, err
resources := newIncludedResources(ctx, a.ds, request.Params.Include)
resources.Artists(mfs.ArtistIDs()...)
resources.Albums(mfs.AlbumIDs()...)
response := GetTracks200JSONResponse{
Data: toAPITracks(mfs),
Links: links,
Meta: &meta,
}
err = resources.AddAlbums(mfs.AlbumIDs()...)
if err != nil {
return nil, err
}
return GetTracks200JSONResponse{
Data: toAPITracks(mfs),
Links: links,
Meta: &meta,
Included: resources.Build(),
}, nil
response.Included, err = resources.Build()
return response, err
}
func (a *Router) GetTrack(ctx context.Context, request GetTrackRequestObject) (GetTrackResponseObject, error) {
@ -95,19 +92,16 @@ func (a *Router) GetTrack(ctx context.Context, request GetTrackRequestObject) (G
if err != nil {
return nil, err
}
resources := includedResources{ctx: ctx, ds: a.ds, includes: request.Params.Include}
err = resources.AddArtists(mf.ArtistID, mf.AlbumArtistID)
if err != nil {
return nil, err
resources := newIncludedResources(ctx, a.ds, request.Params.Include)
resources.Artists(mf.ArtistID, mf.AlbumArtistID)
resources.Albums(mf.AlbumID)
response := GetTrack200JSONResponse{
Data: toAPITrack(*mf),
}
err = resources.AddAlbums(mf.AlbumID)
if err != nil {
return nil, err
}
return GetTrack200JSONResponse{
Data: toAPITrack(*mf),
Included: resources.Build(),
}, nil
response.Included, err = resources.Build()
return response, err
}
func (a *Router) GetAlbums(ctx context.Context, request GetAlbumsRequestObject) (GetAlbumsResponseObject, error) {
@ -122,17 +116,17 @@ func (a *Router) GetAlbums(ctx context.Context, request GetAlbumsRequestObject)
}
baseUrl := baseResourceUrl(ctx, "albums")
links, meta := buildPaginationLinksAndMeta(int32(cnt), request.Params, baseUrl)
resources := includedResources{ctx: ctx, ds: a.ds, includes: request.Params.Include}
err = resources.AddArtists(albums.ArtistIDs()...)
if err != nil {
return nil, err
resources := newIncludedResources(ctx, a.ds, request.Params.Include)
resources.Artists(albums.ArtistIDs()...)
response := GetAlbums200JSONResponse{
Data: toAPIAlbums(albums),
Links: links,
Meta: &meta,
}
return GetAlbums200JSONResponse{
Data: toAPIAlbums(albums),
Links: links,
Meta: &meta,
Included: resources.Build(),
}, nil
response.Included, err = resources.Build()
return response, err
}
func (a *Router) GetAlbum(ctx context.Context, request GetAlbumRequestObject) (GetAlbumResponseObject, error) {
@ -140,19 +134,16 @@ func (a *Router) GetAlbum(ctx context.Context, request GetAlbumRequestObject) (G
if err != nil {
return nil, err
}
resources := includedResources{ctx: ctx, ds: a.ds, includes: request.Params.Include}
err = resources.AddArtists(album.ArtistID, album.AlbumArtistID)
if err != nil {
return nil, err
resources := newIncludedResources(ctx, a.ds, request.Params.Include)
resources.Artists(album.ArtistID, album.AlbumArtistID)
resources.Tracks(album.ID)
response := GetAlbum200JSONResponse{
Data: toAPIAlbum(*album),
}
err = resources.AddTracks(album.ID)
if err != nil {
return nil, err
}
return GetAlbum200JSONResponse{
Data: toAPIAlbum(*album),
Included: resources.Build(),
}, nil
response.Included, err = resources.Build()
return response, err
}
func (a *Router) GetArtists(ctx context.Context, request GetArtistsRequestObject) (GetArtistsResponseObject, error) {

View file

@ -14,14 +14,46 @@ type includedResources struct {
ds model.DataStore
includes *includeSlice
resources []IncludedResource
ids map[ResourceType][]string
}
func (i *includedResources) AddTracks(albumIds ...string) error {
if i.includes == nil || !slices.Contains(*i.includes, string(ResourceTypeTrack)) {
return nil
func newIncludedResources(ctx context.Context, ds model.DataStore, includes *includeSlice) *includedResources {
i := &includedResources{
ctx: ctx,
ds: ds,
includes: includes,
}
sort.Strings(albumIds)
slices.Compact(albumIds)
if includes != nil {
i.ids = make(map[ResourceType][]string)
for _, inc := range *includes {
i.ids[ResourceType(inc)] = []string{}
}
}
return i
}
func (i *includedResources) Tracks(trackIds ...string) {
if i.ids == nil || i.ids[ResourceTypeTrack] == nil {
return
}
i.ids[ResourceTypeTrack] = append(i.ids[ResourceTypeTrack], trackIds...)
}
func (i *includedResources) Albums(albumIds ...string) {
if i.ids == nil || i.ids[ResourceTypeAlbum] == nil {
return
}
i.ids[ResourceTypeAlbum] = append(i.ids[ResourceTypeAlbum], albumIds...)
}
func (i *includedResources) Artists(artistIds ...string) {
if i.ids == nil || i.ids[ResourceTypeArtist] == nil {
return
}
i.ids[ResourceTypeArtist] = append(i.ids[ResourceTypeArtist], artistIds...)
}
func (i *includedResources) addTracks(albumIds []string) error {
tracks, err := i.ds.MediaFile(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"album_id": albumIds}})
if err != nil {
return err
@ -34,12 +66,7 @@ func (i *includedResources) AddTracks(albumIds ...string) error {
return nil
}
func (i *includedResources) AddAlbums(albumIds ...string) error {
if i.includes == nil || !slices.Contains(*i.includes, string(ResourceTypeAlbum)) {
return nil
}
sort.Strings(albumIds)
slices.Compact(albumIds)
func (i *includedResources) addAlbums(albumIds []string) error {
albums, err := i.ds.Album(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"id": albumIds}})
if err != nil {
return err
@ -52,12 +79,7 @@ func (i *includedResources) AddAlbums(albumIds ...string) error {
return nil
}
func (i *includedResources) AddArtists(artistIds ...string) error {
if i.includes == nil || !slices.Contains(*i.includes, string(ResourceTypeArtist)) {
return nil
}
sort.Strings(artistIds)
slices.Compact(artistIds)
func (i *includedResources) addArtists(artistIds []string) error {
artists, err := i.ds.Artist(i.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"artist.id": artistIds}})
if err != nil {
return err
@ -70,9 +92,32 @@ func (i *includedResources) AddArtists(artistIds ...string) error {
return nil
}
func (i *includedResources) Build() *[]IncludedResource {
func (i *includedResources) Build() (*[]IncludedResource, error) {
if i.includes == nil {
return nil
return nil, nil
}
return &i.resources
for _, typ := range *i.includes {
ids := i.ids[ResourceType(typ)]
sort.Strings(ids)
slices.Compact(ids)
if len(ids) == 0 {
continue
}
switch ResourceType(typ) {
case ResourceTypeAlbum:
if err := i.addAlbums(ids); err != nil {
return nil, err
}
case ResourceTypeArtist:
if err := i.addArtists(ids); err != nil {
return nil, err
}
case ResourceTypeTrack:
if err := i.addTracks(ids); err != nil {
return nil, err
}
}
}
return &i.resources, nil
}