1use std::path::PathBuf;
4use std::sync::Arc;
5use std::time::Duration;
6
7use dashmap::DashMap;
8
9#[derive(Clone)]
11pub struct CacheEntry {
12 pub path: PathBuf,
14}
15
16pub type FileCache = Arc<DashMap<String, CacheEntry>>;
18
19#[derive(Clone)]
21pub struct AppState {
22 pub files_dir: PathBuf,
23 pub backend_url: String,
24 pub api_key: String,
25 pub allowed_origins: Vec<String>,
26 pub http: reqwest::Client,
27 pub files_cache: FileCache,
28 pub min_free_space_bytes: u64,
29}
30
31impl AppState {
32 pub fn new(files_dir: PathBuf, backend_url: String, api_key: String, allowed_origins: Vec<String>, min_free_space_bytes: u64) -> Self {
33 Self {
34 files_dir,
35 backend_url,
36 api_key,
37 allowed_origins,
38 min_free_space_bytes,
39 http: reqwest::Client::builder()
40 .timeout(Duration::from_secs(30))
41 .connect_timeout(Duration::from_secs(5))
42 .pool_idle_timeout(Duration::from_secs(30))
43 .build()
44 .expect("Failed to build reqwest client"),
45 files_cache: Arc::new(DashMap::new()),
46 }
47 }
48
49 pub async fn init_cache(&self) {
50 let mut entries = tokio::fs::read_dir(&self.files_dir).await;
51 if let Ok(ref mut entries) = entries {
52 while let Ok(Some(entry)) = entries.next_entry().await {
53 let name = entry.file_name().to_string_lossy().to_string();
54 if let Some(dot) = name.rfind('.') {
55 let id = name[..dot].to_string();
56 self.files_cache.insert(id, CacheEntry { path: entry.path() });
57 }
58 }
59 }
60 tracing::info!("file cache initialized with {} entries", self.files_cache.len());
61 }
62}