Files
minstrel/internal/coverart/provider_mbcaa.go
T
bvandeusen 1e3a76eba8 feat(server/m7-cover-sources): MBCAA provider wrapper
Adapts the existing Fetcher-based MBCAA client to the new Provider
abstraction. mbcaaProvider embeds *Fetcher and implements
Provider + AlbumCoverProvider + TestableProvider. init() registers a
default-config instance; NewMBCAAProviderFromConfig swaps in
production config (User-Agent, MinPeriod) at boot.

Wrapper approach (rather than reimplementing the HTTP logic) keeps
the package compiling during the T4–T8 window: enricher.go and
main.go still reference the legacy Fetcher type / NewFetcher
constructor / Fetch method, all of which remain unchanged in
fetcher.go. A-T8 will consolidate the HTTP logic into this file and
delete fetcher.go after the enricher rewrite removes the last
legacy call sites.

TestConnection hits a hardcoded popular release MBID (Beatles
"Abbey Road" UK release) and treats both 200 and 404 as "connection
works" — MBCAA needs no auth, so only 5xx / network failures
surface. Tests cover ID/DisplayName/Capability metadata, success
path, 404→ErrNotFound, disabled-returns-ErrNotFound, Configure
toggle, TestConnection variants, and NewMBCAAProviderFromConfig
swap.
2026-05-06 12:35:35 -04:00

92 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package coverart
import (
"context"
"errors"
"sync/atomic"
)
// mbcaaProvider implements Provider, AlbumCoverProvider, and
// TestableProvider. It wraps an *Fetcher (the existing
// MBCAA-specific HTTP client) for the actual fetch logic, adapting
// the Fetcher's Fetch method to the AlbumCoverProvider interface.
//
// The wrapping (rather than reimplementing) is temporary: A-T8 will
// consolidate fetcher.go's logic into this file and delete fetcher.go.
// During the T4T8 window, this struct lets the new provider chain
// coexist with the legacy Fetcher used by enricher.go and main.go.
type mbcaaProvider struct {
fetcher *Fetcher
enabled atomic.Bool
}
// Sample MBID used by TestConnection. The Beatles' "Abbey Road" UK
// release; verified present on MBCAA at design time. Both 200 (image
// returned) and 404 (no art for the sample) are treated as "connection
// works" since MBCAA needs no auth — only network failures surface.
const mbcaaTestSampleMBID = "f4b3df80-8a6c-3e87-b51e-5c1ee70a78ee"
func init() {
// Register with a default-config Fetcher. main.go (in A-T8) will
// call NewMBCAAProviderFromConfig to swap in the production
// User-Agent + MinPeriod. Default config values come from
// FetcherConfig's zero-value handling in NewFetcher.
Register(&mbcaaProvider{
fetcher: NewFetcher(FetcherConfig{}),
})
}
// NewMBCAAProviderFromConfig replaces the registered MBCAA provider's
// internal Fetcher with one built from the supplied config. main.go
// calls this at boot to set the production User-Agent. Idempotent;
// safe to call repeatedly.
func NewMBCAAProviderFromConfig(cfg FetcherConfig) {
p, err := ProviderByID("mbcaa")
if err != nil {
// init() should have registered it; if not, register fresh.
Register(&mbcaaProvider{fetcher: NewFetcher(cfg)})
return
}
mp, ok := p.(*mbcaaProvider)
if !ok {
// Some other provider claimed the "mbcaa" ID — registry bug.
panic("coverart: provider with ID 'mbcaa' is not *mbcaaProvider")
}
mp.fetcher = NewFetcher(cfg)
}
func (p *mbcaaProvider) ID() string { return "mbcaa" }
func (p *mbcaaProvider) DisplayName() string { return "Cover Art Archive" }
func (p *mbcaaProvider) RequiresAPIKey() bool { return false }
func (p *mbcaaProvider) DefaultEnabled() bool { return true }
func (p *mbcaaProvider) Configure(s ProviderSettings) error {
p.enabled.Store(s.Enabled)
return nil // MBCAA has no per-operator config beyond enabled
}
// FetchAlbumCover delegates to the wrapped Fetcher. The Fetcher's
// existing Fetch method already returns ErrNotFound / ErrTransient
// per the contract, so no error mapping is needed.
func (p *mbcaaProvider) FetchAlbumCover(ctx context.Context, mbid string) ([]byte, error) {
if !p.enabled.Load() {
return nil, ErrNotFound // defensive; enricher already filters on enabled
}
return p.fetcher.Fetch(ctx, mbid)
}
// TestConnection hits the sample MBID's front-500 endpoint. A 200
// (image bytes) or 404 (no art for sample) both indicate the
// connection works; 5xx / network errors surface as TestConnection
// failures.
func (p *mbcaaProvider) TestConnection(ctx context.Context) error {
_, err := p.fetcher.Fetch(ctx, mbcaaTestSampleMBID)
if err == nil {
return nil
}
if errors.Is(err, ErrNotFound) {
return nil
}
return err
}