Skip to main content

aimdb_core/
context.rs

1//! Runtime context for AimDB services
2//!
3//! Provides a unified interface to runtime capabilities like sleep and timestamp
4//! functions, abstracting away the specific runtime adapter implementation.
5
6#[cfg(not(feature = "std"))]
7extern crate alloc;
8
9use aimdb_executor::Runtime;
10use core::future::Future;
11
12/// Unified runtime context for AimDB services
13///
14/// Provides access to runtime capabilities (sleep, timestamps) through
15/// a unified API, abstracting the underlying runtime implementation.
16///
17/// Services receive this context for timing operations without knowing
18/// about the specific runtime adapter.
19#[derive(Clone)]
20pub struct RuntimeContext<R>
21where
22    R: Runtime,
23{
24    #[cfg(feature = "std")]
25    runtime: std::sync::Arc<R>,
26    #[cfg(not(feature = "std"))]
27    runtime: alloc::sync::Arc<R>,
28}
29
30#[cfg(feature = "std")]
31impl<R> RuntimeContext<R>
32where
33    R: Runtime,
34{
35    /// Create a new RuntimeContext (std version uses Arc internally)
36    pub fn new(runtime: R) -> Self {
37        Self {
38            runtime: std::sync::Arc::new(runtime),
39        }
40    }
41
42    /// Create from an existing Arc to avoid double-wrapping
43    pub fn from_arc(runtime: std::sync::Arc<R>) -> Self {
44        Self { runtime }
45    }
46
47    /// Extract runtime context from type-erased Arc (std version)
48    ///
49    /// This is a helper for runtime adapters to convert the raw `Arc<dyn Any>`
50    /// context passed to `.source_raw()` and `.tap_raw()` into a typed `RuntimeContext`.
51    ///
52    /// # Panics
53    /// Panics if the runtime type doesn't match `R`.
54    pub fn extract_from_any(ctx_any: std::sync::Arc<dyn core::any::Any + Send + Sync>) -> Self {
55        let runtime = ctx_any
56            .downcast::<R>()
57            .expect("Runtime type mismatch - expected matching runtime adapter");
58        Self::from_arc(runtime.clone())
59    }
60}
61
62#[cfg(not(feature = "std"))]
63impl<R> RuntimeContext<R>
64where
65    R: Runtime,
66{
67    /// Create a new RuntimeContext (no_std version uses Arc internally)
68    pub fn new(runtime: R) -> Self {
69        Self {
70            runtime: alloc::sync::Arc::new(runtime),
71        }
72    }
73
74    /// Create from an existing Arc to avoid double-wrapping
75    pub fn from_arc(runtime: alloc::sync::Arc<R>) -> Self {
76        Self { runtime }
77    }
78
79    /// Extract runtime context from type-erased Arc (no_std version)
80    ///
81    /// This is a helper for runtime adapters to convert the raw `Arc<dyn Any>`
82    /// context passed to `.source_raw()` and `.tap_raw()` into a typed `RuntimeContext`.
83    ///
84    /// # Panics
85    /// Panics if the runtime type doesn't match `R`.
86    pub fn extract_from_any(ctx_any: alloc::sync::Arc<dyn core::any::Any + Send + Sync>) -> Self {
87        let runtime = ctx_any
88            .downcast::<R>()
89            .expect("Runtime type mismatch - expected matching runtime adapter");
90        Self::from_arc(runtime)
91    }
92}
93
94impl<R> RuntimeContext<R>
95where
96    R: Runtime,
97{
98    /// Access time utilities
99    ///
100    /// Returns a time accessor for duration creation, sleep, and timing operations.
101    pub fn time(&self) -> Time<'_, R> {
102        Time { ctx: self }
103    }
104
105    /// Access logging utilities
106    pub fn log(&self) -> Log<'_, R> {
107        Log { ctx: self }
108    }
109
110    /// Get access to the underlying runtime
111    ///
112    /// This provides direct access to the runtime for advanced use cases.
113    #[cfg(feature = "std")]
114    pub fn runtime(&self) -> &R {
115        &self.runtime
116    }
117
118    #[cfg(not(feature = "std"))]
119    pub fn runtime(&self) -> &R {
120        &self.runtime
121    }
122}
123
124#[cfg(feature = "std")]
125impl<R> RuntimeContext<R>
126where
127    R: Runtime,
128{
129    /// Create a RuntimeContext from a runtime adapter (std version with Arc)
130    pub fn from_runtime(runtime: R) -> Self {
131        Self::new(runtime)
132    }
133}
134
135/// Create a RuntimeContext from any Runtime implementation (std version)
136#[cfg(feature = "std")]
137pub fn create_runtime_context<R>(runtime: R) -> RuntimeContext<R>
138where
139    R: Runtime,
140{
141    RuntimeContext::from_runtime(runtime)
142}
143
144/// Time utilities accessor for RuntimeContext
145///
146/// Provides duration creation, sleep, and timing measurements.
147pub struct Time<'a, R: Runtime> {
148    ctx: &'a RuntimeContext<R>,
149}
150
151impl<'a, R: Runtime> Time<'a, R> {
152    /// Create a duration from milliseconds
153    pub fn millis(&self, millis: u64) -> R::Duration {
154        self.ctx.runtime.millis(millis)
155    }
156
157    /// Create a duration from seconds
158    pub fn secs(&self, secs: u64) -> R::Duration {
159        self.ctx.runtime.secs(secs)
160    }
161
162    /// Create a duration from microseconds
163    pub fn micros(&self, micros: u64) -> R::Duration {
164        self.ctx.runtime.micros(micros)
165    }
166
167    /// Sleep for the specified duration
168    pub fn sleep(&self, duration: R::Duration) -> impl Future<Output = ()> + Send + '_ {
169        self.ctx.runtime.sleep(duration)
170    }
171
172    /// Get the current timestamp
173    pub fn now(&self) -> R::Instant {
174        self.ctx.runtime.now()
175    }
176
177    /// Get the duration between two instants
178    ///
179    /// Returns None if `later` is before `earlier`.
180    pub fn duration_since(&self, later: R::Instant, earlier: R::Instant) -> Option<R::Duration> {
181        self.ctx.runtime.duration_since(later, earlier)
182    }
183
184    /// Number of whole nanoseconds in a duration (runtime-agnostic).
185    pub fn duration_as_nanos(&self, duration: R::Duration) -> u64 {
186        self.ctx.runtime.duration_as_nanos(duration)
187    }
188}
189
190/// Log utilities accessor for RuntimeContext
191///
192/// Provides structured logging operations.
193pub struct Log<'a, R: Runtime> {
194    ctx: &'a RuntimeContext<R>,
195}
196
197impl<'a, R: Runtime> Log<'a, R> {
198    /// Log an informational message
199    pub fn info(&self, message: &str) {
200        self.ctx.runtime.info(message)
201    }
202
203    /// Log a debug message
204    pub fn debug(&self, message: &str) {
205        self.ctx.runtime.debug(message)
206    }
207
208    /// Log a warning message
209    pub fn warn(&self, message: &str) {
210        self.ctx.runtime.warn(message)
211    }
212
213    /// Log an error message
214    pub fn error(&self, message: &str) {
215        self.ctx.runtime.error(message)
216    }
217}