Skip to main content

codetether_agent/tui/chat/sync/
s3_key.rs

1//! S3 key sanitization and checkpoint path helpers.
2
3use std::path::{Path, PathBuf};
4
5use super::config_types::ChatSyncConfig;
6
7pub fn sanitize_s3_key_segment(value: &str) -> String {
8    let mut out = String::with_capacity(value.len());
9    for ch in value.chars() {
10        if ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.') {
11            out.push(ch);
12        } else {
13            out.push('-');
14        }
15    }
16    let cleaned = out.trim_matches('-').to_string();
17    if cleaned.is_empty() {
18        "unknown".into()
19    } else {
20        cleaned
21    }
22}
23
24pub fn chat_sync_checkpoint_path(archive_path: &Path, config: &ChatSyncConfig) -> PathBuf {
25    let e = sanitize_s3_key_segment(&config.endpoint.replace("://", "-"));
26    let b = sanitize_s3_key_segment(&config.bucket);
27    archive_path.with_file_name(format!("chat_events.minio-sync.{e}.{b}.offset"))
28}
29
30pub fn load_chat_sync_offset(checkpoint_path: &Path) -> u64 {
31    std::fs::read_to_string(checkpoint_path)
32        .ok()
33        .and_then(|v| v.trim().parse::<u64>().ok())
34        .unwrap_or(0)
35}
36
37pub fn store_chat_sync_offset(checkpoint_path: &Path, offset: u64) {
38    if let Err(err) = std::fs::write(checkpoint_path, offset.to_string()) {
39        tracing::warn!(error = %err, "Failed to store chat sync offset");
40    }
41}