Hyper.Img.Db.Gc.Prune (Hyper v0.1.0)

Copy Markdown View Source

The delete step of the layer GC, factored out of the Gc server so its safety contracts are testable against a real database without the cluster-singleton GenServer around them:

  • a missing blob still referenced by an image is dangling — reported, never deleted;
  • rows younger than grace_period are never deleted;
  • the DELETE re-checks NOT EXISTS (image_layers), so a reference that appeared after the caller's snapshot is skipped, not violated;
  • the shared medium is re-probed before any delete, so a mount that vanished mid-page skips the page instead of mass-deleting;
  • presence/1 maps only a true :enoent to :missing; any other I/O error is :unknown and never drives a delete.

Every query runs at low priority: in a transaction with a capped per-statement timeout, so the GC can never pin a backend.

Summary

Functions

Act on one page's missing set: re-check the medium is still mounted, split dangling (still referenced) from prunable, delete what is out of grace. Returns {pruned, pruned_bytes, dangling}.

Shared-medium presence probe injected into the pure Sweep core. Distinguishes a genuine absence (:enoent -> prunable) from an I/O error (:unknown -> never pruned), so a transient NFS hiccup can never drive a delete.

Run a DB operation at low priority: in a transaction with a capped per-statement timeout, so it can never pin a backend and yields under contention.

Functions

execute(config, missing)

Act on one page's missing set: re-check the medium is still mounted, split dangling (still referenced) from prunable, delete what is out of grace. Returns {pruned, pruned_bytes, dangling}.

presence(id)

@spec presence(String.t()) :: Hyper.Img.Db.Gc.Sweep.presence()

Shared-medium presence probe injected into the pure Sweep core. Distinguishes a genuine absence (:enoent -> prunable) from an I/O error (:unknown -> never pruned), so a transient NFS hiccup can never drive a delete.

with_low_priority(config, fun)

@spec with_low_priority(Hyper.Cfg.Gc.t(), (-> result)) :: result when result: var

Run a DB operation at low priority: in a transaction with a capped per-statement timeout, so it can never pin a backend and yields under contention.