Image.Plug.VariantStore.Persistence behaviour (image_plug v0.1.0)

Copy Markdown View Source

Behaviour for persisting variants across application restarts.

A persistence backend is responsible for two things:

  • load/1 — called once at boot when the variant store initialises. Returns the list of previously-stored variants. The store seeds them into its table before applying any application-env seeds.

  • write/4 — called after every successful put or delete. Write-through, fire-and-forget: failures are logged at :warn but do not fail the originating CRUD operation.

Built-in backends

Configuration

Configure on the ETS variant store:

plug Image.Plug,
  ...
  variant_store: {Image.Plug.VariantStore.ETS, [
    persistence:
      {Image.Plug.VariantStore.Persistence.File,
       path: "/var/lib/image_plug/variants.json"}
  ]}

Persistable variants

Only variants whose :options field is set (i.e. variants created from a CDN-grammar options string) are persisted. Variants built programmatically from an Image.Plug.Pipeline struct (no options string) cannot be round-tripped without a pipeline codec and are skipped with a warning. If you build pipelines programmatically and want them persisted, also set the :options field with an equivalent options string.

Provider

Persisted variants store the original options string, not the parsed pipeline. At load time the string is re-parsed via the :provider option (defaulting to Image.Plug.Provider.Cloudflare). This dodges the JSON-serialisation problem for pipeline ops, which embed atoms and struct types that don't survive a round-trip cleanly.

Summary

Callbacks

Loads previously-persisted variants.

Writes a single variant change.

Callbacks

load(options)

@callback load(options :: keyword()) :: {:ok, [Image.Plug.Variant.t()]} | {:error, term()}

Loads previously-persisted variants.

Arguments

  • options is the keyword list configured on the persistence entry.

Returns

  • {:ok, [variant]} on success. Empty list is fine — first run.

  • {:error, reason} to abort boot. Use sparingly; a fresh install with no persisted state is the normal first-boot condition and should return {:ok, []}, not an error.

write(action, name, variant, options)

@callback write(
  action :: :put | :delete,
  name :: String.t(),
  variant :: Image.Plug.Variant.t() | nil,
  options :: keyword()
) :: :ok | {:error, term()}

Writes a single variant change.

Called after every successful put or delete on the variant store. Receives the action (:put or :delete), the variant name, and either the new variant struct (for :put) or nil (for :delete).

Returns

  • :ok on success.

  • {:error, reason} on failure. The store logs the error at :warn but does not fail the originating CRUD call — persistence is fire-and-forget.