xet_data/processing/
configurations.rs1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3
4use http::HeaderMap;
5use tracing::info;
6use xet_client::cas_client::auth::AuthConfig;
7use xet_runtime::core::XetContext;
8#[cfg(not(target_family = "wasm"))]
9use xet_runtime::core::xet_cache_root;
10
11use crate::error::Result;
12
13#[derive(Debug, Clone)]
16pub struct SessionContext {
17 pub endpoint: String,
20 pub auth: Option<AuthConfig>,
21 pub custom_headers: Option<Arc<HeaderMap>>,
22 pub repo_paths: Vec<String>,
23 pub session_id: Option<String>,
24}
25
26impl SessionContext {
27 pub fn is_local(&self, ctx: &XetContext) -> bool {
29 self.endpoint.starts_with(ctx.config.data.local_cas_scheme.as_str())
30 }
31
32 pub fn local_path(&self, ctx: &XetContext) -> Option<PathBuf> {
34 let path = self.endpoint.strip_prefix(ctx.config.data.local_cas_scheme.as_str())?;
35 Some(PathBuf::from(path))
36 }
37
38 pub fn is_memory(&self) -> bool {
40 self.endpoint == "memory://"
41 }
42
43 pub fn for_local_path(ctx: &XetContext, base_dir: impl AsRef<Path>) -> Self {
45 let path = base_dir.as_ref().to_path_buf();
46 let endpoint = format!("{}{}", ctx.config.data.local_cas_scheme, path.display());
47 Self {
48 endpoint,
49 auth: None,
50 custom_headers: None,
51 repo_paths: vec!["".into()],
52 session_id: None,
53 }
54 }
55
56 pub fn for_memory() -> Self {
58 Self {
59 endpoint: "memory://".into(),
60 auth: None,
61 custom_headers: None,
62 repo_paths: vec!["".into()],
63 session_id: None,
64 }
65 }
66}
67
68#[derive(Debug, Clone)]
71pub struct TranslatorConfig {
72 pub ctx: XetContext,
73 pub session: SessionContext,
74
75 pub shard_cache_directory: PathBuf,
77
78 pub shard_session_directory: PathBuf,
80
81 pub force_disable_progress_aggregation: bool,
84}
85
86impl TranslatorConfig {
87 fn create_base_xet_dir(base_dir: impl AsRef<Path>) -> Result<PathBuf> {
88 let base_path = base_dir.as_ref().join("xet");
89 std::fs::create_dir_all(&base_path)?;
90 Ok(base_path)
91 }
92
93 pub fn new(ctx: &XetContext, session: SessionContext) -> Result<Self> {
99 #[cfg(target_family = "wasm")]
100 let (shard_cache_directory, shard_session_directory) = (PathBuf::new(), PathBuf::new());
101
102 #[cfg(not(target_family = "wasm"))]
103 let (shard_cache_directory, shard_session_directory) = {
104 let config = ctx.config.as_ref();
105
106 if let Some(local_path) = session.local_path(ctx) {
107 let base_path = local_path.join("xet");
108 std::fs::create_dir_all(&base_path)?;
109
110 (base_path.join(&config.shard.cache_subdir), base_path.join(&config.session.dir_name))
111 } else if session.is_memory() {
112 let cache_path = xet_cache_root().join("memory");
113 std::fs::create_dir_all(&cache_path)?;
114
115 (cache_path.join(&config.shard.cache_subdir), cache_path.join(&config.session.dir_name))
116 } else {
117 let cache_path = compute_cache_path(&session.endpoint);
118 std::fs::create_dir_all(&cache_path)?;
119
120 let staging_directory = cache_path.join(&config.data.staging_subdir);
121 std::fs::create_dir_all(&staging_directory)?;
122
123 (cache_path.join(&config.shard.cache_subdir), staging_directory.join(&config.session.dir_name))
124 }
125 };
126
127 info!(
128 endpoint = %session.endpoint,
129 session_id = ?session.session_id,
130 shard_cache = %shard_cache_directory.display(),
131 shard_session = %shard_session_directory.display(),
132 "TranslatorConfig initialized"
133 );
134
135 Ok(Self {
136 ctx: ctx.clone(),
137 session,
138 shard_cache_directory,
139 shard_session_directory,
140 force_disable_progress_aggregation: false,
141 })
142 }
143
144 pub fn local_config(ctx: &XetContext, base_dir: impl AsRef<Path>) -> Result<Self> {
146 Self::new(ctx, SessionContext::for_local_path(ctx, base_dir))
147 }
148
149 pub fn memory_config(ctx: &XetContext, base_dir: impl AsRef<Path>) -> Result<Self> {
152 let session = SessionContext::for_memory();
153 let config = ctx.config.as_ref();
154 let base_path = Self::create_base_xet_dir(base_dir)?;
155
156 Ok(Self {
157 ctx: ctx.clone(),
158 session,
159 shard_cache_directory: base_path.join(&config.shard.cache_subdir),
160 shard_session_directory: base_path.join(&config.session.dir_name),
161 force_disable_progress_aggregation: false,
162 })
163 }
164
165 pub fn test_server_config(ctx: &XetContext, endpoint: impl AsRef<str>, base_dir: impl AsRef<Path>) -> Result<Self> {
169 let session = SessionContext {
170 endpoint: endpoint.as_ref().to_string(),
171 auth: None,
172 custom_headers: None,
173 repo_paths: vec!["".into()],
174 session_id: None,
175 };
176 let config = ctx.config.as_ref();
177 let base_path = Self::create_base_xet_dir(base_dir)?;
178
179 Ok(Self {
180 ctx: ctx.clone(),
181 session,
182 shard_cache_directory: base_path.join(&config.shard.cache_subdir),
183 shard_session_directory: base_path.join(&config.session.dir_name),
184 force_disable_progress_aggregation: false,
185 })
186 }
187
188 pub fn disable_progress_aggregation(mut self) -> Self {
189 self.force_disable_progress_aggregation = true;
190 self
191 }
192}
193
194#[cfg(not(target_family = "wasm"))]
196fn compute_cache_path(endpoint: &str) -> PathBuf {
197 let cache_root = xet_cache_root();
198
199 let endpoint_prefix = endpoint
200 .chars()
201 .take(16)
202 .map(|c| if c.is_alphanumeric() { c } else { '_' })
203 .collect::<String>();
204
205 let endpoint_hash = xet_core_structures::merklehash::compute_data_hash(endpoint.as_bytes()).base64();
206 let endpoint_tag = format!("{endpoint_prefix}-{}", &endpoint_hash[..16]);
207
208 cache_root.join(endpoint_tag)
209}
210
211#[cfg(test)]
212mod tests {
213 use tempfile::tempdir;
214 use xet_runtime::core::XetContext;
215
216 use super::{SessionContext, TranslatorConfig};
217
218 #[test]
219 fn test_session_context_mode_detection() {
220 let ctx = XetContext::default().unwrap();
221 let temp_dir = tempdir().unwrap();
222 let local_session = SessionContext::for_local_path(&ctx, temp_dir.path());
223 assert!(local_session.is_local(&ctx));
224 assert!(!local_session.is_memory());
225 assert_eq!(local_session.local_path(&ctx).unwrap(), temp_dir.path().to_path_buf());
226
227 let memory_session = SessionContext::for_memory();
228 assert!(memory_session.is_memory());
229 assert!(!memory_session.is_local(&ctx));
230 assert!(memory_session.local_path(&ctx).is_none());
231
232 let remote_session = SessionContext {
233 endpoint: "http://localhost:8080".into(),
234 auth: None,
235 custom_headers: None,
236 repo_paths: Vec::new(),
237 session_id: None,
238 };
239 assert!(!remote_session.is_local(&ctx));
240 assert!(!remote_session.is_memory());
241 assert!(remote_session.local_path(&ctx).is_none());
242 }
243
244 #[test]
245 fn test_memory_and_server_configs_use_base_xet_layout() {
246 let ctx = XetContext::default().unwrap();
247 let temp_dir = tempdir().unwrap();
248
249 let memory_config = TranslatorConfig::memory_config(&ctx, temp_dir.path()).unwrap();
250 assert!(memory_config.shard_cache_directory.starts_with(temp_dir.path().join("xet")));
251 assert!(memory_config.shard_session_directory.starts_with(temp_dir.path().join("xet")));
252
253 let server_config =
254 TranslatorConfig::test_server_config(&ctx, "http://localhost:8080", temp_dir.path()).unwrap();
255 assert!(server_config.shard_cache_directory.starts_with(temp_dir.path().join("xet")));
256 assert!(server_config.shard_session_directory.starts_with(temp_dir.path().join("xet")));
257 }
258}