codetether_agent/session/
tail_load.rs1use std::fs::File;
8use std::io::BufReader;
9use std::path::{Path, PathBuf};
10
11use anyhow::{Context, Result};
12
13use super::tail_seed::with_tail_cap;
14use super::types::Session;
15
16#[derive(Debug)]
18pub struct TailLoad {
19 pub session: Session,
21 pub dropped: usize,
24 pub file_bytes: u64,
26}
27
28impl Session {
29 pub async fn load_tail(id: &str, window: usize) -> Result<TailLoad> {
36 let path = Self::session_path(id)?;
37 Self::load_tail_from_path(path, window).await
38 }
39
40 pub async fn load_tail_from_path(path: PathBuf, window: usize) -> Result<TailLoad> {
42 tokio::task::spawn_blocking(move || parse_tail(&path, window))
43 .await
44 .context("session tail-load task panicked")?
45 }
46}
47
48fn parse_tail(path: &Path, window: usize) -> Result<TailLoad> {
49 let file_bytes = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0);
50 let file = File::open(path).with_context(|| format!("open session file {}", path.display()))?;
51 let reader = BufReader::with_capacity(64 * 1024, file);
52 let (parsed, dropped) = with_tail_cap(window, || {
53 serde_json::from_reader::<_, Session>(reader)
54 .with_context(|| format!("parse session file {}", path.display()))
55 });
56 Ok(TailLoad {
57 session: parsed?,
58 dropped,
59 file_bytes,
60 })
61}