1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-06-27 16:35:59 +00:00

feat(service/media): add deep hashed directory structure for S3

This commit is contained in:
AndSDev 2025-06-06 17:19:18 +03:00
parent 2c47045659
commit 59e4f4d8f1
3 changed files with 64 additions and 19 deletions

View file

@ -250,6 +250,8 @@ impl From<IncompleteConfig> for Config {
secret, secret,
duration, duration,
bucket_use_path, bucket_use_path,
path,
directory_structure,
} => { } => {
let path_style = if bucket_use_path { let path_style = if bucket_use_path {
rusty_s3::UrlStyle::Path rusty_s3::UrlStyle::Path
@ -263,9 +265,11 @@ impl From<IncompleteConfig> for Config {
let credentials = rusty_s3::Credentials::new(key, secret); let credentials = rusty_s3::Credentials::new(key, secret);
MediaBackendConfig::S3 { MediaBackendConfig::S3 {
bucket: bucket, bucket,
credentials: credentials, credentials,
duration: Duration::from_secs(duration), duration: Duration::from_secs(duration),
path,
directory_structure,
} }
} }
}, },
@ -517,6 +521,9 @@ pub enum IncompleteMediaBackendConfig {
duration: u64, duration: u64,
#[serde(default = "false_fn")] #[serde(default = "false_fn")]
bucket_use_path: bool, bucket_use_path: bool,
path: Option<String>,
#[serde(default)]
directory_structure: DirectoryStructure,
}, },
} }
@ -539,6 +546,8 @@ pub enum MediaBackendConfig {
bucket: rusty_s3::Bucket, bucket: rusty_s3::Bucket,
credentials: rusty_s3::Credentials, credentials: rusty_s3::Credentials,
duration: Duration, duration: Duration,
path: Option<String>,
directory_structure: DirectoryStructure,
}, },
} }

View file

@ -488,24 +488,41 @@ impl Service {
directory_structure: &DirectoryStructure, directory_structure: &DirectoryStructure,
sha256_hex: &str, sha256_hex: &str,
) -> Result<PathBuf> { ) -> Result<PathBuf> {
let mut r = PathBuf::new(); Ok(PathBuf::from_iter(self.split_media_path(
r.push(media_directory); Some(media_directory),
directory_structure,
sha256_hex,
)?))
}
if let DirectoryStructure::Deep { length, depth } = directory_structure { pub fn split_media_path<'a>(
&self,
media_directory: Option<&'a str>,
directory_structure: &DirectoryStructure,
sha256_hex: &'a str,
) -> Result<Vec<&'a str>> {
match directory_structure {
DirectoryStructure::Flat => match media_directory {
Some(path) => Ok(vec![path, sha256_hex]),
None => Ok(vec![sha256_hex]),
},
DirectoryStructure::Deep { length, depth } => {
let mut r: Vec<&'a str> = Vec::with_capacity((depth.get() + 2).into());
if let Some(path) = media_directory {
r.push(path);
}
let mut filename = sha256_hex; let mut filename = sha256_hex;
for _ in 0..depth.get() { for _ in 0..depth.get() {
let (current_path, next) = filename.split_at(length.get().into()); let (current_path, next) = filename.split_at(length.get().into());
filename = next; filename = next;
r.push(current_path); r.push(current_path);
} }
r.push(filename); r.push(filename);
} else {
r.push(sha256_hex);
}
Ok(r) Ok(r)
} }
}
}
pub fn shutdown(&self) { pub fn shutdown(&self) {
self.shutdown.store(true, atomic::Ordering::Relaxed); self.shutdown.store(true, atomic::Ordering::Relaxed);

View file

@ -621,10 +621,16 @@ impl Service {
bucket, bucket,
credentials, credentials,
duration, duration,
path,
directory_structure,
} => { } => {
let sha256_hex = hex::encode(sha256_digest); let sha256_hex = hex::encode(sha256_digest);
let file_name = services()
.globals
.split_media_path(path.as_deref(), directory_structure, &sha256_hex)?
.join("/");
let url = bucket let url = bucket
.get_object(Some(credentials), &sha256_hex) .get_object(Some(credentials), &file_name)
.sign(*duration); .sign(*duration);
let client = services().globals.default_client(); let client = services().globals.default_client();
@ -680,9 +686,16 @@ pub async fn create_file(sha256_hex: &str, file: &[u8]) -> Result<()> {
bucket, bucket,
credentials, credentials,
duration, duration,
path,
directory_structure,
} => { } => {
let file_name = services()
.globals
.split_media_path(path.as_deref(), directory_structure, sha256_hex)?
.join("/");
let url = bucket let url = bucket
.put_object(Some(credentials), sha256_hex) .put_object(Some(credentials), &file_name)
.sign(*duration); .sign(*duration);
let client = services().globals.default_client(); let client = services().globals.default_client();
@ -767,9 +780,15 @@ async fn delete_file(sha256_hex: &str) -> Result<()> {
bucket, bucket,
credentials, credentials,
duration, duration,
path,
directory_structure,
} => { } => {
let file_name = services()
.globals
.split_media_path(path.as_deref(), directory_structure, sha256_hex)?
.join("/");
let url = bucket let url = bucket
.delete_object(Some(credentials), sha256_hex) .delete_object(Some(credentials), &file_name)
.sign(*duration); .sign(*duration);
let client = services().globals.default_client(); let client = services().globals.default_client();