Skip to main content

codetether_agent/tui/chat/sync/
batch_upload.rs

1//! Single batch upload logic.
2
3use std::path::PathBuf;
4
5use anyhow::Result;
6use minio::s3::builders::ObjectContent;
7
8use super::archive_reader::read_chat_archive_batch;
9use super::config_types::ChatSyncConfig;
10use super::minio_client::ensure_minio_bucket;
11
12pub struct ChatSyncBatch {
13    pub bytes: u64,
14    pub records: usize,
15    pub object_key: String,
16    pub next_offset: u64,
17}
18
19pub async fn sync_batch(
20    client: &minio::s3::Client,
21    archive_path: &PathBuf,
22    config: &ChatSyncConfig,
23    host_tag: &str,
24    offset: u64,
25) -> Result<Option<ChatSyncBatch>> {
26    if !archive_path.exists() {
27        return Ok(None);
28    }
29    ensure_minio_bucket(client, &config.bucket).await?;
30    let (payload, next_offset, records) = read_chat_archive_batch(archive_path, offset)?;
31    if payload.is_empty() {
32        return Ok(None);
33    }
34    let ts = chrono::Utc::now().format("%Y%m%dT%H%M%SZ");
35    let pfx = config.prefix.trim_matches('/');
36    let key = if pfx.is_empty() {
37        format!("{host_tag}/{ts}-chat-evts-{offset:020}-{next_offset:020}.jsonl")
38    } else {
39        format!("{pfx}/{host_tag}/{ts}-chat-evts-{offset:020}-{next_offset:020}.jsonl")
40    };
41    let bytes = payload.len() as u64;
42    client
43        .put_object_content(&config.bucket, &key, ObjectContent::from(payload))
44        .send()
45        .await?;
46    Ok(Some(ChatSyncBatch {
47        bytes,
48        records,
49        object_key: key,
50        next_offset,
51    }))
52}