1use aws_sdk_s3::Client;
2use aws_sdk_s3::primitives::ByteStream;
3use aws_sdk_s3::types::ChecksumAlgorithm;
4
5pub struct S3Helpers {}
6
7impl S3Helpers {
8 pub async fn get_file_size(client: &Client, bucket: &str, key: &str) -> anyhow::Result<i64> {
9 let resp = client.head_object().bucket(bucket).key(key).send().await?;
10 Ok(resp.content_length.unwrap_or(0))
11 }
12 pub async fn append_to_file(
13 client: &Client,
14 bucket: &str,
15 key: &str,
16 content_to_append: &str,
17 ) -> anyhow::Result<u64> {
18 let offset = Self::get_file_size(client, bucket, key).await.unwrap_or(0);
19 let total_len = offset as u64 + content_to_append.len() as u64;
20 let content_to_append = content_to_append.as_bytes().to_vec();
21 client
22 .put_object()
23 .set_write_offset_bytes(Some(offset))
24 .checksum_algorithm(ChecksumAlgorithm::Crc64Nvme)
25 .bucket(bucket)
26 .key(key)
27 .body(ByteStream::from(content_to_append)) .send()
29 .await?;
30 Ok(total_len)
31 }
32}
33
34#[cfg(test)]
35mod tests {
36
37 use crate::config::tracing_s3_config::TracingS3Config;
38 use crate::config::types::{
39 Bucket, BufferSizeLimitKb, CronIntervalInMs, Endpoint, ObjectSizeLimitMb, Postfix, Prefix,
40 };
41 use crate::s3_helpers::S3Helpers;
42 use chrono::Utc;
43
44 #[tokio::test]
45 pub async fn append_to_file_test() {
46 let config = TracingS3Config::new(
47 None,
48 None,
49 None,
50 Bucket(None),
51 Prefix("prefix"),
52 Postfix("log"),
53 Endpoint(None),
54 ObjectSizeLimitMb::new(1).unwrap(),
55 CronIntervalInMs::new(1_000).unwrap(),
56 BufferSizeLimitKb::new(1).unwrap(),
57 )
58 .await
59 .unwrap();
60 for _ in 0..5 {
61 let _result = S3Helpers::append_to_file(
62 &config.aws_client,
63 &config.bucket,
64 "check-file-exists.log",
65 &format!("hello world {}\n", Utc::now()),
66 )
67 .await;
68 }
69 }
70}