From bc25bf67e46340f8d2c1c9844bbcf28f4b04fc27 Mon Sep 17 00:00:00 2001 From: Kieran Eglin Date: Sun, 10 Mar 2024 15:10:46 -0700 Subject: [PATCH] Adds backfill job to startup tasks --- lib/pinchflat/application.ex | 4 +-- lib/pinchflat/startup_tasks.ex | 15 ++++++++- lib/pinchflat/workers/data_backfill_worker.ex | 18 +++++++++- .../workers/data_backfill_worker_test.exs | 33 +++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/lib/pinchflat/application.ex b/lib/pinchflat/application.ex index 1527d7d..6f838bc 100644 --- a/lib/pinchflat/application.ex +++ b/lib/pinchflat/application.ex @@ -10,9 +10,9 @@ defmodule Pinchflat.Application do children = [ PinchflatWeb.Telemetry, Pinchflat.Repo, - # {Task, &run_startup_tasks/0}, - Pinchflat.StartupTasks, + # Must be before startup tasks {Oban, Application.fetch_env!(:pinchflat, Oban)}, + Pinchflat.StartupTasks, {DNSCluster, query: Application.get_env(:pinchflat, :dns_cluster_query) || :ignore}, {Phoenix.PubSub, name: Pinchflat.PubSub}, # Start the Finch HTTP client for sending emails diff --git a/lib/pinchflat/startup_tasks.ex b/lib/pinchflat/startup_tasks.ex index e4b1aec..8e4be23 100644 --- a/lib/pinchflat/startup_tasks.ex +++ b/lib/pinchflat/startup_tasks.ex @@ -8,8 +8,11 @@ defmodule Pinchflat.StartupTasks do # restart: :temporary means that this process will never be restarted (ie: will run once and then die) use GenServer, restart: :temporary + import Ecto.Query, warn: false + alias Pinchflat.Repo alias Pinchflat.Settings + alias Pinchflat.Workers.DataBackfillWorker def start_link(opts \\ []) do GenServer.start_link(__MODULE__, %{}, opts) @@ -21,11 +24,13 @@ defmodule Pinchflat.StartupTasks do Any code defined here will run every time the application starts. You must make sure that the code is idempotent and safe to run multiple times. - This is a good place to set up default settings, create initial records, stuff like that + This is a good place to set up default settings, create initial records, stuff like that. + Should be fast - anything with the potential to be slow should be kicked off as a job instead. """ @impl true def init(state) do apply_default_settings() + enqueue_backfill_worker() {:ok, state} end @@ -34,4 +39,12 @@ defmodule Pinchflat.StartupTasks do Settings.fetch!(:onboarding, true) Settings.fetch!(:pro_enabled, false) end + + defp enqueue_backfill_worker do + DataBackfillWorker.cancel_pending_backfill_jobs() + + %{} + |> DataBackfillWorker.new() + |> Repo.insert_unique_job() + end end diff --git a/lib/pinchflat/workers/data_backfill_worker.ex b/lib/pinchflat/workers/data_backfill_worker.ex index bd4d949..15a7041 100644 --- a/lib/pinchflat/workers/data_backfill_worker.ex +++ b/lib/pinchflat/workers/data_backfill_worker.ex @@ -14,11 +14,24 @@ defmodule Pinchflat.Workers.DataBackfillWorker do # I'm just trying out that pattern and seeing if I like it better # so this may change. import Ecto.Query, warn: false + require Logger alias __MODULE__ alias Pinchflat.Repo alias Pinchflat.Media.MediaItem + @doc """ + Cancels all pending backfill jobs. Useful for ensuring worker runs immediately + on app boot. + + Returns {:ok, integer()} + """ + def cancel_pending_backfill_jobs do + Oban.Job + |> where(worker: "Pinchflat.Workers.DataBackfillWorker") + |> Oban.cancel_all_jobs() + end + @impl Oban.Worker @doc """ Performs one-off tasks to get data in the right shape. @@ -30,6 +43,7 @@ defmodule Pinchflat.Workers.DataBackfillWorker do Returns :ok """ def perform(%Oban.Job{}) do + Logger.info("Running data backfill worker") backfill_shorts_data() reschedule_backfill() @@ -45,7 +59,9 @@ defmodule Pinchflat.Workers.DataBackfillWorker do where: m.short_form_content == false ) - Repo.update_all(query, set: [short_form_content: true]) + {count, _} = Repo.update_all(query, set: [short_form_content: true]) + + Logger.info("Backfill worker set short_form_content to true for #{count} media items.") end defp reschedule_backfill do diff --git a/test/pinchflat/workers/data_backfill_worker_test.exs b/test/pinchflat/workers/data_backfill_worker_test.exs index 470035e..856bfb6 100644 --- a/test/pinchflat/workers/data_backfill_worker_test.exs +++ b/test/pinchflat/workers/data_backfill_worker_test.exs @@ -4,8 +4,41 @@ defmodule Pinchflat.Workers.DataBackfillWorkerTest do import Pinchflat.MediaFixtures alias Pinchflat.Workers.DataBackfillWorker + alias Pinchflat.Workers.FilesystemDataWorker + + describe "cancel_pending_backfill_jobs/0" do + test "cancels all pending backfill jobs" do + %{} + |> DataBackfillWorker.new() + |> Repo.insert_unique_job() + + assert_enqueued(worker: DataBackfillWorker) + + DataBackfillWorker.cancel_pending_backfill_jobs() + + refute_enqueued(worker: DataBackfillWorker) + end + + test "does not cancel jobs for other workers" do + %{id: 0} + |> FilesystemDataWorker.new() + |> Repo.insert_unique_job() + + assert_enqueued(worker: FilesystemDataWorker) + + DataBackfillWorker.cancel_pending_backfill_jobs() + + assert_enqueued(worker: FilesystemDataWorker) + end + end describe "perform/1" do + setup do + DataBackfillWorker.cancel_pending_backfill_jobs() + + :ok + end + test "reschedules itself once complete" do perform_job(DataBackfillWorker, %{})