es_entity/clock/mod.rs
1//! Time abstraction for es-entity with support for real and artificial time.
2//!
3//! This crate provides a unified interface for time operations that works
4//! identically whether using real time or artificial time for testing.
5//!
6//! # Overview
7//!
8//! The main type is [`ClockHandle`], a cheap-to-clone handle that provides:
9//! - `now()` - Get current time (synchronous, fast)
10//! - `sleep(duration)` - Sleep for a duration
11//! - `timeout(duration, future)` - Timeout a future
12//!
13//! For artificial clocks, a [`ClockController`] is also provided for controlling time.
14//!
15//! # Clock Types
16//!
17//! - **Realtime**: Uses system clock and tokio timers
18//! - **Artificial (Auto)**: Time advances automatically at a configurable scale
19//! - **Artificial (Manual)**: Time only advances via explicit `advance()` calls
20//!
21//! # Example
22//!
23//! ```rust
24//! use es_entity::clock::{ClockHandle, ArtificialClockConfig};
25//! use std::time::Duration;
26//!
27//! // Production: use real time
28//! let clock = ClockHandle::realtime();
29//!
30//! // Testing: use artificial clock with manual advancement
31//! let (clock, ctrl) = ClockHandle::artificial(ArtificialClockConfig::manual());
32//!
33//! // Same interface regardless of clock type
34//! let now = clock.now();
35//! ```
36//!
37//! # Deterministic Testing
38//!
39//! In manual mode, time only advances when you call `advance()`.
40//! Wake events are processed in chronological order, so tasks always see
41//! the correct time when they wake:
42//!
43//! ```rust
44//! use es_entity::clock::{ClockHandle, ArtificialClockConfig};
45//! use std::time::Duration;
46//!
47//! # async fn example() {
48//! let (clock, ctrl) = ClockHandle::artificial(ArtificialClockConfig::manual());
49//!
50//! let clock2 = clock.clone();
51//! tokio::spawn(async move {
52//! clock2.sleep(Duration::from_secs(3600)).await; // 1 hour
53//! // When this wakes, clock2.now() == start + 1 hour
54//! // (even if advance() jumped further)
55//! });
56//!
57//! // Advance 1 day - but the task wakes at exactly +1 hour
58//! ctrl.advance(Duration::from_secs(86400)).await;
59//! # }
60//! ```
61
62#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
63#![cfg_attr(feature = "fail-on-warnings", deny(clippy::all))]
64#![forbid(unsafe_code)]
65
66mod artificial;
67mod config;
68mod controller;
69mod global;
70mod handle;
71mod inner;
72mod realtime;
73mod sleep;
74
75// Re-export public API
76pub use config::{ArtificialClockConfig, ArtificialMode};
77pub use controller::ClockController;
78pub use global::Clock;
79pub use handle::{ClockHandle, Elapsed};
80pub use sleep::{ClockSleep, ClockTimeout};