towerops/lib/towerops/workers/pagerduty_webhook_worker.ex
2026-06-14 16:38:03 -05:00

79 lines
2.1 KiB
Elixir

defmodule Towerops.Workers.PagerdutyWebhookWorker do
@moduledoc """
Processes a PagerDuty webhook event asynchronously so the controller can ACK
the webhook sender immediately.
"""
use Oban.Pro.Worker, queue: :default, max_attempts: 3
alias Towerops.Alerts
require Logger
@impl Oban.Worker
def perform(%Oban.Job{args: %{"event_type" => event_type, "data" => data, "organization_id" => org_id}}) do
case event_type do
"incident.resolved" ->
resolve_from_pagerduty(data, org_id)
"incident.acknowledged" ->
acknowledge_from_pagerduty(data, org_id)
other ->
Logger.debug("Ignoring PagerDuty webhook event: #{other}")
:ok
end
end
defp resolve_from_pagerduty(data, _org_id) do
case extract_alert_id(data) do
nil ->
Logger.debug("PagerDuty resolve: no TowerOps alert ID found in incident")
:ok
alert_id ->
case Alerts.get_alert(alert_id) do
nil ->
Logger.warning("PagerDuty resolve: alert #{alert_id} not found")
%{resolved_at: resolved_at} when not is_nil(resolved_at) ->
Logger.debug("PagerDuty resolve: alert #{alert_id} already resolved")
alert ->
Logger.info("Resolving alert #{alert_id} from PagerDuty")
Alerts.resolve_alert_silent(alert)
end
end
end
defp acknowledge_from_pagerduty(data, _org_id) do
case extract_alert_id(data) do
nil ->
:ok
alert_id ->
case Alerts.get_alert(alert_id) do
nil ->
Logger.warning("PagerDuty acknowledge: alert #{alert_id} not found")
%{acknowledged_at: ack} when not is_nil(ack) ->
Logger.debug("PagerDuty acknowledge: alert #{alert_id} already acknowledged")
alert ->
Logger.info("Acknowledging alert #{alert_id} from PagerDuty")
Alerts.acknowledge_alert_silent(alert)
end
end
end
defp extract_alert_id(data) do
alerts = data["alerts"] || []
Enum.find_value(alerts, fn alert ->
case alert["alert_key"] do
"towerops-alert-" <> id -> id
_ -> nil
end
end)
end
end