Cluster-singleton garbage collector that reconciles the blobs table against
the shared medium: a :present blob whose backing file is gone is a stale row
and is pruned. Runs continuously, one keyset page at a time.
Deletes are irreversible, so a blob is pruned only when all of these agree it is really gone:
- Errno discrimination -
Hyper.Node.Layer.Repo.find_layer/1reports:enoentonly for a true absence; any other I/O error (NFSESTALE/EIO, a vanished mount) is treated as:unknownand never pruned. - Mount re-check -
test_system/0is re-checked after a page's probes and before its deletes, so a mount that drops mid-page can't trigger a mass delete. - Grace period - rows younger than
grace_periodare never deleted, so a blob mid-publish (row present, file not finished) is safe.
The DELETE is also guarded by NOT EXISTS against image_layers, so it can
never violate the FK. A missing-file blob still referenced by an image is a
dangling reference (data loss the GC can't fix) - left in place and reported,
never deleted.
Publish contract: write a layer's file to the medium before inserting its
blobs row (ideally write-temp then atomic rename); the grace period is
insurance, not a substitute.
The delete step itself lives in Hyper.Img.Db.Gc.Prune.
Summary
Functions
Returns a specification to start this module under a supervisor.
Local role + last completed sweep, for introspection on this node.
Types
@type t() :: %Hyper.Img.Db.Gc{ config: Hyper.Cfg.Gc.t(), last_sweep: Hyper.Img.Db.Gc.Sweep.State.t() | nil, role: :active | :standby, sweep: Hyper.Img.Db.Gc.Sweep.State.t() | nil }
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec start_link(keyword()) :: GenServer.on_start()
@spec status() :: %{
role: :active | :standby,
last_sweep: Hyper.Img.Db.Gc.Sweep.State.t() | nil
}
Local role + last completed sweep, for introspection on this node.