AuroraMeter. Oban. Retention
(Aurora Meter v1.0.0)
View Source
Deletes the disposable operational rows AuroraMeter.Retention allows, in
bounded batches.
The work is AuroraMeter.Retention.prune/1 and nothing else. The worker
opens no transaction, takes no lock and reads no clock: every cutoff is
computed by the database inside the statement that uses it.
config :my_app, Oban,
plugins: [{Oban.Plugins.Cron, crontab: [
{"40 3 * * *", AuroraMeter.Oban.Retention}
]}]Recommended schedule "40 3 * * *", which is what
AuroraMeter.Oban.cron_entries/1 returns. Nothing depends on the frequency
for correctness: a row that is still eligible tomorrow is deleted tomorrow.
Do not schedule this until every node writes a heartbeat
A flush receipt is deleted only when every node's "flush:<node>"
heartbeat proves no node can still retry a batch from before the cutoff,
and a fleet that has not been upgraded yet writes none. Deploy first,
confirm one row per node with AuroraMeter.Retention.status/0, then add
the crontab entry. AuroraMeter.Retention refuses rather than guessing if
you do it in the other order, which is the safe direction, but the refusal
is easier to read before it is a surprise.
Job arguments
| Key | Default | Meaning |
|---|---|---|
"only" | every allow-list table | Which tables to consider, by name. Narrows; never widens. |
"batch_size" | 1000 | Rows per DELETE statement. |
"max_items" | 50000 | Rows one job removes per table before returning. |
Every one is a bounded integer or an allow-list name, and neither a cursor
nor a cutoff is a job argument. "only" is validated against the allow list
by AuroraMeter.Retention, so a name outside it fails the job rather than
widening what may be deleted.
Pausing
AuroraMeter.Operations.pause("retention:flush_receipts")
AuroraMeter.Operations.pause("retention:replay_checkpoints")One operation per table, because pausing receipt pruning while leaving the
replay rows alone is a thing an operator actually wants. A paused table is
reported as a :paused reason and the job still returns {:ok, report}:
the other tables were pruned, and a pause is not a failure to retry.
Running it twice
Harmless. A DELETE is idempotent: the second run's statement finds the
rows gone and removes nothing. There is no cursor to get stale, because the
scan advances by doing the work rather than by remembering a position.
Without Oban, call AuroraMeter.Retention.prune/1 from whatever scheduler
you do have. See the scheduler map and
Retention.
Summary
Functions
The checkpoint names this worker pauses and resumes under, one per table.
Prunes and returns {:ok, report}.
Functions
@spec operations() :: [String.t()]
The checkpoint names this worker pauses and resumes under, one per table.
Examples
iex> AuroraMeter.Oban.Retention.operations()
["retention:flush_receipts", "retention:replay_checkpoints"]
@spec perform(Oban.Job.t()) :: {:ok, term()} | {:error, term()} | {:cancel, term()}
Prunes and returns {:ok, report}.
{:ok, {:blocked, report, reasons}} when a table could not be pruned: a
node's heartbeat says it may still hold an old batch, or an operator paused
the operation. Neither is a failure, so neither fails the job, and both are
in the return for an operator reading Oban's completed jobs.
{:error, reason} only when the mechanism itself failed, which Oban
retries.
Examples
{:ok, _} = AuroraMeter.Oban.Retention.perform(%Oban.Job{args: %{}})