feat: fetch all artist albums with caching, filter by type in handler
- Provider fetches all release groups via paginated browse, no type filter - Service caches all albums in DB, ensures referenced artists exist first - Server handler filters by album_types (default: album|ep|single), excludes secondary types - Add secondary_types to domain, DB schema, and MB types - Add ErrBadRequest handling for MusicBrainz 400 errors - Replace migrations with single schema.sql - Add GetAllByArtistID and SaveAll to album repository
This commit is contained in:
@@ -107,6 +107,12 @@ func (c *client) readResponse(ctx context.Context, resp *http.Response, endpoint
|
||||
metrics.ProviderRequests.WithLabelValues("musicbrainz", endpoint, "ok").Inc()
|
||||
return io.ReadAll(resp.Body)
|
||||
|
||||
case http.StatusBadRequest:
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
log.Warn().Str("endpoint", endpoint).Str("body", string(body)).Dur("duration", duration).Msg("HTTP 400 bad request")
|
||||
metrics.ProviderRequests.WithLabelValues("musicbrainz", endpoint, "bad_request").Inc()
|
||||
return nil, fmt.Errorf("%w: %s", ErrBadRequest, extractErrorMessage(body))
|
||||
|
||||
case http.StatusNotFound:
|
||||
log.Debug().Str("endpoint", endpoint).Dur("duration", duration).Msg("HTTP 404")
|
||||
metrics.ProviderRequests.WithLabelValues("musicbrainz", endpoint, "not_found").Inc()
|
||||
@@ -137,17 +143,12 @@ func (c *client) lookup(ctx context.Context, entity, id string, inc []string) ([
|
||||
}
|
||||
|
||||
func (c *client) browse(ctx context.Context, entity, linkedEntity, linkedID string, limit, offset int, inc []string) ([]byte, error) {
|
||||
return c.browseWithTypes(ctx, entity, linkedEntity, linkedID, limit, offset, inc, nil)
|
||||
}
|
||||
|
||||
func (c *client) browseWithTypes(ctx context.Context, entity, linkedEntity, linkedID string, limit, offset int, inc []string, types []string) ([]byte, error) {
|
||||
zerolog.Ctx(ctx).Debug().
|
||||
Str("entity", entity).
|
||||
Str("linked_entity", linkedEntity).
|
||||
Str("linked_id", linkedID).
|
||||
Int("limit", limit).
|
||||
Int("offset", offset).
|
||||
Strs("types", types).
|
||||
Msg("provider browse")
|
||||
|
||||
params := url.Values{}
|
||||
@@ -159,10 +160,6 @@ func (c *client) browseWithTypes(ctx context.Context, entity, linkedEntity, link
|
||||
params.Set("inc", joined)
|
||||
}
|
||||
|
||||
if typeStr := strings.Join(types, "|"); typeStr != "" {
|
||||
params.Set("type", typeStr)
|
||||
}
|
||||
|
||||
return c.get(ctx, entity, params)
|
||||
}
|
||||
|
||||
@@ -184,6 +181,16 @@ func joinIncludes(inc []string) string {
|
||||
return strings.Join(inc, "+")
|
||||
}
|
||||
|
||||
func extractErrorMessage(body []byte) string {
|
||||
var errResp struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
if json.Unmarshal(body, &errResp) == nil && errResp.Error != "" {
|
||||
return errResp.Error
|
||||
}
|
||||
return string(body)
|
||||
}
|
||||
|
||||
func decode[T any](data []byte) (*T, error) {
|
||||
var result T
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user