use bison_db::{Db, DbOptions, DocId, Document, SyncPolicy, Value};
fn session(user_id: i64, created_at: i64, agent: &str) -> Document {
let mut d = Document::new();
d.set("user_id", user_id)
.set("created_at", created_at)
.set("agent", agent);
d
}
fn login(db: &mut Db, user_id: i64, created_at: i64, agent: &str) -> bison_db::Result<DocId> {
db.insert(session(user_id, created_at, agent))
}
fn logout_everywhere(db: &mut Db, user_id: i64) -> bison_db::Result<usize> {
let ids = db.find("user_id", &Value::from(user_id))?;
for id in &ids {
db.delete(*id)?;
}
Ok(ids.len())
}
fn main() -> bison_db::Result<()> {
let path = std::env::temp_dir().join("bison_db_session_store.bison");
let _ = std::fs::remove_file(&path);
let mut db = Db::open_with(&path, DbOptions::new().sync(SyncPolicy::Always))?;
db.create_index("user_id")?;
let alice = 1001;
let bob = 1002;
let a1 = login(&mut db, alice, 1_700_000_000, "Firefox/Linux")?;
let _a2 = login(&mut db, alice, 1_700_000_300, "Safari/iOS")?;
let b1 = login(&mut db, bob, 1_700_000_500, "Chrome/Windows")?;
println!("opened {} sessions", db.len());
if let Some(s) = db.get(a1)? {
let agent = s.get("agent").and_then(Value::as_str).unwrap_or("?");
println!(
"session {a1} belongs to user {} via {agent}",
s.get("user_id").and_then(Value::as_int).unwrap_or(0)
);
}
let revoked = logout_everywhere(&mut db, alice)?;
println!("revoked {revoked} sessions for user {alice}");
assert!(db.get(a1)?.is_none());
assert!(db.get(b1)?.is_some());
let before = db.stats().file_bytes;
db.compact()?;
println!(
"compacted {} -> {} bytes, {} live session(s)",
before,
db.stats().file_bytes,
db.len()
);
let _ = std::fs::remove_file(&path);
Ok(())
}