Clock
The clock module manages frame timing for the forge runner. It provides types
for controlling tick interval, pausing and resuming the clock, and querying
clock state — all expressed as serializable request/response messages so they
can be forwarded over HTTP, WebSocket, or any async channel.
ClockAction
pub enum ClockAction {
Step,
SetInterval { interval_ms: u64 },
Pause,
Resume,
Status,
}
| Action | Effect |
|---|---|
Step |
Advance exactly one frame, regardless of interval |
SetInterval { interval_ms } |
Start or change the continuous tick interval. interval_ms = 0 means single-shot mode |
Pause |
Suspend the clock; subsequent Step commands still work |
Resume |
Restart a paused clock |
Status |
Return current ClockStatus without mutating state |
ClockRequest / ClockResponse
pub struct ClockRequest {
pub action: ClockAction,
pub session_id: String,
pub request_id: Option<String>,
}
pub struct ClockResponse {
pub success: bool,
pub status: Option<ClockStatus>,
pub error: Option<ClockError>,
pub request_id: Option<String>,
}
Build a request:
let req = ClockRequest::new(ClockAction::Pause, "session-abc")
.with_request_id("req-001");
The response echoes the request_id so callers can correlate async responses.
ClockState
ClockState is the mutable runtime state held by the clock task. It is not
part of the public serialization contract; use ClockStatus for the
observable view.
ClockStatus
pub struct ClockStatus {
pub running: bool,
pub paused: bool,
pub interval_ms: u64,
pub current_frame: i64,
pub mode: String, // "continuous" | "single_shot" | "paused"
}
Convenience predicates:
status.is_continuous() // interval_ms > 0 and not paused
status.is_single_shot() // interval_ms == 0
status.is_paused() // paused flag set
ClockError
pub struct ClockError {
pub code: String,
pub message: String,
}
Standard codes: "invalid_action", "operation_failed".
handle_clock_request
pub async fn handle_clock_request(
request: ClockRequest,
state: &ClockState,
) -> ClockResponse;
The handler is async because some actions (e.g. SetInterval) may interact with
the tokio task that drives frame advancement. It always returns a ClockResponse
rather than propagating errors, so it is safe to call over an HTTP handler
without additional error mapping.
Time Utilities
// Current wall-clock time as milliseconds since Unix epoch
pub fn current_time_ms() -> u64;
// Same, as SystemTime
pub fn now() -> std::time::SystemTime;
// Convert between u64 ms and SystemTime
pub fn ms_to_system_time(ms: u64) -> std::time::SystemTime;
pub fn system_time_to_ms(t: std::time::SystemTime) -> u64;
FrameTimestamp and FrameDuration are newtype wrappers over u64 (ms) for
type-safe frame timing arithmetic.
ClockUtils is a utility struct grouping the above functions for use from
non-async contexts where you cannot call current_time_ms() directly.