prop/lib/microwaveprop/workers/partition_maintenance_worker.ex
2026-06-16 12:38:08 -05:00

53 lines
1.8 KiB
Elixir

defmodule Microwaveprop.Workers.PartitionMaintenanceWorker do
@moduledoc """
Daily Oban job that keeps the time-partitioned tables ahead of the
current write window.
Calls `Microwaveprop.PartitionManager.ensure_quarterly_partitions/1`
for the default parents (`hrrr_profiles`, `hrdps_profiles`) with a
4-quarter lookahead. Idempotent — the partition manager uses
`CREATE TABLE IF NOT EXISTS`, so a fire that finds nothing missing
is a no-op.
Lookahead choice: 4 quarters ≈ 1 year of runway. The cron runs daily,
so a single missed fire (or a week of missed fires after an outage)
still leaves >9 months of partition coverage before writes would hit
a missing quarter. The safety margin is intentionally large — the
cost of an extra empty partition is one zero-row table, while the
cost of a missing partition is silently failed inserts.
"""
use Oban.Pro.Worker,
queue: :admin,
max_attempts: 3,
unique: [period: 3600, states: :incomplete]
alias Microwaveprop.PartitionManager
require Logger
@lookahead_quarters 4
@impl Oban.Pro.Worker
@spec process(Oban.Job.t()) :: :ok
def process(%Oban.Job{args: args}) do
lookahead = lookahead(args)
results = PartitionManager.ensure_quarterly_partitions(lookahead)
created = Enum.filter(results, fn {_, _, status} -> status == :created end)
case created do
[] ->
Logger.info("PartitionMaintenanceWorker: all #{length(results)} partitions already exist")
list ->
names = Enum.map_join(list, ", ", fn {_parent, name, _} -> name end)
Logger.info("PartitionMaintenanceWorker: created partitions: #{names}")
end
:ok
end
@spec lookahead(map()) :: non_neg_integer()
defp lookahead(%{"lookahead_quarters" => n}) when is_integer(n) and n >= 0, do: n
defp lookahead(_), do: @lookahead_quarters
end