kellnr_storage/
docs_storage.rs1use std::collections::HashSet;
2
3use bytes::Bytes;
4
5use crate::cached_crate_storage::DynStorage;
6use crate::storage::ObjectWithMeta;
7use crate::storage_error::StorageError;
8
9pub struct DocsStorage {
10 storage: DynStorage,
11}
12
13impl DocsStorage {
14 pub fn new(storage: DynStorage) -> Self {
15 Self { storage }
16 }
17
18 pub fn file_key(crate_name: &str, version: &str, relative_path: &str) -> String {
21 format!("{crate_name}/{version}/{relative_path}")
22 }
23
24 pub fn version_prefix(crate_name: &str, version: &str) -> String {
25 format!("{crate_name}/{version}/")
26 }
27
28 pub fn crate_prefix(crate_name: &str) -> String {
29 format!("{crate_name}/")
30 }
31
32 pub async fn put(&self, key: &str, data: Bytes) -> Result<(), StorageError> {
33 self.storage
34 .put_overwrite(key, data)
35 .await
36 .map_err(|e| StorageError::DocsStoreFailed {
37 key: key.to_string(),
38 reason: e.to_string(),
39 })
40 }
41
42 pub async fn get(&self, key: &str) -> Result<Bytes, StorageError> {
43 self.storage.get(key).await.map_err(|e| {
44 if matches!(
45 &e,
46 StorageError::S3Error(object_store::Error::NotFound { .. })
47 | StorageError::FileDoesNotExist(_)
48 ) {
49 return StorageError::DocsNotFound {
50 key: key.to_string(),
51 };
52 }
53 StorageError::DocsGetFailed {
54 key: key.to_string(),
55 reason: e.to_string(),
56 }
57 })
58 }
59
60 pub async fn get_with_meta(&self, key: &str) -> Result<ObjectWithMeta, StorageError> {
61 self.storage.get_with_meta(key).await.map_err(|e| {
62 if matches!(
63 &e,
64 StorageError::S3Error(object_store::Error::NotFound { .. })
65 | StorageError::FileDoesNotExist(_)
66 ) {
67 return StorageError::DocsNotFound {
68 key: key.to_string(),
69 };
70 }
71 StorageError::DocsGetFailed {
72 key: key.to_string(),
73 reason: e.to_string(),
74 }
75 })
76 }
77
78 pub async fn exists(&self, key: &str) -> Result<bool, StorageError> {
79 self.storage.exists(key).await
80 }
81
82 pub async fn delete(&self, key: &str) -> Result<(), StorageError> {
83 self.storage
84 .delete(key)
85 .await
86 .map_err(|e| StorageError::DocsDeleteFailed {
87 key: key.to_string(),
88 reason: e.to_string(),
89 })
90 }
91
92 pub async fn list(&self, prefix: &str) -> Result<Vec<String>, StorageError> {
93 self.storage
94 .list(prefix)
95 .await
96 .map_err(|e| StorageError::DocsListFailed {
97 prefix: prefix.to_string(),
98 reason: e.to_string(),
99 })
100 }
101
102 pub async fn delete_prefix(&self, prefix: &str) -> Result<(), StorageError> {
104 for key in self.list(prefix).await? {
105 self.delete(&key).await?;
106 }
107 Ok(())
108 }
109
110 pub async fn version_candidates(&self, crate_name: &str) -> Result<Vec<String>, StorageError> {
114 let prefix = Self::crate_prefix(crate_name);
115 let mut versions = HashSet::new();
116 for key in self.list(&prefix).await? {
117 if let Some(rest) = key.strip_prefix(&prefix)
118 && let Some(v) = rest.split('/').next()
119 {
120 versions.insert(v.to_string());
121 }
122 }
123 Ok(versions.into_iter().collect())
124 }
125}