defmodule Mix.Tasks.Oban.CancelStuckDiscovery do @shortdoc "Cancels stuck DiscoveryWorker jobs" @moduledoc """ Cancels all stuck DiscoveryWorker jobs that are in scheduled or retryable state. ## Usage # In production via kubectl: kubectl exec -n towerops deployment/towerops -- /app/bin/towerops rpc "Mix.Tasks.Oban.CancelStuckDiscovery.run([])" # Locally: mix oban.cancel_stuck_discovery """ use Mix.Task import Ecto.Query require Logger @impl Mix.Task def run(_args) do Mix.Task.run("app.start") cancelled_count = Oban.Job |> where([j], j.worker == "Towerops.Workers.DiscoveryWorker") |> where([j], j.state in ["scheduled", "retryable", "executing"]) |> Towerops.Repo.all() |> Enum.map(fn job -> :ok = Oban.cancel_job(Oban, job.id) Logger.info( "Cancelled stuck discovery job", job_id: job.id, device_id: get_in(job.args, ["device_id"]), state: job.state, attempted_at: job.attempted_at ) 1 end) |> Enum.sum() Mix.shell().info("Cancelled #{cancelled_count} stuck discovery jobs") end end