Help us shape the future of Go! Take the 2026 Go Developer Survey

timers

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

README

pkg/controller/timers

Single-goroutine *time.Timer wrapper that papers over Go's well-known timer footguns.

Overview

SafeTimer provides safe Stop / Reset operations and exposes the channel as Chan() <-chan time.Time (returning nil when no timer is active so it blocks forever in a select). It exists because plain time.Timer.Reset after Stop returning false can leak a stale tick into the next cycle, and every component that uses timers in its event loop would otherwise re-implement the drain dance.

It must only be used from a single goroutine — there is no internal synchronisation.

Quick Start

import "github.com/haproxy-haptic/HAPTIC/pkg/controller/timers"

var t timers.SafeTimer

for {
    select {
    case event := <-eventChan:
        // Trailing-edge debounce: every event resets the countdown.
        t.Reset(5 * time.Second)
        process(event)

    case <-t.Chan():
        t.Fired() // MUST be called after receiving — clears the internal
                  // reference so Chan() goes back to nil until the next Reset.
        flush()

    case <-ctx.Done():
        t.Stop()
        return
    }
}

Fired() is easy to forget. Without it, t.timer != nil keeps reading as true even after the timer's channel was drained, so a stale reference lingers until the next Reset or Stop.

Reset implements trailing-edge debouncing. Controller event loops use it for configuration coalescing, CRD discovery settling, and drift-prevention cadence.

See Also

License

Apache-2.0 — see root LICENSE.

Documentation

Overview

Package timers provides safe timer management for event-driven controller components.

SafeTimer wraps *time.Timer with safe stop/drain/reset operations that avoid the common pitfalls of Go timer usage (leaked channels, double-drain races). It is designed for single-goroutine use within select loops.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SafeTimer

type SafeTimer struct {
	// contains filtered or unexported fields
}

SafeTimer wraps *time.Timer with safe stop, drain, reset, and channel-get operations. It must only be used from a single goroutine (no internal synchronization).

func (*SafeTimer) Chan

func (t *SafeTimer) Chan() <-chan time.Time

Chan returns the timer's channel, or nil if no timer is active. A nil channel blocks forever in a select, which is the desired behavior when there is no active timer.

func (*SafeTimer) Fired

func (t *SafeTimer) Fired()

Fired should be called when the timer's channel is read in a select case. It clears the internal reference so a new timer can be started.

func (*SafeTimer) Reset

func (t *SafeTimer) Reset(d time.Duration)

Reset stops any existing timer and starts a new one with the given duration. This implements trailing-edge debounce: every call resets the countdown.

func (*SafeTimer) Stop

func (t *SafeTimer) Stop()

Stop stops the timer if running, drains the channel, and clears the reference.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL