ArrJanitor::Scheduler
Runs the configured backends: one worker fiber per backend, each looping and
running a scan whenever its backend is due?, then calling schedule_next.
Workers never touch Crystal's Log directly — they emit LogEvents through
a shared Reporter/Channel(LogEvent) that the main (calling) fiber
drains via LogConsumer.drain, so console output stays ordered across the
-Dpreview_mt worker threads.
#run_due is the decomposed, fiber-free scheduling core (iterate the
backends once, run each due one) so the scheduling decision is unit-testable
without spawning fibers or sleeping.
Constants
How often the retention-sweep fiber deletes aged processed_downloads
rows. Long by design — the audit log is swept on a TTL, not per tick.
How long a worker waits between due-checks (also the shutdown latency ceiling — a worker wakes early when the stop signal arrives).
Constructors
Instance methods
Traps INT/TERM, spawns one worker fiber per backend, then drains the
log channel on the calling (main) fiber until shutdown. A helper fiber
closes the log channel once every worker has stopped, which lets the drain
loop finish and this method return.
Iterates the backends once, running every due? backend through the
janitor and advancing its next_run. The fiber-free core of the worker
loop — call it directly in tests to exercise scheduling without fibers.
Runs a single scan pass over every backend, then returns — the one-shot
counterpart to #run. Spawns one worker fiber per backend that runs the
backend once (via run_if_due, which runs on a fresh process because
next_run is nil) and signals completion; a helper fiber closes the
store and log channel once all workers finish, which lets the drain loop
end and this method return. No signal traps, no tick loop, and no
retention sweep — those are daemon-only.
Signals the workers to stop. Idempotent — safe to call from a signal handler that may fire more than once.
Deletes processed_downloads rows older than the configured retention
window and logs how many were removed. A no-op when no store/retention is
configured. The fiber-free core of the sweep loop — call it directly in
tests to exercise the sweep without spawning a fiber.