# `VirtualClock`
[🔗](https://github.com/d-led/gen_server_virtual_time/blob/v1.1.0/packages/gen_server_virtual_time/lib/virtual_clock.ex#L1)

A GenServer that manages virtual time for testing time-dependent behaviors.

The VirtualClock maintains a virtual timestamp and scheduled events.
Time can be advanced manually, triggering all events scheduled up to that point.

## Example

    iex> {:ok, clock} = VirtualClock.start_link()
    iex> VirtualClock.now(clock)
    0
    iex> VirtualClock.advance(clock, 1000)
    {:ok, 1000}
    iex> VirtualClock.now(clock)
    1000

# `advance`

Advances the virtual clock by the specified amount of milliseconds.
All events scheduled up to the new time will be triggered.

This ensures that:
- All events up to the target time are processed
- The system reaches quiescence at the target time
- All callbacks scheduled for the target time are executed

## Examples

    # Advance by 1000ms
    VirtualClock.advance(clock, 1000)

    # Advance by 0 (process all events at current time and wait for quiescence)
    VirtualClock.advance(clock, 0)

# `advance_to_next`

Advances the virtual clock to the next scheduled event.
Returns the amount advanced in milliseconds, or 0 if no events are scheduled.

# `cancel_timer`

Cancels a scheduled timer.

Mirrors `Process.cancel_timer/1`: returns the remaining virtual time in
milliseconds until the cancelled event would have fired, or `false` if no
event is scheduled under that reference.

## Examples

    iex> {:ok, clock} = VirtualClock.start_link()
    iex> ref = VirtualClock.send_after(clock, self(), :later, 500)
    iex> VirtualClock.cancel_timer(clock, ref)
    500
    iex> VirtualClock.cancel_timer(clock, ref)
    false

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `now`

Gets the current virtual time.

# `scheduled_count`

Returns the number of events currently scheduled.

# `scheduled_count_until`

Returns the count of events scheduled up to a specific virtual time.

This is useful for waiting for quiescence within a time frame,
ignoring events scheduled for later times.

## Examples

    # Count events scheduled up to current time
    VirtualClock.scheduled_count_until(clock)

    # Count events scheduled up to 5000ms
    VirtualClock.scheduled_count_until(clock, 5000)

# `send_after`

Schedules a message to be sent after a delay in virtual time (in milliseconds).
Returns a reference that can be used to cancel the timer.

# `start_link`

Starts a new virtual clock.

## Options

  * `:ack_timeout_ms` - how long to wait for each delivery acknowledgement
    before giving up on it (default: 30000ms). This is a
    real-time safety net against an actor that stopped responding, not a
    performance budget: the clock waits for acknowledgements, it does not race
    them.

# `wait_for_quiescence`

Waits for quiescence - when all scheduled events have been processed
and no new events are being scheduled.

Retries every 10ms for up to 1000ms (1 second) by default.

## Parameters
- `clock`: The virtual clock process
- `timeout_ms`: Real-time timeout in milliseconds (default: 1000)
- `retry_interval_ms`: Retry interval in milliseconds (default: 10)

# `wait_for_quiescence_until`

Waits for quiescence within a specific virtual time frame.

This function waits for all events scheduled up to the given virtual time
to be processed, but ignores events scheduled for later times.

## Parameters
- `clock`: The virtual clock process
- `opts`: Keyword list of options:
  - `:until_time_ms` - Maximum virtual time in milliseconds to consider (default: current time)
  - `:timeout_ms` - Real-time timeout in milliseconds (default: 1000)
  - `:retry_interval_ms` - Retry interval in milliseconds (default: 10)

## Examples

    # Wait for quiescence up to current time
    VirtualClock.wait_for_quiescence_until(clock)

    # Wait for quiescence up to a specific virtual time
    VirtualClock.wait_for_quiescence_until(clock, until_time_ms: 5000)

    # Wait with custom timeout and retry interval
    VirtualClock.wait_for_quiescence_until(clock,
      until_time_ms: 1000,
      timeout_ms: 500,
      retry_interval_ms: 5
    )

---

*Consult [api-reference.md](api-reference.md) for complete listing*
