fluentci_ext/cache/
s3.rs

1use std::{env, fs, io::Write};
2
3use anyhow::Error;
4use async_trait::async_trait;
5use aws_config::meta::region::RegionProviderChain;
6use aws_sdk_s3::{primitives::ByteStream, Client};
7use owo_colors::OwoColorize;
8
9use super::CacheBackend;
10
11pub struct S3 {
12    client: Client,
13    prefix: String,
14}
15
16pub async fn new() -> Result<S3, Error> {
17    let region_provider = RegionProviderChain::default_provider().or_else("us-east-1");
18
19    #[allow(deprecated)]
20    let config = aws_config::from_env()
21        .endpoint_url(std::env::var("FLUENTCI_CACHE_S3_ENDPOINT")?)
22        .region(region_provider)
23        .load()
24        .await;
25    let client = Client::new(&config);
26    let prefix = format!("{}/{}", env::consts::OS, env::consts::ARCH);
27
28    Ok(S3 { client, prefix })
29}
30
31#[async_trait]
32impl CacheBackend for S3 {
33    async fn restore(&self, path: &str) -> Result<(), Error> {
34        let filename = path.split("/").last().unwrap();
35        let bucket = env::var("FLUENTCI_CACHE_S3_BUCKET")?;
36        let key = format!("{}/{}", self.prefix, filename);
37
38        if let Ok(mut object) = self
39            .client
40            .get_object()
41            .bucket(bucket)
42            .key(key.clone())
43            .send()
44            .await
45        {
46            let mut file = fs::File::create(path)?;
47            while let Some(chunk) = object.body.try_next().await? {
48                file.write_all(&chunk)?;
49            }
50            return Ok(());
51        }
52
53        println!("{} Cache not found for key: {}", "[s3]".cyan(), key);
54
55        Ok(())
56    }
57
58    async fn save(&self, path: &str) -> Result<(), Error> {
59        let body = ByteStream::read_from()
60            .path(path)
61            .buffer_size(2048)
62            .build()
63            .await?;
64
65        let bucket = env::var("FLUENTCI_CACHE_S3_BUCKET")?;
66
67        let filename = path.split("/").last().unwrap();
68        let key = format!("{}/{}", self.prefix, filename);
69
70        match self
71            .client
72            .put_object()
73            .bucket(bucket)
74            .key(key)
75            .body(body)
76            .send()
77            .await
78        {
79            Ok(_) => {
80                println!(" Uploaded succesfully")
81            }
82            Err(e) => {
83                println!(" Failed to upload: {}", e)
84            }
85        }
86
87        Ok(())
88    }
89}