1use aws_sdk_s3::Client;
2use aws_sdk_s3::primitives::ByteStream;
3use aws_sdk_s3::types::ChecksumAlgorithm;
4
5pub async fn get_file_size(client: &Client, bucket: &str, key: &str) -> anyhow::Result<i64> {
6 let resp = client.head_object().bucket(bucket).key(key).send().await?;
7 Ok(resp.content_length.unwrap_or(0))
8}
9
10async fn append_to_file_multipart(
11 client: &Client,
12 bucket: &str,
13 key: &str,
14 content_to_append: &str,
16) -> anyhow::Result<()> {
17 let offset = get_file_size(client, bucket, key)
18 .await
19 .unwrap_or_else(|_| 0);
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(())
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::config::{Bucket, Config, CronIntervalInMs, Endpoint, ObjectSizeLimitMb, Prefix};
36 use crate::s3_helpers::{append_to_file_multipart, get_file_size};
37 use chrono::Utc;
38
39 #[tokio::test]
40 pub async fn append_to_file_test() {
41 let config = Config::new(
42 None,
43 None,
44 None,
45 Bucket(None),
46 Prefix("prefix"),
47 Endpoint(None),
48 ObjectSizeLimitMb(1),
49 CronIntervalInMs(1_000),
50 )
51 .await
52 .unwrap();
53 for _ in 0..5 {
54 let result = append_to_file_multipart(
55 &config.aws_client,
56 &config.bucket,
57 "check-file-exists.log",
58 &format!("hello world {}\n", Utc::now()),
59 )
60 .await;
61 println!("append_to_file_test result => {result:?}");
62 }
63 }
64}