# `MishkaCmsMigration.Resources.Validations.Status`
[🔗](https://github.com/mishka-group/mishka_cms_migration/blob/v0.0.1/lib/mishka_cms_migration/resources/__validations/status.ex#L5)

Holds a run's move to the statuses it may come from: the status the run is in before the action,
not the one the action sets.

    update :start_import do
      validate {MishkaCmsMigration.Resources.Validations.Status, from: [:dry_run]}
      change set_attribute(:status, :importing)
    end

Run atomically, it is a condition of the update itself, so two requests that both read the run
before either wrote it cannot both move it.

With `as_read: true` the run must also still be in the status the caller read it in, so what the
action takes from that status, such as the status a job of picked items puts the run back in
(`MishkaCmsMigration.Resources.Changes.PickedItems`), is the one the database held. A run read
before it moved on is refused with the status it is in now.

    validate {MishkaCmsMigration.Resources.Validations.Status, from: [:done], as_read: true}

A refused run is an `Ash.Error.Changes.InvalidAttribute` on `status` whose message says, in
words, what the run is doing and what to do, such as "An import of this run is running. Wait until
it finishes, then try again." It names no variable, so the same sentence reads in a flash and in
the log, and the atomic check picks it in the database by the status the run is in.

# `running?`

```elixir
@spec running?(term()) :: boolean()
```

Whether `error` is this validation's refusal of a run whose dry run or import is running now,
which holds once that job is done, unlike a refusal of a run in a status it never leaves on its
own, such as a cancelled one.

---

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