Move asset pruning logic to Assets context

Closes #130
This commit is contained in:
Claudio Ortolina
2026-03-25 11:55:28 +00:00
parent 0ccaf46ebd
commit 09f61b6039
2 changed files with 30 additions and 24 deletions
+24
View File
@@ -56,6 +56,30 @@ defmodule MusicLibrary.Assets do
)
end
@doc """
Deletes all assets not referenced by any record cover or artist info image.
Returns the number of pruned assets.
"""
@spec prune_unreferenced() :: non_neg_integer()
def prune_unreferenced do
# Note that SQLite doesn't support left joins on delete, so we do it in two steps.
asset_hashes =
from a in Asset,
left_join: r in MusicLibrary.Records.Record,
on: r.cover_hash == a.hash,
left_join: ai in MusicLibrary.Artists.ArtistInfo,
on: ai.image_data_hash == a.hash,
where: is_nil(r.id) and is_nil(ai.id),
select: a.hash
q =
from a in Asset,
where: a.hash in subquery(asset_hashes)
{count, nil} = Repo.delete_all(q)
count
end
@spec track_total_cache_size() :: :ok
def track_total_cache_size do
:telemetry.execute(
+6 -24
View File
@@ -1,35 +1,17 @@
defmodule MusicLibrary.Worker.PruneAssets do
use Oban.Worker, queue: :default, max_attempts: 3
@moduledoc """
Prunes unreferenced assets from the database.
"""
import Ecto.Query
use Oban.Worker, queue: :default, max_attempts: 3
require Logger
alias MusicLibrary.{
Artists.ArtistInfo,
Assets.Asset,
Records.Record,
Repo
}
alias MusicLibrary.Assets
@impl Oban.Worker
def perform(_) do
# Find all assets that are not referenced by any records or artist info
# Note that SQLite doesn't support left joins on delete, so we do it in two steps.
asset_hashes =
from a in Asset,
left_join: r in Record,
on: r.cover_hash == a.hash,
left_join: ai in ArtistInfo,
on: ai.image_data_hash == a.hash,
where: is_nil(r.id) and is_nil(ai.id),
select: a.hash
q =
from a in Asset,
where: a.hash in subquery(asset_hashes)
{count, nil} = Repo.delete_all(q)
count = Assets.prune_unreferenced()
Logger.info(fn -> "Pruned #{count} unreferenced assets." end)
end