75 lines
2 KiB
Elixir
75 lines
2 KiB
Elixir
defmodule Towerops.Workers.ReportWorker do
|
|
@moduledoc """
|
|
Oban worker for scheduled report generation and delivery.
|
|
|
|
The cron dispatcher (no args) runs hourly and checks which reports are due.
|
|
Individual jobs receive `%{"report_id" => id}` and generate + email the report.
|
|
"""
|
|
use Oban.Worker, queue: :maintenance
|
|
|
|
alias Towerops.Reports
|
|
alias Towerops.Reports.Notifier
|
|
|
|
require Logger
|
|
|
|
# Cron dispatcher: find due reports and enqueue individual jobs
|
|
@impl Oban.Worker
|
|
def perform(%Oban.Job{args: args}) when args == %{} do
|
|
reports =
|
|
Reports.Report
|
|
|> Towerops.Repo.all()
|
|
|> Enum.filter(&(&1.enabled and Reports.due?(&1)))
|
|
|
|
enqueued =
|
|
Enum.count(reports, fn report ->
|
|
case %{"report_id" => report.id}
|
|
|> new(unique: [period: 3600])
|
|
|> Oban.insert() do
|
|
{:ok, _} ->
|
|
true
|
|
|
|
{:error, changeset} ->
|
|
Logger.error("Failed to enqueue report job for report_id=#{report.id}: #{inspect(changeset)}")
|
|
false
|
|
end
|
|
end)
|
|
|
|
if enqueued > 0 do
|
|
Logger.info("Report worker: dispatched #{enqueued} report jobs")
|
|
end
|
|
|
|
:ok
|
|
end
|
|
|
|
# Individual report: generate and deliver
|
|
def perform(%Oban.Job{args: %{"report_id" => id}}) do
|
|
case Reports.get_report(id) do
|
|
{:ok, report} ->
|
|
run_report(report)
|
|
|
|
{:error, :not_found} ->
|
|
Logger.warning("Report #{id} not found, skipping")
|
|
:ok
|
|
end
|
|
end
|
|
|
|
defp run_report(report) do
|
|
{:ok, csv_data} = Reports.generate_csv(report)
|
|
|
|
case Notifier.deliver_report(report, csv_data) do
|
|
:ok ->
|
|
Reports.mark_run(report, "success")
|
|
Logger.info("Report #{report.id} (#{report.name}) delivered successfully")
|
|
:ok
|
|
|
|
{:error, _reason} ->
|
|
Reports.mark_run(report, "partial_failure")
|
|
:ok
|
|
end
|
|
rescue
|
|
exception ->
|
|
Reports.mark_run(report, "failed")
|
|
Logger.error("Report #{report.id} generation failed: #{Exception.message(exception)}")
|
|
:ok
|
|
end
|
|
end
|