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