# `MishkaCmsMigration.Resources.Notifiers.Steps`
[🔗](https://github.com/mishka-group/mishka_cms_migration/blob/v0.0.1/lib/mishka_cms_migration/resources/__notifiers/steps.ex#L5)

What a run's steps tell the admins, an Ash notifier on `MishkaCmsMigration.MigrationRun`, run once
a step is saved.

Every step is an entry of the run's log (`MishkaCmsMigration.MigrationLog`): the run connected
(created), a dry run or an import started, finished, failed or was cancelled, or the run was
cancelled while it waited. The entry keeps who took the step, the run's host, a finished step's
counts and a failed step's reason, and the Migration page's Logs read it in the same sentence
the bell says (`sentence/2`), its reason in words (`MishkaCmsMigration.MigrationRun.reason_label/1`).

When a dry run or an import ends — it finished, its job failed, or an admin cancelled it while it
ran — the run's user (who created it) and the admin whose job it was (who pressed Dry run or
Import) are told in the topbar bell, through the core's `MishkaCmsCore.Notify.deliver/2`: a title
such as "Import finished", one sentence (`sentence/2`), such as "Import of localhost:8089
finished: 384 created, 371 updated, 185 skipped.", and a link to the Migration page. The admin
who cancelled a run is not told of it. Nothing told names the run's connection or its secret.
The step is saved before it is told, so an entry or a notification that cannot be written is
logged and changes nothing.

A step is the action and what it ended (`step/1`): a failure is the step of the job that failed,
its worker (`context.ash_oban.job`, which AshOban hands its trigger's `on_error`, and
`MishkaCmsMigration.Workers.Helpers.Discarded` hands on), and a cancel the step the run was in.

Each kind of notification is a type, `"migration:dry_run:finished"` through
`"migration:import:cancelled"`, which a site may turn off with the setting
`MishkaCmsCore.Notify.setting_key/1` names; none is registered, so each is on.

# `step`

```elixir
@type step() ::
  :connected
  | :dry_run_started
  | :dry_run_finished
  | :dry_run_failed
  | :dry_run_cancelled
  | :import_started
  | :import_finished
  | :import_failed
  | :import_cancelled
  | :cancelled
```

A step of a run's life (`MishkaCmsMigration.MigrationLog.steps/0`).

# `load`

# `requires_original_data?`

# `sentence`

```elixir
@spec sentence(step(), map()) :: String.t()
```

The sentence that tells `step` of a run, in the reader's language, from what its log entry keeps:
a map with the run's `source_host`, and a finished step's `counts` and a failed step's `reason`
(a `MishkaCmsMigration.MigrationLog` is one).

    sentence(:import_finished, %{source_host: "localhost:8089", counts: counts, reason: nil})
    #=> "Import of localhost:8089 finished: 384 created, 371 updated, 185 skipped."

A finished step's counts are what the run counted when it ended, so they read in the past tense:
"Dry run of localhost:8090 finished: 1,029 created, 74 skipped, 565 needed your decision."

# `step`

```elixir
@spec step(Ash.Notifier.Notification.t()) :: step() | nil
```

The step a notification of `MishkaCmsMigration.MigrationRun` saved, or `nil` for an action that
is none, such as a job saving its progress: a cancel of a run that was neither dry running nor
importing is `:cancelled`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
