use anyhow::Result;
use std::sync::{Arc, OnceLock};
use parking_lot::RwLock;
use tokio::time::{Duration, sleep};
use std::path::PathBuf;
static REACTIVITY_STATE: OnceLock<Arc<RwLock<ReactivityState>>> = OnceLock::new();
struct ReactivityState {
in_batch: bool,
batch_start: Option<std::time::Instant>,
}
impl Default for ReactivityState {
fn default() -> Self {
Self {
in_batch: false,
batch_start: None,
}
}
}
fn get_reactivity_state() -> Arc<RwLock<ReactivityState>> {
REACTIVITY_STATE.get_or_init(|| Arc::new(RwLock::new(ReactivityState::default()))).clone()
}
pub fn trigger_realtime_event(file: PathBuf, _content: String) -> Result<()> {
tracing::debug!("⚡ Realtime event: {:?}", file);
Ok(())
}
pub async fn trigger_debounced_event(file: PathBuf, _content: String) -> Result<()> {
tracing::debug!("⏱️ Debounced event: {:?} (300ms)", file);
sleep(Duration::from_millis(300)).await;
Ok(())
}
pub async fn trigger_idle_event(file: PathBuf) -> Result<()> {
tracing::debug!("😴 Idle event: {:?} (≥2s idle)", file);
sleep(Duration::from_secs(2)).await;
Ok(())
}
pub fn begin_batch_operation() -> Result<()> {
let state = get_reactivity_state();
let mut state = state.write();
tracing::info!("📦 Beginning batch operation");
state.in_batch = true;
state.batch_start = Some(std::time::Instant::now());
Ok(())
}
pub fn end_batch_operation() -> Result<()> {
let state = get_reactivity_state();
let mut state = state.write();
if let Some(start) = state.batch_start {
let duration = start.elapsed();
tracing::info!("✅ Batch operation completed in {:.2}s", duration.as_secs_f64());
}
state.in_batch = false;
state.batch_start = None;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_batch_operation() {
begin_batch_operation().unwrap();
end_batch_operation().unwrap();
}
#[tokio::test]
async fn test_debounced_event() {
let file = PathBuf::from("test.ts");
let result = trigger_debounced_event(file, "content".to_string()).await;
assert!(result.is_ok());
}
}