#![allow(clippy::print_stdout)]
use std::sync::Arc;
use chrono::{Duration as ChronoDuration, Utc};
use entelix::{
Episode, EpisodicMemory, ExecutionContext, InMemoryStore, Namespace, Result, Store, TenantId,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
struct TaskEvent {
task: String,
phase: String,
}
#[tokio::main]
async fn main() -> Result<()> {
let store: Arc<dyn Store<Vec<Episode<TaskEvent>>>> = Arc::new(InMemoryStore::new());
let ns = Namespace::new(TenantId::new("acme")).with_scope("worklog");
let memory = EpisodicMemory::new(store, ns);
let ctx = ExecutionContext::new();
let now = Utc::now();
let day = ChronoDuration::days(1);
let t_minus_8 = now - day * 8;
let t_minus_4 = now - day * 4;
let t_minus_3 = now - day * 3;
let t_minus_2 = now - day * 2;
let t_minus_1 = now - day;
memory
.append_at(&ctx, evt("ingest", "started"), t_minus_8)
.await?;
memory
.append_at(&ctx, evt("ingest", "complete"), t_minus_8)
.await?;
memory
.append_at(&ctx, evt("classify", "started"), t_minus_4)
.await?;
memory
.append_at(&ctx, evt("classify", "complete"), t_minus_3)
.await?;
memory
.append_at(&ctx, evt("publish", "started"), t_minus_2)
.await?;
memory
.append_at(&ctx, evt("publish", "complete"), t_minus_1)
.await?;
println!("=== total episodes ===");
println!(" {}", memory.count(&ctx).await?);
println!("\n=== recent(3) — last three in reverse chronological ===");
for e in memory.recent(&ctx, 3).await? {
print_episode(&e, now);
}
println!("\n=== range(t-4d, t-3d) — closed interval ===");
for e in memory.range(&ctx, t_minus_4, t_minus_3).await? {
print_episode(&e, now);
}
println!("\n=== since(t-2d) — checkpoint and forward ===");
for e in memory.since(&ctx, t_minus_2).await? {
print_episode(&e, now);
}
let pruned = memory
.prune_older_than(&ctx, std::time::Duration::from_mins(10_080))
.await?;
println!("\n=== prune_older_than(7 days) ===");
println!(" pruned: {pruned}");
println!(" remaining: {}", memory.count(&ctx).await?);
Ok(())
}
fn evt(task: &str, phase: &str) -> TaskEvent {
TaskEvent {
task: task.to_owned(),
phase: phase.to_owned(),
}
}
fn print_episode(e: &Episode<TaskEvent>, now: chrono::DateTime<Utc>) {
let days_back = (now - e.timestamp).num_days();
println!(
" [t-{days_back}d] {task} → {phase}",
task = e.payload.task,
phase = e.payload.phase,
);
}