#[cfg(not(feature = "tokio"))]
fn main() {
println!("This example requires the 'tokio' feature.");
println!("Run with: cargo run --example async_autopersist --features tokio,serde");
}
#[cfg(feature = "tokio")]
#[tokio::main(flavor = "current_thread")]
async fn main() {
use chrono::Duration;
use std::sync::Arc;
use tiny_counter::storage::MemoryStorage;
use tiny_counter::EventStore;
println!("=== Async and Auto-Persist Examples ===\n");
println!("1. Auto-persistence (every 2 seconds):");
{
let store = Arc::new(
EventStore::builder()
.with_storage(MemoryStorage::new())
.auto_persist(Duration::seconds(2))
.build()
.unwrap(),
);
println!(" Recording events...");
for i in 1..=5 {
store.record("async_event");
println!(" Recorded event {} (dirty: {})", i, store.is_dirty());
tokio::time::sleep(tokio::time::Duration::from_millis(600)).await;
}
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
println!(" After auto-persist: dirty={}\n", store.is_dirty());
}
println!("2. Async workflow integration:");
{
let store = Arc::new(EventStore::new());
async fn process_request(store: Arc<EventStore>, request_id: u32) {
store.record("async_request");
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
println!(" Processed request {}", request_id);
}
let mut tasks = vec![];
for i in 0..5 {
let store = Arc::clone(&store);
tasks.push(tokio::spawn(process_request(store, i)));
}
for task in tasks {
task.await.unwrap();
}
let total = store.query("async_request").last_days(1).sum().unwrap_or(0);
println!(" Total requests processed: {}\n", total);
}
println!("3. Graceful shutdown:");
{
let store = Arc::new(
EventStore::builder()
.with_storage(MemoryStorage::new())
.auto_persist(Duration::seconds(10))
.build()
.unwrap(),
);
store.record("shutdown_event");
store.record_count("shutdown_batch", 42);
println!(" Recorded events");
println!(" Is dirty: {}", store.is_dirty());
store.persist().expect("Failed to persist");
println!(" Explicitly persisted before shutdown");
println!(" Is dirty: {}\n", store.is_dirty());
}
println!("4. Concurrent async tasks:");
{
let store = Arc::new(EventStore::new());
async fn analytics_task(store: Arc<EventStore>) {
for i in 0..10 {
store.record("analytics_tick");
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
if i % 3 == 0 {
let count = store
.query("analytics_tick")
.last_minutes(1)
.sum()
.unwrap_or(0);
println!(" Analytics: {} events so far", count);
}
}
}
async fn monitoring_task(store: Arc<EventStore>) {
for _ in 0..5 {
store.record("monitoring_check");
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
}
println!(" Monitoring: Completed checks");
}
tokio::join!(
analytics_task(Arc::clone(&store)),
monitoring_task(Arc::clone(&store)),
);
let analytics = store
.query("analytics_tick")
.last_days(1)
.sum()
.unwrap_or(0);
let monitoring = store
.query("monitoring_check")
.last_days(1)
.sum()
.unwrap_or(0);
println!(
" Final: {} analytics, {} monitoring\n",
analytics, monitoring
);
}
println!("5. Async rate limiting:");
{
use tiny_counter::TimeUnit;
let store = Arc::new(EventStore::new());
async fn make_api_call(store: Arc<EventStore>, call_id: u32) -> Result<(), String> {
let result = store
.limit()
.at_most("async_api", 5, TimeUnit::Minutes)
.check_and_record("async_api");
match result {
Ok(()) => {
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
println!(" API call {}: ✓ Success", call_id);
Ok(())
}
Err(e) => {
println!(" API call {}: ✗ Rate limited", call_id);
Err(format!("Rate limited: {}", e))
}
}
}
for i in 0..8 {
make_api_call(Arc::clone(&store), i).await.ok();
}
println!();
}
println!("6. Background metrics collection:");
{
let store = Arc::new(EventStore::new());
let bg_store = Arc::clone(&store);
let background_task = tokio::spawn(async move {
for _ in 0..5 {
bg_store.record("background_metric");
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
}
println!(" Background task: Collected metrics");
});
for _ in 0..3 {
store.record("foreground_event");
tokio::time::sleep(tokio::time::Duration::from_millis(150)).await;
}
println!(" Foreground: Processed events");
background_task.await.unwrap();
let bg = store
.query("background_metric")
.last_days(1)
.sum()
.unwrap_or(0);
let fg = store
.query("foreground_event")
.last_days(1)
.sum()
.unwrap_or(0);
println!(" Total: {} background, {} foreground", bg, fg);
}
println!("\n✓ Async patterns complete!");
}