The migration jobs: AshOban's triggers on MishkaCmsMigration.MigrationRun generate the two
workers, MishkaCmsMigration.Workers.DryRunWorker (:run_dry_run) and
MishkaCmsMigration.Workers.ImportWorker (:run_import), each three attempts of an hour, run
as the admin who started the run (MishkaCmsMigration.Workers.Helpers.Actor). What a job does is
MishkaCmsMigration.Workers.Helpers.Pipeline. One run of a site is dry running or importing at a
time, held by the run's :one_active_per_site identity. Oban stops an attempt that runs longer
than its hour and tries the job again; an import's next attempt skips what the last one wrote and
recorded, so a large site goes on where it stopped.
This module attaches the handler that fails the run of a job Oban discards (attach/0), the one
ending AshOban's on_error cannot reach.
Telemetry
Each attempt of a job, and the New import form's connection check, tell :telemetry what they
do, so a host can attach its own handlers for metrics or logs. Every event's name starts with
:mishka_cms_migration. A reason is in words (MishkaCmsMigration.Report.reason/1), and no
event carries a connection or its secret. Durations are in :native time units.
[:mishka_cms_migration, :run, :start]— an attempt of a dry run or an import begins (:telemetry.span/3). Measurements:system_time,monotonic_time. Metadata:run_id,site_id,source(the source's id),source_hostandmode(:dry_runor:import).[:mishka_cms_migration, :run, :stop]— the attempt ended. Measurements:duration,monotonic_timeand, for a finished one, its report'screated,updated,skippedandfailedcounts. Metadata: the start's, andresult::finished;:cancelledwhen the run no longer waited for its job; or:failed, with itsreason, which AshOban tries again and, after the last attempt, fails the run on.[:mishka_cms_migration, :run, :exception]— the attempt raised past the walk's own rescue. Measurements:duration,monotonic_time. Metadata: the start's, andkind,reasonandstacktrace.[:mishka_cms_migration, :kind, :listed]— the source answered the last page of a kind. Measurements:count, the rows it listed, andpages. Metadata: the run's, andkind.[:mishka_cms_migration, :item, :settled]— an item was written and recorded, recorded as skipped or failed, or, in a dry run, reported. Measurements:duration. Metadata: the run's, and the item'skind,source_id,outcome(:created,:updated,:skippedor:failed) andreason.[:mishka_cms_migration, :connect, :refused]— a source refused to connect, at the form's check or in a job (MishkaCmsMigration.Source.connect/4). Measurements:system_time. Metadata:source,source_host,site_idandreason, and from a job the run'srun_idandmode.
A handler runs in the process that emits the event, the job's or the form's, so it should be
quick, and one that raises is detached by :telemetry:
:telemetry.attach(
"imports-to-metrics",
[:mishka_cms_migration, :run, :stop],
&MyApp.Metrics.handle_migration/4,
nil
)
Summary
Functions
Attaches MishkaCmsMigration.Workers.Helpers.Discarded.call/4 to Oban's own
[:oban, :job, :exception] telemetry, so a migration job Oban discards — its last attempt timed
out or crashed past every rescue — fails its run. MishkaCmsMigration.Application attaches it
at boot; attaching again replaces it. Only a job lost with its node, which Oban's lifeline puts
back without that event, leaves its run where it was, for an admin to cancel.
Functions
@spec attach() :: :ok | {:error, :already_exists}
Attaches MishkaCmsMigration.Workers.Helpers.Discarded.call/4 to Oban's own
[:oban, :job, :exception] telemetry, so a migration job Oban discards — its last attempt timed
out or crashed past every rescue — fails its run. MishkaCmsMigration.Application attaches it
at boot; attaching again replaces it. Only a job lost with its node, which Oban's lifeline puts
back without that event, leaves its run where it was, for an admin to cancel.