fix(oban): handle orphaned source deletion jobs gracefully

Add rescue block to SourceDeletionWorker to handle cases where the
source no longer exists. This prevents infinite retries when a deletion
job fails and the source has already been removed from the database.
This commit is contained in:
Amadeus Mader 2026-03-07 18:52:19 +01:00
parent 46a1500aed
commit 80ae7ea1ff
3 changed files with 8 additions and 1 deletions

View file

@ -129,7 +129,7 @@ sqlite3 /path/to/pinchflat.db "
docker compose start pinchflat docker compose start pinchflat
``` ```
## Issue 5: Orphaned deletion jobs for non-existent sources ## Issue 5: Orphaned deletion jobs for non-existent sources [COMPLETED]
**Problem:** When a source is deleted, a `SourceDeletionWorker` job is created. If this job fails repeatedly (e.g., due to database busy errors or files already deleted), it keeps retrying indefinitely even after the source no longer exists. **Problem:** When a source is deleted, a `SourceDeletionWorker` job is created. If this job fails repeatedly (e.g., due to database busy errors or files already deleted), it keeps retrying indefinitely even after the source no longer exists.

View file

@ -34,5 +34,8 @@ defmodule Pinchflat.Sources.SourceDeletionWorker do
source = Sources.get_source!(source_id) source = Sources.get_source!(source_id)
Sources.delete_source(source, delete_files: delete_files) Sources.delete_source(source, delete_files: delete_files)
rescue
Ecto.NoResultsError -> Logger.info("#{__MODULE__} discarded: source #{source_id} not found")
Ecto.StaleEntryError -> Logger.info("#{__MODULE__} discarded: source #{source_id} stale")
end end
end end

View file

@ -48,5 +48,9 @@ defmodule Pinchflat.Sources.SourceDeletionWorkerTest do
assert_raise Ecto.NoResultsError, fn -> Repo.reload!(media_item) end assert_raise Ecto.NoResultsError, fn -> Repo.reload!(media_item) end
refute File.exists?(media_item.media_filepath) refute File.exists?(media_item.media_filepath)
end end
test "does not blow up if the record doesn't exist" do
assert :ok = perform_job(SourceDeletionWorker, %{id: 0})
end
end end
end end