use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use funera_core::env::FuneraEnv;
fn main() {
let connections: Arc<Mutex<Vec<&'static str>>> = Arc::new(Mutex::new(Vec::new()));
let listeners = Arc::new(AtomicUsize::new(0));
let (env, _watcher) = FuneraEnv::new(async_openai::Client::new(), "demo-model");
env.effect({
let connections = Arc::clone(&connections);
move || {
connections.lock().unwrap().push("db");
println!("[setup] opened db connection");
Box::new(move || {
connections.lock().unwrap().retain(|c| *c != "db");
println!("[dispose] closed db connection");
})
}
});
env.effect({
let listeners = Arc::clone(&listeners);
move || {
listeners.fetch_add(1, Ordering::SeqCst);
println!("[setup] subscribed listener");
Box::new(move || {
listeners.fetch_sub(1, Ordering::SeqCst);
println!("[dispose] unsubscribed listener");
})
}
});
env.effect(|| {
println!("[setup] started consumer of listener");
Box::new(|| println!("[dispose] stopped consumer (runs first: LIFO)"))
});
println!(
"live: connections={} listeners={}",
connections.lock().unwrap().len(),
listeners.load(Ordering::SeqCst)
);
env.dispose();
assert!(connections.lock().unwrap().is_empty());
assert_eq!(listeners.load(Ordering::SeqCst), 0);
println!(
"after dispose: connections={} listeners={} — no leaks",
connections.lock().unwrap().len(),
listeners.load(Ordering::SeqCst)
);
}