From 499786cab984be42033c56c52ada7c5b5fa64365 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 10 Jun 2025 08:30:26 +0200 Subject: [PATCH] Introduced Backend.Close method This allows Backend implementations to free used resources. Currently used for musicbrainzws2.Client --- internal/backends/deezer/deezer.go | 2 ++ internal/backends/deezerhistory/deezerhistory.go | 2 ++ internal/backends/dump/dump.go | 2 ++ internal/backends/funkwhale/funkwhale.go | 2 ++ internal/backends/jspf/jspf.go | 2 ++ internal/backends/lastfm/lastfm.go | 2 ++ internal/backends/lbarchive/lbarchive.go | 14 ++++++++++---- internal/backends/listenbrainz/listenbrainz.go | 14 ++++++++++---- internal/backends/maloja/maloja.go | 2 ++ internal/backends/scrobblerlog/scrobblerlog.go | 2 ++ internal/backends/spotify/spotify.go | 2 ++ internal/backends/spotifyhistory/spotifyhistory.go | 2 ++ internal/backends/subsonic/subsonic.go | 2 ++ internal/models/interfaces.go | 3 +++ 14 files changed, 45 insertions(+), 8 deletions(-) diff --git a/internal/backends/deezer/deezer.go b/internal/backends/deezer/deezer.go index 9d622df..f70a2c9 100644 --- a/internal/backends/deezer/deezer.go +++ b/internal/backends/deezer/deezer.go @@ -38,6 +38,8 @@ type DeezerApiBackend struct { func (b *DeezerApiBackend) Name() string { return "deezer" } +func (b *DeezerApiBackend) Close() {} + func (b *DeezerApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "client-id", diff --git a/internal/backends/deezerhistory/deezerhistory.go b/internal/backends/deezerhistory/deezerhistory.go index 5574a5d..9c74368 100644 --- a/internal/backends/deezerhistory/deezerhistory.go +++ b/internal/backends/deezerhistory/deezerhistory.go @@ -43,6 +43,8 @@ type DeezerHistoryBackend struct { func (b *DeezerHistoryBackend) Name() string { return "deezer-history" } +func (b *DeezerHistoryBackend) Close() {} + func (b *DeezerHistoryBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "file-path", diff --git a/internal/backends/dump/dump.go b/internal/backends/dump/dump.go index 8d7c641..b342ba5 100644 --- a/internal/backends/dump/dump.go +++ b/internal/backends/dump/dump.go @@ -36,6 +36,8 @@ type DumpBackend struct { func (b *DumpBackend) Name() string { return "dump" } +func (b *DumpBackend) Close() {} + func (b *DumpBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "file-path", diff --git a/internal/backends/funkwhale/funkwhale.go b/internal/backends/funkwhale/funkwhale.go index 8874c70..8039ec2 100644 --- a/internal/backends/funkwhale/funkwhale.go +++ b/internal/backends/funkwhale/funkwhale.go @@ -36,6 +36,8 @@ type FunkwhaleApiBackend struct { func (b *FunkwhaleApiBackend) Name() string { return "funkwhale" } +func (b *FunkwhaleApiBackend) Close() {} + func (b *FunkwhaleApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "server-url", diff --git a/internal/backends/jspf/jspf.go b/internal/backends/jspf/jspf.go index 887fd72..cdbb23e 100644 --- a/internal/backends/jspf/jspf.go +++ b/internal/backends/jspf/jspf.go @@ -46,6 +46,8 @@ type JSPFBackend struct { func (b *JSPFBackend) Name() string { return "jspf" } +func (b *JSPFBackend) Close() {} + func (b *JSPFBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "file-path", diff --git a/internal/backends/lastfm/lastfm.go b/internal/backends/lastfm/lastfm.go index 186a631..ebe226a 100644 --- a/internal/backends/lastfm/lastfm.go +++ b/internal/backends/lastfm/lastfm.go @@ -46,6 +46,8 @@ type LastfmApiBackend struct { func (b *LastfmApiBackend) Name() string { return "lastfm" } +func (b *LastfmApiBackend) Close() {} + func (b *LastfmApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "username", diff --git a/internal/backends/lbarchive/lbarchive.go b/internal/backends/lbarchive/lbarchive.go index a91c0a5..ce23795 100644 --- a/internal/backends/lbarchive/lbarchive.go +++ b/internal/backends/lbarchive/lbarchive.go @@ -42,11 +42,17 @@ const ( type ListenBrainzArchiveBackend struct { filePath string lbClient listenbrainz.Client - mbClient musicbrainzws2.Client + mbClient *musicbrainzws2.Client } func (b *ListenBrainzArchiveBackend) Name() string { return "listenbrainz-archive" } +func (b *ListenBrainzArchiveBackend) Close() { + if b.mbClient != nil { + b.mbClient.Close() + } +} + func (b *ListenBrainzArchiveBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "archive-path", @@ -58,7 +64,7 @@ func (b *ListenBrainzArchiveBackend) Options() []models.BackendOption { func (b *ListenBrainzArchiveBackend) InitConfig(config *config.ServiceConfig) error { b.filePath = config.GetString("archive-path") b.lbClient = listenbrainz.NewClient("", version.UserAgent()) - b.mbClient = *musicbrainzws2.NewClient(musicbrainzws2.AppInfo{ + b.mbClient = musicbrainzws2.NewClient(musicbrainzws2.AppInfo{ Name: version.AppName, Version: version.AppVersion, URL: version.AppURL, @@ -191,7 +197,7 @@ func (b *ListenBrainzArchiveBackend) ExportLoves( if len(batch) >= lovesBatchSize { // The dump does not contain track metadata. Extend it with additional // lookups - loves, err := lbapi.ExtendTrackMetadata(ctx, &b.lbClient, &b.mbClient, &batch) + loves, err := lbapi.ExtendTrackMetadata(ctx, &b.lbClient, b.mbClient, &batch) if err != nil { p.Export.Abort() progress <- p @@ -205,7 +211,7 @@ func (b *ListenBrainzArchiveBackend) ExportLoves( } } - loves, err := lbapi.ExtendTrackMetadata(ctx, &b.lbClient, &b.mbClient, &batch) + loves, err := lbapi.ExtendTrackMetadata(ctx, &b.lbClient, b.mbClient, &batch) if err != nil { p.Export.Abort() progress <- p diff --git a/internal/backends/listenbrainz/listenbrainz.go b/internal/backends/listenbrainz/listenbrainz.go index 98d1525..b809b47 100644 --- a/internal/backends/listenbrainz/listenbrainz.go +++ b/internal/backends/listenbrainz/listenbrainz.go @@ -36,12 +36,18 @@ const lovesBatchSize = listenbrainz.MaxItemsPerGet type ListenBrainzApiBackend struct { client listenbrainz.Client - mbClient musicbrainzws2.Client + mbClient *musicbrainzws2.Client username string checkDuplicates bool existingMBIDs map[mbtypes.MBID]bool } +func (b *ListenBrainzApiBackend) Close() { + if b.mbClient != nil { + b.mbClient.Close() + } +} + func (b *ListenBrainzApiBackend) Name() string { return "listenbrainz" } func (b *ListenBrainzApiBackend) Options() []models.BackendOption { @@ -62,7 +68,7 @@ func (b *ListenBrainzApiBackend) Options() []models.BackendOption { func (b *ListenBrainzApiBackend) InitConfig(config *config.ServiceConfig) error { b.client = listenbrainz.NewClient(config.GetString("token"), version.UserAgent()) - b.mbClient = *musicbrainzws2.NewClient(musicbrainzws2.AppInfo{ + b.mbClient = musicbrainzws2.NewClient(musicbrainzws2.AppInfo{ Name: version.AppName, Version: version.AppVersion, URL: version.AppURL, @@ -261,7 +267,7 @@ out: // Missing track metadata indicates that the recording MBID is no // longer available and might have been merged. Try fetching details // from MusicBrainz. - lovesBatch, err := ExtendTrackMetadata(ctx, &b.client, &b.mbClient, &batch) + lovesBatch, err := ExtendTrackMetadata(ctx, &b.client, b.mbClient, &batch) if err != nil { results <- models.LovesResult{Error: err} return @@ -276,7 +282,7 @@ out: offset += listenbrainz.MaxItemsPerGet } - lovesBatch, err := ExtendTrackMetadata(ctx, &b.client, &b.mbClient, &batch) + lovesBatch, err := ExtendTrackMetadata(ctx, &b.client, b.mbClient, &batch) if err != nil { results <- models.LovesResult{Error: err} return diff --git a/internal/backends/maloja/maloja.go b/internal/backends/maloja/maloja.go index d85309f..e5537df 100644 --- a/internal/backends/maloja/maloja.go +++ b/internal/backends/maloja/maloja.go @@ -35,6 +35,8 @@ type MalojaApiBackend struct { func (b *MalojaApiBackend) Name() string { return "maloja" } +func (b *MalojaApiBackend) Close() {} + func (b *MalojaApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "server-url", diff --git a/internal/backends/scrobblerlog/scrobblerlog.go b/internal/backends/scrobblerlog/scrobblerlog.go index 13aecba..3a91e92 100644 --- a/internal/backends/scrobblerlog/scrobblerlog.go +++ b/internal/backends/scrobblerlog/scrobblerlog.go @@ -41,6 +41,8 @@ type ScrobblerLogBackend struct { func (b *ScrobblerLogBackend) Name() string { return "scrobbler-log" } +func (b *ScrobblerLogBackend) Close() {} + func (b *ScrobblerLogBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "file-path", diff --git a/internal/backends/spotify/spotify.go b/internal/backends/spotify/spotify.go index fbfe821..85b40dd 100644 --- a/internal/backends/spotify/spotify.go +++ b/internal/backends/spotify/spotify.go @@ -41,6 +41,8 @@ type SpotifyApiBackend struct { func (b *SpotifyApiBackend) Name() string { return "spotify" } +func (b *SpotifyApiBackend) Close() {} + func (b *SpotifyApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "client-id", diff --git a/internal/backends/spotifyhistory/spotifyhistory.go b/internal/backends/spotifyhistory/spotifyhistory.go index 5f67604..985469f 100644 --- a/internal/backends/spotifyhistory/spotifyhistory.go +++ b/internal/backends/spotifyhistory/spotifyhistory.go @@ -36,6 +36,8 @@ type SpotifyHistoryBackend struct { func (b *SpotifyHistoryBackend) Name() string { return "spotify-history" } +func (b *SpotifyHistoryBackend) Close() {} + func (b *SpotifyHistoryBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "archive-path", diff --git a/internal/backends/subsonic/subsonic.go b/internal/backends/subsonic/subsonic.go index f75366d..1ffa510 100644 --- a/internal/backends/subsonic/subsonic.go +++ b/internal/backends/subsonic/subsonic.go @@ -37,6 +37,8 @@ type SubsonicApiBackend struct { func (b *SubsonicApiBackend) Name() string { return "subsonic" } +func (b *SubsonicApiBackend) Close() {} + func (b *SubsonicApiBackend) Options() []models.BackendOption { return []models.BackendOption{{ Name: "server-url", diff --git a/internal/models/interfaces.go b/internal/models/interfaces.go index 79a4c6c..0f287bf 100644 --- a/internal/models/interfaces.go +++ b/internal/models/interfaces.go @@ -35,6 +35,9 @@ type Backend interface { // Return configuration options Options() []BackendOption + + // Free all resources of the backend + Close() } type ImportBackend interface {