[WIP] started on source deletion

This commit is contained in:
Kieran Eglin 2024-05-30 15:13:41 -07:00
parent 3dd901ff3e
commit ee9173d218
No known key found for this signature in database
GPG key ID: 193984967FCF432D
6 changed files with 107 additions and 22 deletions

View file

@ -64,7 +64,7 @@ config :pinchflat, Oban,
media_indexing: 2,
media_collection_indexing: 2,
media_fetching: 2,
local_metadata: 8,
local_data: 8,
remote_metadata: 4
]

View file

@ -2,9 +2,9 @@ defmodule Pinchflat.Downloading.MediaRetentionWorker do
@moduledoc false
use Oban.Worker,
queue: :local_metadata,
queue: :local_data,
unique: [period: :infinity, states: [:available, :scheduled, :retryable, :executing]],
tags: ["media_item", "local_metadata"]
tags: ["media_item", "local_data"]
require Logger

View file

@ -0,0 +1,38 @@
defmodule Pinchflat.Sources.SourceDeletionWorker do
@moduledoc false
use Oban.Worker,
queue: :local_data,
tags: ["sources", "local_data"]
require Logger
alias __MODULE__
alias Pinchflat.Sources
@doc """
Starts the source deletion worker. Does not attach it to a task like `kickoff_with_task/2`
since deletion also cancels all tasks for the source
Returns {:ok, %Task{}} | {:error, %Ecto.Changeset{}}
"""
def kickoff(source, job_args \\ %{}, job_opts \\ []) do
%{id: source.id}
|> Map.merge(job_args)
|> SourceDeletionWorker.new(job_opts)
|> Oban.insert()
end
@doc """
Deletes a source and optionally deletes its files
Returns :ok
"""
@impl Oban.Worker
def perform(%Oban.Job{args: %{"id" => source_id} = args}) do
delete_files = Map.get(args, "delete_files", false)
source = Sources.get_source!(source_id)
Sources.delete_source(source, delete_files: delete_files)
end
end

View file

@ -8,6 +8,7 @@ defmodule PinchflatWeb.Sources.SourceController do
alias Pinchflat.Sources.Source
alias Pinchflat.Media.MediaItem
alias Pinchflat.Profiles.MediaProfile
alias Pinchflat.Sources.SourceDeletionWorker
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
alias Pinchflat.Metadata.SourceMetadataStorageWorker
@ -109,17 +110,13 @@ defmodule PinchflatWeb.Sources.SourceController do
def delete(conn, %{"id" => id} = params) do
delete_files = Map.get(params, "delete_files", false)
source = Sources.get_source!(id)
{:ok, _source} = Sources.delete_source(source, delete_files: delete_files)
flash_message =
if delete_files do
"Source and files deleted successfully."
else
"Source deleted successfully. Files were not deleted."
end
SourceDeletionWorker.kickoff(source, %{delete_files: delete_files})
conn
|> put_flash(:info, flash_message)
|> put_flash(
:info,
"Started deletion job in background. May take a while to complete depending on the number of media items."
)
|> redirect(to: ~p"/sources")
end

View file

@ -0,0 +1,54 @@
defmodule Pinchflat.Sources.SourceDeletionWorkerTest do
use Pinchflat.DataCase
import Pinchflat.MediaFixtures
import Pinchflat.SourcesFixtures
alias Pinchflat.Media
alias Pinchflat.Sources
alias Pinchflat.Sources.SourceDeletionWorker
setup do
stub(UserScriptRunnerMock, :run, fn _event_type, _data -> :ok end)
{:ok, %{source: source_fixture()}}
end
describe "kickoff/3" do
test "starts the worker", %{source: source} do
assert [] = all_enqueued(worker: SourceDeletionWorker)
assert {:ok, _} = SourceDeletionWorker.kickoff(source)
assert [_] = all_enqueued(worker: SourceDeletionWorker)
end
test "can be called with additional job arguments", %{source: source} do
job_args = %{"delete_files" => true}
assert {:ok, _} = SourceDeletionWorker.kickoff(source, job_args)
assert_enqueued(worker: SourceDeletionWorker, args: %{"id" => source.id, "delete_files" => true})
end
end
describe "perform/1" do
test "deletes the source but leaves the files", %{source: source} do
media_item = media_item_with_attachments(%{source_id: source.id})
perform_job(SourceDeletionWorker, %{"id" => source.id})
assert_raise Ecto.NoResultsError, fn -> Sources.get_source!(source.id) end
assert_raise Ecto.NoResultsError, fn -> Media.get_media_item!(media_item.id) end
assert File.exists?(media_item.media_filepath)
end
test "deletes the source and files if specified", %{source: source} do
media_item = media_item_with_attachments(%{source_id: source.id})
perform_job(SourceDeletionWorker, %{"id" => source.id, "delete_files" => true})
assert_raise Ecto.NoResultsError, fn -> Sources.get_source!(source.id) end
assert_raise Ecto.NoResultsError, fn -> Media.get_media_item!(media_item.id) end
refute File.exists?(media_item.media_filepath)
end
end
end

View file

@ -119,6 +119,12 @@ defmodule PinchflatWeb.SourceControllerTest do
end
describe "delete source when just deleting the records" do
setup do
stub(UserScriptRunnerMock, :run, fn _event_type, _data -> :ok end)
:ok
end
setup [:create_source]
test "deletes chosen source and media_items", %{conn: conn, source: source, media_item: media_item} do
@ -137,16 +143,6 @@ defmodule PinchflatWeb.SourceControllerTest do
delete(conn, ~p"/sources/#{source}")
assert File.exists?(media_item.media_filepath)
end
end
describe "delete source when deleting the records and files" do
setup [:create_source]
setup do
stub(UserScriptRunnerMock, :run, fn _event_type, _data -> :ok end)
:ok
end
test "deletes chosen source and media_items", %{conn: conn, source: source, media_item: media_item} do
delete(conn, ~p"/sources/#{source}?delete_files=true")