Documentation
¶
Overview ¶
Package gc provides a generic background sweep worker used by all GC subsystems in xolu: blob storage, timeseries retention, FSM machine collection (v2), and event delivery log cleanup (v2).
The package implements the ticker-and-stop-channel lifecycle pattern once so that each sweeper only needs to implement the Sweeper interface. Workers are registered at server startup and exposed via the admin API at POST /api/v1/admin/gc/{name}/run and GET /api/v1/admin/gc.
A panic in any registered Sweeper's own Sweep method is recovered by Worker.RunOnce, logged at Error level with a stack trace, and turned into a normal error -- one GC subsystem's bug degrades to a logged failure for that subsystem's own sweeps, never a crash of the whole server. See RunOnce's own doc comment for why this exists.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Report ¶
type Report struct {
Examined int // items inspected this cycle
Collected int // items collected (deleted or hard-purged)
Quarantined int // items moved to a staging area (two-phase sweepers)
Errors int // non-fatal errors encountered
Duration time.Duration // wall time for the sweep
}
Report summarises the result of a single sweep cycle. Zero values are valid; sweepers that do not track a field leave it at 0.
type Sweeper ¶
Sweeper is implemented by each GC subsystem. Sweep must be safe to call concurrently from RunOnce and the ticker goroutine.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker runs a Sweeper on a ticker interval. It is safe for concurrent use.
func (*Worker) LastReport ¶
LastReport returns the report from the most recent completed sweep and the time it started. Returns a zero Report and zero time if no sweep has completed yet.
func (*Worker) RunOnce ¶
RunOnce executes a single sweep synchronously. Used by the admin endpoint and by tests. Safe to call concurrently with the background goroutine.
Recovers a panic from the underlying Sweeper's own Sweep method, logs it at Error level with a full stack trace, and returns it as a normal error instead of letting it propagate -- added 2026-08-04 (T-156: a real type-assertion panic in pkg/timeseries's RetentionWorker, registered as exactly this kind of Sweeper, crashed CI outright). A server should never go down because one GC subsystem has a bug; the worker survives a panicking sweep and keeps ticking on schedule, the same way it already survives a sweep that returns a normal error.
func (*Worker) Start ¶
func (w *Worker) Start()
Start launches the background sweep goroutine. Calling Start more than once on the same Worker panics.
The panic was always this method's documented contract, but the guard itself was never implemented: a second Start silently launched a second run() goroutine, and the eventual symptom was a "close of closed channel" panic in run()'s own deferred close(w.done) -- in a background goroutine, crashing the whole process, far from the call that caused it (demonstrated live by TestWorker_StartTwicePanics's own pre-fix run, which took down the test binary mid-suite attributed to a different test's name). Same lifecycle-unsafety family as pkg/server's own pre-T-140 Start/Shutdown race.
func (*Worker) Stop ¶
func (w *Worker) Stop()
Stop signals the worker to stop and blocks until the background goroutine has exited. Idempotent. Calling Stop on a worker that was never started returns immediately -- there is nothing to wait for.
The previous behaviour, documented and implemented, was to block forever on <-w.done in that case: the same sharp edge as pkg/server's own pre-T-140 Shutdown-before-Start, kept alive here purely by its documentation. Not a live bug on any known call path (every worker the server registers is Started at registration, checked directly), but a footgun with no upside. A Start after such a Stop launches a goroutine that observes the already-closed stop channel and exits at once -- harmless by construction.