use std::sync::OnceLock;
pub type AsyncInitTask<T, E> = Box<
dyn FnOnce() -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<T, E>> + Send>>
+ Send,
>;
pub struct LazyInit<T> {
cell: OnceLock<T>,
}
impl<T> LazyInit<T> {
pub const fn new() -> Self {
Self {
cell: OnceLock::new(),
}
}
#[inline]
pub fn get_or_init<F>(&self, f: F) -> &T
where
F: FnOnce() -> T,
{
self.cell.get_or_init(f)
}
#[inline]
pub fn get(&self) -> Option<&T> {
self.cell.get()
}
}
impl<T> Default for LazyInit<T> {
fn default() -> Self {
Self::new()
}
}
#[allow(dead_code)]
fn _cached_pattern_example() {
}
pub async fn parallel_init<T, E>(tasks: Vec<AsyncInitTask<T, E>>) -> Vec<Result<T, E>>
where
T: Send + 'static,
E: Send + 'static,
{
let handles: Vec<_> = tasks
.into_iter()
.map(|task| tokio::spawn(async move { task().await }))
.collect();
let mut results = Vec::new();
for handle in handles {
match handle.await {
Ok(result) => results.push(result),
Err(e) => {
panic!("Task panicked: {:?}", e);
}
}
}
results
}
#[derive(Debug, Clone)]
pub struct StartupMetrics {
pub broker_init_ms: u64,
pub config_load_ms: u64,
pub backend_init_ms: u64,
pub total_ms: u64,
}
impl StartupMetrics {
pub fn new() -> Self {
Self {
broker_init_ms: 0,
config_load_ms: 0,
backend_init_ms: 0,
total_ms: 0,
}
}
pub fn report(&self) -> String {
format!(
"Startup Performance:\n\
- Broker Init: {}ms\n\
- Config Load: {}ms\n\
- Backend Init: {}ms\n\
- Total: {}ms",
self.broker_init_ms, self.config_load_ms, self.backend_init_ms, self.total_ms
)
}
}
impl Default for StartupMetrics {
fn default() -> Self {
Self::new()
}
}
#[macro_export]
macro_rules! time_init {
($block:block) => {{
let start = std::time::Instant::now();
let result = $block;
let duration = start.elapsed();
(result, duration)
}};
}