AuroraMeter. Clock. Fixed
(Aurora Meter v1.0.0)
View Source
A frozen clock for tests: one Agent holding one instant.
It ships in lib/ rather than test/support/ because host test suites need
it, exactly as AuroraMeter.Test does. Drive it through
AuroraMeter.Test.with_clock/2 and AuroraMeter.Test.travel/1,2 rather than
starting it by hand: the helper serialises against other configuration
changes, restores the previous clock: value on the way out (including on a
raise) and stops the agent.
It is a single named agent, so it is global to the node: every test that
installs it must be async: false.
All four readings come from the one frozen instant, db_now/0 included. That
is the point of putting db_now/0 on the behaviour rather than leaving it as
a bare query helper: a decision that consults the database's clock is exactly
as testable as one that consults the node's, and a test can drive a cooldown
or a retry horizon across its boundary in both directions without waiting.
monotonic_ms/0 moves in step with the frozen instant: travelling forward by
90 seconds moves it by exactly 90_000. It is an offset from the real
monotonic reading taken when the agent started, not the frozen instant's epoch
milliseconds, so it shares a number line with the real monotonic clock and a
span measured across the end of a frozen block is still comparable with one
measured outside it. A cache TTL, for example, does not come back with an
expiry decades in the future.
Because db_now/0 is answered from the frozen instant, a test using this
clock stops exercising the real query. AuroraMeter.ClockTest closes that gap
deliberately with cases that call AuroraMeter.Clock.System.db_now/0.
Summary
Types
Any unit DateTime.add/3 accepts.
Functions
Moves the pinned instant by amount of unit (negative moves it back, which
is how a test reproduces a backwards step deliberately).
Returns a specification to start this module under a supervisor.
Whether the fixed clock agent is running.
Pins the clock to instant.
Starts the agent. :instant pins it immediately; without one every read
raises until set/1 is called.
Stops the agent. Safe to call when it is not running.
Types
@type unit() :: System.time_unit() | :day | :hour | :minute
Any unit DateTime.add/3 accepts.
Functions
Moves the pinned instant by amount of unit (negative moves it back, which
is how a test reproduces a backwards step deliberately).
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec running?() :: boolean()
Whether the fixed clock agent is running.
@spec set(DateTime.t()) :: :ok
Pins the clock to instant.
@spec start_link(keyword()) :: Agent.on_start()
Starts the agent. :instant pins it immediately; without one every read
raises until set/1 is called.
@spec stop() :: :ok
Stops the agent. Safe to call when it is not running.