Packages

Event-driven notification system for Ash Framework with multiple transport types

Current section

Files

Jump to
ash_dispatch lib calculations oban_job.ex
Raw

lib/calculations/oban_job.ex

defmodule AshDispatch.Calculations.ObanJob do
@moduledoc """
Calculation that loads Oban job data for delivery receipts.
This is populated by the LoadObanJob preparation during queries.
The calculation itself just returns nil - the real loading happens in the preparation.
"""
use Ash.Resource.Calculation
alias AshDispatch.Config
import Ecto.Query
@impl true
def calculate(records, _opts, _context) do
# Get all receipt IDs that have oban_job_id
job_ids =
records
|> Enum.filter(fn receipt -> receipt.oban_job_id end)
|> Enum.map(& &1.oban_job_id)
|> Enum.uniq()
if Enum.empty?(job_ids) do
# No jobs to load, return nil for all
Enum.map(records, fn _ -> nil end)
else
# Query Oban jobs using configured repo
repo = get_repo()
jobs =
from(j in Oban.Job,
where: j.id in ^job_ids,
select: %{
id: j.id,
state: j.state,
queue: j.queue,
worker: j.worker,
scheduled_at: j.scheduled_at,
attempted_at: j.attempted_at,
completed_at: j.completed_at,
errors: j.errors,
attempt: j.attempt,
max_attempts: j.max_attempts
}
)
|> repo.all()
|> Map.new(&{&1.id, &1})
# Return oban_job for each receipt
Enum.map(records, fn receipt ->
if receipt.oban_job_id do
Map.get(jobs, receipt.oban_job_id)
else
nil
end
end)
end
end
@impl true
def load(_query, _opts, _context) do
# Load oban_job_id so we can use it in calculate/3
[:oban_job_id]
end
defp get_repo do
Config.repo() ||
raise """
Missing configuration for :ash_dispatch, :repo
Add to your config:
config :ash_dispatch,
repo: MyApp.Repo
"""
end
end