[Enhancement] Allow forcing a refresh of source metadata (#194)

* Stopped sources from fetching metadata on every update

* Added action button to force a metadata refresh
This commit is contained in:
Kieran 2024-04-18 15:35:53 -07:00 committed by GitHub
parent 526bc0c2e3
commit 98c2812ee8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 98 additions and 20 deletions

View file

@ -38,9 +38,9 @@ defmodule Pinchflat.Metadata.SourceMetadataStorageWorker do
- The NFO file for the source (if specified)
- Downloads and stores source images (if specified)
The worker is kicked off after a source is inserted/updated - this can
take an unknown amount of time so don't rely on this data being here
before, say, the first indexing or downloading task is complete.
The worker is kicked off after a source is inserted or it's original_url
is updated - this can take an unknown amount of time so don't rely on this
data being here before, say, the first indexing or downloading task is complete.
Returns :ok
"""

View file

@ -237,7 +237,7 @@ defmodule Pinchflat.Sources do
if run_post_commit_tasks do
maybe_handle_media_tasks(changeset, source)
maybe_run_indexing_task(changeset, source)
run_metadata_storage_task(source)
maybe_run_metadata_storage_task(changeset, source)
end
{:ok, source}
@ -276,9 +276,20 @@ defmodule Pinchflat.Sources do
end
end
# This runs every time to pick up any changes to the metadata
defp run_metadata_storage_task(source) do
SourceMetadataStorageWorker.kickoff_with_task(source)
defp maybe_run_metadata_storage_task(changeset, source) do
case {changeset.data, changeset.changes} do
# If the changeset is new (not persisted), fetch metadata no matter what
{%{__meta__: %{state: :built}}, _} ->
SourceMetadataStorageWorker.kickoff_with_task(source)
# If the record has been persisted, only fetch metadata if the
# original_url has changed
{_, %{original_url: _}} ->
SourceMetadataStorageWorker.kickoff_with_task(source)
_ ->
:ok
end
end
defp maybe_update_slow_indexing_task(changeset, source) do

View file

@ -10,6 +10,7 @@ defmodule PinchflatWeb.Sources.SourceController do
alias Pinchflat.Profiles.MediaProfile
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
alias Pinchflat.Metadata.SourceMetadataStorageWorker
def index(conn, _params) do
sources =
@ -104,20 +105,38 @@ defmodule PinchflatWeb.Sources.SourceController do
end
def force_download(conn, %{"source_id" => id}) do
source = Sources.get_source!(id)
DownloadingHelpers.enqueue_pending_download_tasks(source)
conn
|> put_flash(:info, "Forced download of pending media items.")
|> redirect(to: ~p"/sources/#{source}")
wrap_forced_action(
conn,
id,
"Forcing download of pending media items.",
&DownloadingHelpers.enqueue_pending_download_tasks/1
)
end
def force_index(conn, %{"source_id" => id}) do
source = Sources.get_source!(id)
SlowIndexingHelpers.kickoff_indexing_task(source, %{force: true})
wrap_forced_action(
conn,
id,
"Index enqueued.",
&SlowIndexingHelpers.kickoff_indexing_task(&1, %{force: true})
)
end
def force_metadata_refresh(conn, %{"source_id" => id}) do
wrap_forced_action(
conn,
id,
"Metadata refresh enqueued.",
&SourceMetadataStorageWorker.kickoff_with_task/1
)
end
defp wrap_forced_action(conn, source_id, message, fun) do
source = Sources.get_source!(source_id)
fun.(source)
conn
|> put_flash(:info, "Index enqueued.")
|> put_flash(:info, message)
|> redirect(to: ~p"/sources/#{source}")
end

View file

@ -36,6 +36,15 @@ defmodule PinchflatWeb.Sources.SourceHTML do
|> Phoenix.json_library().encode!()
end
def title_filter_regex_help do
url = "https://github.com/nalgeon/sqlean/blob/main/docs/regexp.md#supported-syntax"
classes = "underline decoration-bodydark decoration-1 hover:decoration-white"
"""
A PCRE-compatible regex. Only media with titles that match this regex will be downloaded. <a href="#{url}" class="#{classes}" target="_blank">See here</a> for syntax
"""
end
def output_path_template_override_help do
help_button_classes = "underline decoration-bodydark decoration-1 hover:decoration-white cursor-pointer"
help_button = ~s{<span class="#{help_button_classes}" x-on:click="$dispatch('load-template')">Click here</span>}

View file

@ -30,6 +30,15 @@
Force Index
</.link>
</:option>
<:option>
<.link
href={~p"/sources/#{@source}/force_metadata_refresh"}
method="post"
data-confirm="Are you sure you want to refresh this source's metadata?"
>
Refresh Metadata
</.link>
</:option>
<:option>
<div class="h-px w-full bg-bodydark2"></div>
</:option>

View file

@ -23,7 +23,7 @@
field={f[:custom_name]}
type="text"
label="Custom Name"
help="Something descriptive. Does not impact indexing or downloading"
help="Does not impact indexing or downloading. Will be inferred from the source if left blank"
/>
<.input field={f[:original_url]} type="text" label="Source URL" help="URL of a channel or playlist (required)" />
@ -111,7 +111,8 @@
type="text"
label="Title Filter Regex"
placeholder="(?i)^How to Bike$"
help="A PCRE-compatible regex. Only media with titles that match this regex will be downloaded. Look up 'SQLean Regex docs' for more"
help={title_filter_regex_help()}
html_help={true}
/>
<section

View file

@ -35,6 +35,7 @@ defmodule PinchflatWeb.Router do
resources "/sources", Sources.SourceController do
post "/force_download", Sources.SourceController, :force_download
post "/force_index", Sources.SourceController, :force_index
post "/force_metadata_refresh", Sources.SourceController, :force_metadata_refresh
resources "/media", MediaItems.MediaItemController, only: [:show, :edit, :update, :delete] do
post "/force_download", MediaItems.MediaItemController, :force_download

View file

@ -514,14 +514,24 @@ defmodule Pinchflat.SourcesTest do
assert source.index_frequency_minutes == 0
end
test "updating will kickoff a metadata storage worker" do
test "updating will kickoff a metadata storage worker if the original_url changes" do
expect(YtDlpRunnerMock, :run, &playlist_mock/3)
source = source_fixture()
update_attrs = %{name: "some updated name"}
update_attrs = %{original_url: "https://www.youtube.com/channel/cba321"}
assert {:ok, %Source{} = source} = Sources.update_source(source, update_attrs)
assert_enqueued(worker: SourceMetadataStorageWorker, args: %{"id" => source.id})
end
test "updating will not kickoff a metadata storage worker other attrs change" do
source = source_fixture()
update_attrs = %{name: "some new name"}
assert {:ok, %Source{}} = Sources.update_source(source, update_attrs)
refute_enqueued(worker: SourceMetadataStorageWorker)
end
end
describe "update_source/3 when testing options" do

View file

@ -9,6 +9,7 @@ defmodule PinchflatWeb.SourceControllerTest do
alias Pinchflat.Repo
alias Pinchflat.Settings
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.Metadata.SourceMetadataStorageWorker
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
setup do
@ -215,6 +216,23 @@ defmodule PinchflatWeb.SourceControllerTest do
end
end
describe "force_metadata_refresh" do
test "forces a metadata refresh", %{conn: conn} do
source = source_fixture()
assert [] = all_enqueued(worker: SourceMetadataStorageWorker)
post(conn, ~p"/sources/#{source.id}/force_metadata_refresh")
assert [_] = all_enqueued(worker: SourceMetadataStorageWorker)
end
test "redirects to the source page", %{conn: conn} do
source = source_fixture()
conn = post(conn, ~p"/sources/#{source.id}/force_metadata_refresh")
assert redirected_to(conn) == ~p"/sources/#{source.id}"
end
end
defp create_source(_) do
source = source_fixture()
media_item = media_item_with_attachments(%{source_id: source.id})