PhoenixKit.Modules.Storage.FileRepair (phoenix_kit v2.62.2)

Copy Markdown View Source

Puts one file's storage right: what FileReport.verify/1 finds wrong, and what the reconciler would make.

It does, in order:

  1. Reads every copy back (FileReport.verify/1).
  2. Copies a good copy over a bad one — a copy that is gone from its bucket or whose bytes differ from the checksum recorded for it — from another bucket that holds a good one (Manager.copy_object/3).
  3. Makes again what no good copy is left of, when it is a size made from the original (VariantGenerator.generate_variant/5, which also uses a fresh key for a repaired size). An original with no good copy anywhere cannot be made again: that is reported, not hidden — and because every size is made from the original, nothing is made from an original that is damaged.
  4. Records a copy it finds in an enabled bucket for an object with no location row (Locations.record/2).
  5. Reconciles (Reconciler.reconcile_file/1): sizes the variant set wants and the file lacks, sizes made from another spec, and copies where the storage profile wants them.
  6. Reads everything back again, so the result says what is right now.

Steps 2 to 4 run twice: a size made again may leave a bucket of the file's profile without it, and the second pass copies it there.

Returns {:ok, %{actions: [action], verification: [result]}}, where an action is %{name:, kind:, bucket:, from:} and kind is one of :restored, :regenerated, :recorded, :unrecoverable, :unreadable, :skipped, :failed or :reconciled. {:error, :edit_in_progress} while an image edit is rendering: the bytes are about to change. {:error, :busy} while another repair or reconciliation holds the file lock, or {:error, :not_found} if the file was deleted.

Summary

Types

action()

@type action() :: %{
  name: String.t(),
  kind: atom(),
  bucket: String.t() | nil,
  from: String.t() | nil
}

Functions

repair(file, opts \\ [])

@spec repair(PhoenixKit.Modules.Storage.File.t(), keyword()) ::
  {:ok,
   %{
     actions: [action()],
     verification: [map()],
     problems_left: non_neg_integer()
   }}
  | {:error, :edit_in_progress | :busy | :not_found}