Documentation
¶
Overview ¶
Package clock abstracts the passage of time so that the election loop can be driven deterministically by tests.
The election loop reads time for exactly two purposes: to schedule its next action, and to compute how long it may keep believing it is the leader. The second one is a safety property, so the tests that exercise it must not depend on wall-clock timing to pass.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Clock ¶
type Clock interface {
// Now returns the current time. Callers must only use differences between
// values returned by the same Clock; with [System] those differences are
// monotonic and unaffected by wall-clock adjustments.
Now() time.Time
// NewTimer returns a timer that fires once after d.
NewTimer(d time.Duration) Timer
// WithTimeout derives a context that is cancelled after d has elapsed on
// this Clock.
WithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
}
Clock provides the subset of the time package the election loop needs.
type Fake ¶
type Fake struct {
// contains filtered or unexported fields
}
Fake is a Clock whose time only moves when a test moves it.
Two properties make it usable for testing a concurrent loop:
- Fake.Advance fires due timers in chronological order and does not return until every fired value has been received. When it returns, the goroutines it woke are running rather than merely runnable.
- Fake.WaitForTimers blocks until at least n timers are armed, which lets a test wait for the loop to reach its next scheduling point instead of guessing.
Fake is safe for concurrent use.
func (*Fake) Advance ¶
Advance moves the clock forward by d, firing every timer that becomes due.
Timers fire in deadline order, with the clock positioned at each timer's own deadline as it fires, so a timer armed by a goroutine that Advance just woke still observes a consistent view of time. Advance returns only after every fired value has been received or its timer has been stopped.
func (*Fake) WaitForTimers ¶
WaitForTimers blocks until at least n timers are armed. It is the synchronisation point a test uses to know the loop under test has finished reacting and is waiting for time to pass again.
func (*Fake) WithTimeout ¶
func (f *Fake) WithTimeout(parent context.Context, d time.Duration) (context.Context, context.CancelFunc)
WithTimeout derives a context cancelled once the fake clock advances past d.
Because the deadline is virtual, the context is cancelled rather than expired: ctx.Err reports context.Canceled while context.Cause reports context.DeadlineExceeded. Code under test should consult context.Cause, which behaves identically under the system clock.
type Timer ¶
type Timer interface {
// C is the channel on which the firing time is delivered.
C() <-chan time.Time
// Reset restarts the timer to fire after d. It is safe to call after the
// timer has fired and been received from.
Reset(d time.Duration)
// Stop prevents the timer from firing. It is idempotent.
Stop()
}
Timer is a single-shot timer. A Timer has one owning goroutine: Reset and Stop must not be called concurrently with a receive from C.