diff --git a/config/config.exs b/config/config.exs index fe5fdb56..faf9a8d1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -78,7 +78,7 @@ config :phoenix, :json_library, JSON config :music_library, Oban, engine: Oban.Engines.Lite, - queues: [default: 10, heavy_writes: 1, music_brainz: 1], + queues: [default: 10, heavy_writes: 1, music_brainz: 1, discogs: 1], repo: MusicLibrary.BackgroundRepo, plugins: [ {Oban.Plugins.Cron, diff --git a/lib/music_library/artists.ex b/lib/music_library/artists.ex index 5a386b5c..1567f46f 100644 --- a/lib/music_library/artists.ex +++ b/lib/music_library/artists.ex @@ -100,6 +100,50 @@ defmodule MusicLibrary.Artists do end end + def refresh_musicbrainz_data(artist_id) do + with {:ok, musicbrainz_artist} <- MusicBrainz.get_artist(artist_id) do + get_artist_info!(artist_id) + |> ArtistInfo.changeset(%{musicbrainz_data: musicbrainz_artist.musicbrainz_data}) + |> Repo.update() + end + end + + def refresh_musicbrainz_data_async(artist_info) do + meta = %{} + params = %{"id" => artist_info.id} + + params + |> Worker.ArtistRefreshMusicBrainzData.new(meta: meta) + |> BackgroundRepo.insert() + end + + def refresh_discogs_data(artist_id) do + artist_info = get_artist_info!(artist_id) + + if discogs_id = ArtistInfo.discogs_id(artist_info) do + case Discogs.get_artist(discogs_id) do + {:ok, discogs_artist} -> + artist_info + |> ArtistInfo.changeset(%{discogs_data: discogs_artist}) + |> Repo.update() + + error -> + error + end + else + {:ok, artist_info} + end + end + + def refresh_discogs_data_async(artist_info) do + meta = %{} + params = %{"id" => artist_info.id} + + params + |> Worker.ArtistRefreshDiscogsData.new(meta: meta) + |> BackgroundRepo.insert() + end + def create_artist_info(attrs) do %ArtistInfo{} |> ArtistInfo.changeset(attrs) diff --git a/lib/music_library/artists/artist_info.ex b/lib/music_library/artists/artist_info.ex index b13bff89..cd4b7765 100644 --- a/lib/music_library/artists/artist_info.ex +++ b/lib/music_library/artists/artist_info.ex @@ -71,4 +71,11 @@ defmodule MusicLibrary.Artists.ArtistInfo do def external_links(artist_info), do: ExternalLink.external_links(artist_info.musicbrainz_data, @external_link_patterns) + + def discogs_id(artist_info) do + case artist_info.discogs_data do + %{"id" => discogs_id} -> discogs_id + _ -> nil + end + end end diff --git a/lib/music_library/artists/batch.ex b/lib/music_library/artists/batch.ex new file mode 100644 index 00000000..b41aa0d4 --- /dev/null +++ b/lib/music_library/artists/batch.ex @@ -0,0 +1,48 @@ +defmodule MusicLibrary.Artists.Batch do + import Ecto.Query + + alias MusicLibrary.Artists + alias MusicLibrary.Artists.ArtistInfo + alias MusicLibrary.Repo + + require Logger + + def refresh_musicbrainz_data do + run_on_all_artist_infos(fn artist_info -> + Artists.refresh_musicbrainz_data_async(artist_info) + end) + end + + def refresh_discogs_data do + run_on_all_artist_infos(fn artist_info -> + Artists.refresh_discogs_data_async(artist_info) + end) + end + + defp run_on_all_artist_infos(fun) do + q = from(r in ArtistInfo) + stream = Repo.stream(q, max_rows: 50) + + Repo.transaction( + fn -> + Enum.reduce(stream, [], fn artist_info, acc -> + case fun.(artist_info) do + {:error, reason} -> + Logger.error( + "Failed to run function on artist_info #{artist_info.id} with #{inspect(reason)}" + ) + + [artist_info.id | acc] + + :ok -> + acc + + {:ok, _artist_info} -> + acc + end + end) + end, + timeout: :infinity + ) + end +end diff --git a/lib/music_library/worker/artist_refresh_discogs_data.ex b/lib/music_library/worker/artist_refresh_discogs_data.ex new file mode 100644 index 00000000..bf149003 --- /dev/null +++ b/lib/music_library/worker/artist_refresh_discogs_data.ex @@ -0,0 +1,10 @@ +defmodule MusicLibrary.Worker.ArtistRefreshDiscogsData do + use Oban.Worker, queue: :discogs, max_attempts: 3 + + @impl Oban.Worker + def perform(%Oban.Job{args: %{"id" => artist_info_id}}) do + MusicLibrary.Artists.refresh_discogs_data(artist_info_id) + + Process.sleep(100) + end +end diff --git a/lib/music_library/worker/artist_refresh_music_brainz_data.ex b/lib/music_library/worker/artist_refresh_music_brainz_data.ex new file mode 100644 index 00000000..25d17104 --- /dev/null +++ b/lib/music_library/worker/artist_refresh_music_brainz_data.ex @@ -0,0 +1,10 @@ +defmodule MusicLibrary.Worker.ArtistRefreshMusicBrainzData do + use Oban.Worker, queue: :music_brainz, max_attempts: 3 + + @impl Oban.Worker + def perform(%Oban.Job{args: %{"id" => artist_info_id}}) do + MusicLibrary.Artists.refresh_musicbrainz_data(artist_info_id) + + Process.sleep(500) + end +end diff --git a/lib/music_library_web/live/maintenance_live/index.ex b/lib/music_library_web/live/maintenance_live/index.ex index e38e4401..26d69eb5 100644 --- a/lib/music_library_web/live/maintenance_live/index.ex +++ b/lib/music_library_web/live/maintenance_live/index.ex @@ -3,7 +3,8 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do require Logger - alias MusicLibrary.Records.Batch + alias MusicLibrary.Artists + alias MusicLibrary.Records alias MusicLibrary.Repo def mount(_params, _session, socket) do @@ -16,7 +17,7 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do end def handle_event("refresh_records_musicbrainz_data", _params, socket) do - Batch.refresh_musicbrainz_data() + Records.Batch.refresh_musicbrainz_data() {:noreply, socket @@ -24,7 +25,23 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do end def handle_event("generate_record_embeddings", _params, socket) do - Batch.generate_embeddings() + Records.Batch.generate_embeddings() + + {:noreply, + socket + |> put_toast(:info, gettext("Operation started in the background."))} + end + + def handle_event("refresh_artists_musicbrainz_data", _params, socket) do + Artists.Batch.refresh_musicbrainz_data() + + {:noreply, + socket + |> put_toast(:info, gettext("Operation started in the background."))} + end + + def handle_event("refresh_artists_discogs_data", _params, socket) do + Artists.Batch.refresh_discogs_data() {:noreply, socket diff --git a/lib/music_library_web/live/maintenance_live/index.html.heex b/lib/music_library_web/live/maintenance_live/index.html.heex index 0c013a6d..22121ff3 100644 --- a/lib/music_library_web/live/maintenance_live/index.html.heex +++ b/lib/music_library_web/live/maintenance_live/index.html.heex @@ -48,7 +48,6 @@