codetether_agent/session/helper/
archive.rs1use std::path::PathBuf;
9
10use crate::event_stream::s3_sink::S3Sink;
11
12pub(crate) fn event_stream_path() -> Option<PathBuf> {
15 std::env::var("CODETETHER_EVENT_STREAM_PATH")
16 .ok()
17 .map(PathBuf::from)
18}
19
20pub(crate) async fn archive_event_stream_to_s3(session_id: &str, base_dir: Option<PathBuf>) {
27 if !S3Sink::is_configured() {
28 return;
29 }
30
31 let Some(base_dir) = base_dir else {
32 return;
33 };
34
35 let session_event_dir = base_dir.join(session_id);
36 if !session_event_dir.exists() {
37 return;
38 }
39
40 let Ok(sink) = S3Sink::from_env().await else {
41 tracing::warn!("Failed to create S3 sink for archival");
42 return;
43 };
44
45 let session_id = session_id.to_string();
46 tokio::spawn(async move {
47 let Ok(mut entries) = tokio::fs::read_dir(&session_event_dir).await else {
48 return;
49 };
50 while let Ok(Some(entry)) = entries.next_entry().await {
51 let path = entry.path();
52 if path.extension().is_none_or(|e| e != "jsonl") {
53 continue;
54 }
55 match sink.upload_file(&path, &session_id).await {
56 Ok(url) => tracing::info!(url = %url, "Archived event stream to S3/R2"),
57 Err(e) => tracing::warn!(error = %e, "Failed to archive event file to S3"),
58 }
59 }
60 });
61}