69 lines
1.8 KiB
Elixir
69 lines
1.8 KiB
Elixir
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 ->
|
|
case Oban.cancel_job(Oban, job.id) do
|
|
{:ok, cancelled_job} ->
|
|
Logger.info(
|
|
"Cancelled stuck discovery job",
|
|
job_id: cancelled_job.id,
|
|
device_id: get_in(cancelled_job.args, ["device_id"]),
|
|
state: cancelled_job.state,
|
|
attempted_at: cancelled_job.attempted_at
|
|
)
|
|
|
|
1
|
|
|
|
:ok ->
|
|
# Some versions of Oban return :ok instead of {:ok, job}
|
|
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
|
|
|
|
{:error, reason} ->
|
|
Logger.error(
|
|
"Failed to cancel job",
|
|
job_id: job.id,
|
|
error: inspect(reason)
|
|
)
|
|
|
|
0
|
|
end
|
|
end)
|
|
|> Enum.sum()
|
|
|
|
Mix.shell().info("Cancelled #{cancelled_count} stuck discovery jobs")
|
|
end
|
|
end
|