Documentation
¶
Overview ¶
Package idle provides a small scheduler for "run eventually" background work. Tasks block on Scheduler.WaitForIdle until the API has been quiet for a configurable window or a hard cap elapses, so cold-boot work like arcade DB checks or update polling doesn't compete with the launcher's first request for the single ARM core or the SQLite file lock.
Index ¶
- Variables
- type Scheduler
- func (s *Scheduler) InFlight() int64
- func (s *Scheduler) RequestEnded()
- func (s *Scheduler) RequestStarted()
- func (s *Scheduler) Schedule(ctx context.Context, name string, quietWindow, maxWait time.Duration, ...)
- func (s *Scheduler) Wait()
- func (s *Scheduler) WaitForIdle(ctx context.Context, quietWindow, maxWait time.Duration) error
Constants ¶
This section is empty.
Variables ¶
var ErrMaxWaitElapsed = errors.New("idle scheduler: max wait elapsed before idle")
ErrMaxWaitElapsed is returned by WaitForIdle when the maxWait hard cap expired before the quiet window was satisfied. Callers that want to run the task anyway (the typical case for Schedule) should treat this as a success-equivalent signal and proceed; callers that want to bail can check errors.Is(err, ErrMaxWaitElapsed).
Functions ¶
This section is empty.
Types ¶
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler tracks in-flight API requests and lets background work wait until the system has been idle for a configurable quiet window. Safe for concurrent use; the zero value is not usable, construct with New.
Wakeups use a single channel that RequestEnded closes and replaces under mu. WaitForIdle snapshots the channel under mu before reading the in- flight predicate, so a RequestEnded that races the read still wakes us (the snapshotted channel is the closed one, and the next select returns immediately rather than blocking on stale state).
func New ¶
func New() *Scheduler
New constructs a Scheduler with no in-flight requests using the real system clock.
func NewWithClock ¶
NewWithClock constructs a Scheduler using the supplied clock. Tests use this with clockwork.NewFakeClock to drive time deterministically.
func (*Scheduler) InFlight ¶
InFlight returns the current number of in-flight requests. Mostly for tests and diagnostics.
func (*Scheduler) RequestEnded ¶
func (s *Scheduler) RequestEnded()
RequestEnded decrements the in-flight counter and wakes any waiters. Pair with RequestStarted; the API server middleware should call this on request completion. The wake is done by closing the current wakeCh and replacing it with a fresh one under mu, which fans out to every goroutine currently in WaitForIdle's select.
Unmatched calls (double RequestEnded, or RequestEnded without a prior RequestStarted) clamp the counter at zero rather than letting it go negative — a negative inFlight would prevent WaitForIdle's `inFlight == 0` predicate from ever holding, wedging waiters until the maxWait cap.
func (*Scheduler) RequestStarted ¶
func (s *Scheduler) RequestStarted()
RequestStarted increments the in-flight counter. Pair with RequestEnded; the API server middleware should call this on request entry.
func (*Scheduler) Schedule ¶
func (s *Scheduler) Schedule( ctx context.Context, name string, quietWindow, maxWait time.Duration, task func(context.Context), )
Schedule spawns a goroutine that waits for an idle window then runs task. Logs the wait result; task errors are the task's responsibility. Returns immediately. The spawned goroutine is tracked internally so callers can block on Wait during shutdown to avoid racing tasks against resource teardown (e.g. database close).
func (*Scheduler) Wait ¶
func (s *Scheduler) Wait()
Wait blocks until every goroutine started by Schedule has returned. Intended for shutdown: callers should cancel the scheduler's context first so any task still in WaitForIdle exits promptly, then call Wait before tearing down resources the tasks may still be using.
func (*Scheduler) WaitForIdle ¶
WaitForIdle blocks until the in-flight counter is zero AND the time since the last request ended exceeds quietWindow, OR maxWait elapses, OR ctx is cancelled. Returns ctx.Err() on context cancellation, ErrMaxWaitElapsed when the hard cap expires before the quiet window is satisfied, and nil when the idle window is achieved.