diff --git a/lib/music_library/maintenance.ex b/lib/music_library/maintenance.ex index 0a977025..8bbcb584 100644 --- a/lib/music_library/maintenance.ex +++ b/lib/music_library/maintenance.ex @@ -10,20 +10,23 @@ defmodule MusicLibrary.Maintenance do alias MusicLibrary.BackgroundRepo alias MusicLibrary.Repo + @active_states ~w(available scheduled executing retryable) + @doc """ - Counts active Oban jobs for the given worker module name. + Returns a map of worker module names to their count of active Oban jobs. Active jobs are those in "available", "scheduled", "executing", or "retryable" states. """ - @spec count_active_jobs(String.t()) :: non_neg_integer() | nil - def count_active_jobs(worker) do - query = - from j in Oban.Job, - where: j.worker == ^worker, - where: j.state in ["available", "scheduled", "executing", "retryable"], - select: count(j.id) + @spec count_active_jobs_by_worker() :: %{String.t() => non_neg_integer()} + def count_active_jobs_by_worker do + q = + from j in subquery(Oban.Job.query(state: @active_states)), + group_by: j.worker, + select: {j.worker, count(j.id)} - BackgroundRepo.one(query) + q + |> BackgroundRepo.all() + |> Map.new() end @doc """ diff --git a/lib/music_library_web/live/maintenance_live/index.ex b/lib/music_library_web/live/maintenance_live/index.ex index c981d948..baf940a4 100644 --- a/lib/music_library_web/live/maintenance_live/index.ex +++ b/lib/music_library_web/live/maintenance_live/index.ex @@ -305,30 +305,32 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do end defp assign_job_counts(socket) do + counts = Maintenance.count_active_jobs_by_worker() + socket |> assign( :refresh_records_musicbrainz_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.RecordRefreshMusicBrainzData") + Map.get(counts, "MusicLibrary.Worker.RecordRefreshMusicBrainzData", 0) ) |> assign( :generate_record_embeddings_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.GenerateRecordEmbedding") + Map.get(counts, "MusicLibrary.Worker.GenerateRecordEmbedding", 0) ) |> assign( :refresh_artists_musicbrainz_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.ArtistRefreshMusicBrainzData") + Map.get(counts, "MusicLibrary.Worker.ArtistRefreshMusicBrainzData", 0) ) |> assign( :refresh_artists_discogs_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.ArtistRefreshDiscogsData") + Map.get(counts, "MusicLibrary.Worker.ArtistRefreshDiscogsData", 0) ) |> assign( :refresh_artists_wikipedia_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.ArtistRefreshWikipediaData") + Map.get(counts, "MusicLibrary.Worker.ArtistRefreshWikipediaData", 0) ) |> assign( :refresh_artists_lastfm_jobs, - Maintenance.count_active_jobs("MusicLibrary.Worker.FetchArtistLastFmData") + Map.get(counts, "MusicLibrary.Worker.FetchArtistLastFmData", 0) ) end diff --git a/test/music_library/maintenance_test.exs b/test/music_library/maintenance_test.exs index 97d2a88c..353ba812 100644 --- a/test/music_library/maintenance_test.exs +++ b/test/music_library/maintenance_test.exs @@ -3,6 +3,7 @@ defmodule MusicLibrary.MaintenanceTest do import MusicLibrary.ScrobbledTracksFixtures + alias MusicLibrary.BackgroundRepo alias MusicLibrary.Maintenance describe "optimize/0" do @@ -11,9 +12,47 @@ defmodule MusicLibrary.MaintenanceTest do end end - describe "count_active_jobs/1" do - test "returns 0 for a worker with no jobs" do - assert Maintenance.count_active_jobs("MusicLibrary.Worker.NonExistent") == 0 + describe "count_active_jobs_by_worker/0" do + @worker_a "Test.Worker.Alpha" + @worker_b "Test.Worker.Beta" + + test "returns an empty map when there are no jobs" do + assert Maintenance.count_active_jobs_by_worker() == %{} + end + + test "returns counts grouped by worker for active jobs" do + %{id: "1"} + |> Oban.Job.new(worker: @worker_a) + |> Oban.insert!() + + %{id: "2"} + |> Oban.Job.new(worker: @worker_a) + |> Oban.insert!() + + %{id: "3"} + |> Oban.Job.new(worker: @worker_b) + |> Oban.insert!() + + counts = Maintenance.count_active_jobs_by_worker() + + assert counts[@worker_a] == 2 + assert counts[@worker_b] == 1 + end + + test "only counts jobs in active states" do + %{id: "1"} + |> Oban.Job.new(worker: @worker_a) + |> Oban.insert!() + |> then(fn job -> + BackgroundRepo.update_all( + from(j in Oban.Job, where: j.id == ^job.id), + set: [state: "completed"] + ) + end) + + counts = Maintenance.count_active_jobs_by_worker() + + assert Map.get(counts, @worker_a, 0) == 0 end end