fix(metadata): auto-download missing source images on profile change or indexing
Add two mechanisms to ensure source images are downloaded: 1. Trigger SourceMetadataStorageWorker when media_profile_id changes, so if a user switches to a profile with download_source_images enabled, the images will be fetched. 2. After successful indexing, check if source images are missing but should exist (profile has download_source_images: true). If so, kick off the metadata storage worker to download them. This fixes issues where sources created before download_source_images was added, or sources that had failed metadata jobs, never got their artwork downloaded.
This commit is contained in:
parent
80ae7ea1ff
commit
50a1ff61f4
5 changed files with 68 additions and 2 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Issues discovered while debugging Jellyfin artwork problems.
|
||||
|
||||
## Issue 1: Source images not downloaded for early sources
|
||||
## Issue 1: Source images not downloaded for early sources [COMPLETED]
|
||||
|
||||
**Problem:** Sources created before `download_source_images` was added to the media profile have empty `poster_filepath`, `fanart_filepath`, and `banner_filepath` in the `sources` table. The `source_metadata` table may have stale references to files that were never actually downloaded.
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ Issues discovered while debugging Jellyfin artwork problems.
|
|||
2. Downloads missing source images for sources that don't have them
|
||||
3. Updates both `sources` and `source_metadata` tables
|
||||
|
||||
## Issue 2: Source images not downloaded for some new sources
|
||||
## Issue 2: Source images not downloaded for some new sources [COMPLETED]
|
||||
|
||||
**Problem:** Some recently added sources have no `source_metadata` entry at all, even though they use a profile with `download_source_images: true`.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
|
|||
alias Pinchflat.SlowIndexing.FileFollowerServer
|
||||
alias Pinchflat.Downloading.DownloadOptionBuilder
|
||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
||||
alias Pinchflat.Metadata.SourceMetadataStorageWorker
|
||||
|
||||
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
|
||||
|
||||
|
|
@ -245,6 +246,7 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
|
|||
# Updates the source after a successful indexing run. This includes:
|
||||
# - Setting `last_indexed_at` to the current time
|
||||
# - Advancing `download_cutoff_date` to 7 days ago if it's older (or nil)
|
||||
# - Kicking off metadata storage if source images are missing but should be downloaded
|
||||
#
|
||||
# Advancing the cutoff date prevents yt-dlp from scanning through months of old videos
|
||||
# on every index. We use 7 days as a buffer to ensure we don't miss any videos that
|
||||
|
|
@ -260,6 +262,8 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
|
|||
|> maybe_advance_cutoff_date(source.download_cutoff_date, new_cutoff_date)
|
||||
|
||||
Sources.update_source(source, update_attrs, run_post_commit_tasks: false)
|
||||
|
||||
maybe_kickoff_metadata_storage_for_missing_images(source)
|
||||
end
|
||||
|
||||
defp maybe_advance_cutoff_date(attrs, nil, new_cutoff_date) do
|
||||
|
|
@ -273,4 +277,24 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
|
|||
attrs
|
||||
end
|
||||
end
|
||||
|
||||
# Kicks off metadata storage if source images should be downloaded but are missing.
|
||||
# This handles the case where:
|
||||
# 1. A source was created before download_source_images was enabled on the profile
|
||||
# 2. The source metadata worker failed or was interrupted
|
||||
# 3. The profile's download_source_images setting was later enabled
|
||||
defp maybe_kickoff_metadata_storage_for_missing_images(source) do
|
||||
source = Repo.preload(source, :media_profile)
|
||||
|
||||
if source.media_profile.download_source_images && source_images_missing?(source) do
|
||||
Logger.info("Source #{source.id} is missing images, kicking off metadata storage")
|
||||
SourceMetadataStorageWorker.kickoff_with_task(source)
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
defp source_images_missing?(source) do
|
||||
is_nil(source.poster_filepath) || is_nil(source.fanart_filepath)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -336,6 +336,11 @@ defmodule Pinchflat.Sources do
|
|||
{_, %{original_url: _}} ->
|
||||
SourceMetadataStorageWorker.kickoff_with_task(source)
|
||||
|
||||
# If the media_profile_id has changed, re-fetch metadata to potentially
|
||||
# download source images if the new profile has download_source_images enabled
|
||||
{_, %{media_profile_id: _}} ->
|
||||
SourceMetadataStorageWorker.kickoff_with_task(source)
|
||||
|
||||
_ ->
|
||||
:ok
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpersTest do
|
|||
alias Pinchflat.Downloading.MediaDownloadWorker
|
||||
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
|
||||
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
|
||||
alias Pinchflat.Metadata.SourceMetadataStorageWorker
|
||||
|
||||
setup do
|
||||
{:ok, %{source: source_fixture()}}
|
||||
|
|
@ -259,6 +260,32 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpersTest do
|
|||
assert source.download_cutoff_date == recent_cutoff
|
||||
end
|
||||
|
||||
test "kicks off metadata storage if source images are missing but should be downloaded" do
|
||||
profile = media_profile_fixture(%{download_source_images: true})
|
||||
source = source_fixture(%{media_profile_id: profile.id, poster_filepath: nil, fanart_filepath: nil})
|
||||
|
||||
SlowIndexingHelpers.index_and_enqueue_download_for_media_items(source)
|
||||
|
||||
assert_enqueued(worker: SourceMetadataStorageWorker, args: %{"id" => source.id})
|
||||
end
|
||||
|
||||
test "does not kick off metadata storage if source images exist" do
|
||||
source = source_with_metadata_attachments()
|
||||
|
||||
SlowIndexingHelpers.index_and_enqueue_download_for_media_items(source)
|
||||
|
||||
refute_enqueued(worker: SourceMetadataStorageWorker)
|
||||
end
|
||||
|
||||
test "does not kick off metadata storage if profile does not download source images" do
|
||||
profile = media_profile_fixture(%{download_source_images: false})
|
||||
source = source_fixture(%{media_profile_id: profile.id, poster_filepath: nil})
|
||||
|
||||
SlowIndexingHelpers.index_and_enqueue_download_for_media_items(source)
|
||||
|
||||
refute_enqueued(worker: SourceMetadataStorageWorker)
|
||||
end
|
||||
|
||||
test "enqueues a job for each pending media item" do
|
||||
source = source_fixture()
|
||||
media_item = media_item_fixture(source_id: source.id, media_filepath: nil)
|
||||
|
|
|
|||
|
|
@ -565,6 +565,16 @@ defmodule Pinchflat.SourcesTest do
|
|||
|
||||
refute_enqueued(worker: SourceMetadataStorageWorker)
|
||||
end
|
||||
|
||||
test "updating will kickoff a metadata storage worker if the media_profile_id changes" do
|
||||
source = source_fixture()
|
||||
new_profile = media_profile_fixture()
|
||||
update_attrs = %{media_profile_id: new_profile.id}
|
||||
|
||||
assert {:ok, %Source{} = source} = Sources.update_source(source, update_attrs)
|
||||
|
||||
assert_enqueued(worker: SourceMetadataStorageWorker, args: %{"id" => source.id})
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_source/3 when testing media download tasks" do
|
||||
|
|
|
|||
Loading…
Reference in a new issue