fix: fix services accessig directly to localstorage
Prevent services accessing directly to localstorage and prefer using an astraction layer to expose full blob. The abstraction layer (dedup services) will cover backend storage election (local, s3, ...), encryption, etc This change permit audio_metadata_service, media_metadaa_service, face_indexing_service to handle blobs without worring of the backend. note: prefered way to handle blob is the streamed way. Some services may not have this possibility
This commit is contained in:
@@ -2252,6 +2252,19 @@ pub struct AppConfig {
|
||||
pub storage_path: PathBuf,
|
||||
/// Static files directory path
|
||||
pub static_path: PathBuf,
|
||||
/// Directory for tier-1 temporary data — pure scratch, safe to
|
||||
/// lose at reboot. Backend `stream_to_tempfile` writes here so
|
||||
/// extractors that require a `&Path` (id3, mp3_duration,
|
||||
/// ffprobe, nom-exif video) can operate on a local file
|
||||
/// without the service ever seeing a raw blob path.
|
||||
///
|
||||
/// Env: `OXICLOUD_TEMP_DIR`. Default: `std::env::temp_dir()`
|
||||
/// (respects `$TMPDIR`). On Linux this is typically `/tmp`,
|
||||
/// often mounted as tmpfs (RAM-backed); production
|
||||
/// deployments concerned about physical RAM under
|
||||
/// high concurrency should point this at a disk-backed
|
||||
/// directory (e.g. `/var/lib/oxicloud/tmp`).
|
||||
pub temp_dir: PathBuf,
|
||||
/// Server port
|
||||
pub server_port: u16,
|
||||
/// Server host
|
||||
@@ -2356,6 +2369,7 @@ impl Default for AppConfig {
|
||||
Self {
|
||||
storage_path: PathBuf::from("./storage"),
|
||||
static_path: PathBuf::from("./static"),
|
||||
temp_dir: env::temp_dir(),
|
||||
server_port: 8086,
|
||||
server_host: "127.0.0.1".to_string(),
|
||||
cache: CacheConfig::default(),
|
||||
@@ -2394,6 +2408,10 @@ impl AppConfig {
|
||||
config.static_path = PathBuf::from(static_path);
|
||||
}
|
||||
|
||||
if let Ok(temp_dir) = env::var("OXICLOUD_TEMP_DIR") {
|
||||
config.temp_dir = PathBuf::from(temp_dir);
|
||||
}
|
||||
|
||||
if let Ok(server_port) = env::var("OXICLOUD_SERVER_PORT")
|
||||
&& let Ok(port) = server_port.parse::<u16>()
|
||||
{
|
||||
|
||||
+14
-9
@@ -468,11 +468,11 @@ impl AppServiceFactory {
|
||||
);
|
||||
|
||||
// Audio metadata service — created here so it can be wired into file_lifecycle.
|
||||
let audio_metadata_service = self.create_audio_metadata_service(db_pool);
|
||||
let audio_metadata_service = self.create_audio_metadata_service(db_pool, &dedup_service);
|
||||
|
||||
// Image/video capture-metadata service — extracts EXIF/container capture
|
||||
// dates so the Photos timeline groups by real capture time, not upload time.
|
||||
let media_metadata_service = self.create_media_metadata_service(db_pool);
|
||||
let media_metadata_service = self.create_media_metadata_service(db_pool, &dedup_service);
|
||||
|
||||
// ThumbnailRefreshHook: handles FileLifecycleHook events (create/update/delete).
|
||||
// Implemented on ThumbnailRefreshHook (not ThumbnailService) to avoid circular Arc:
|
||||
@@ -544,7 +544,7 @@ impl AppServiceFactory {
|
||||
}
|
||||
fls = fls.with_hook(media_metadata_service.clone());
|
||||
if self.config.features.enable_faces {
|
||||
fls = fls.with_hook(self.create_face_indexing_service(db_pool));
|
||||
fls = fls.with_hook(self.create_face_indexing_service(db_pool, &dedup_service));
|
||||
}
|
||||
let file_lifecycle = Arc::new(fls);
|
||||
|
||||
@@ -950,15 +950,16 @@ impl AppServiceFactory {
|
||||
pub fn create_audio_metadata_service(
|
||||
&self,
|
||||
db_pool: &Arc<PgPool>,
|
||||
dedup: &Arc<crate::infrastructure::services::dedup_service::DedupService>,
|
||||
) -> Option<Arc<AudioMetadataService>> {
|
||||
if !self.config.features.enable_music {
|
||||
tracing::info!("Audio metadata service is disabled (music feature disabled)");
|
||||
return None;
|
||||
}
|
||||
let blob_root = self.storage_path.join(".blobs");
|
||||
Some(Arc::new(AudioMetadataService::new(
|
||||
db_pool.clone(),
|
||||
blob_root,
|
||||
dedup.clone(),
|
||||
self.config.temp_dir.clone(),
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -967,9 +968,13 @@ impl AppServiceFactory {
|
||||
pub fn create_media_metadata_service(
|
||||
&self,
|
||||
db_pool: &Arc<PgPool>,
|
||||
dedup: &Arc<crate::infrastructure::services::dedup_service::DedupService>,
|
||||
) -> Arc<MediaMetadataService> {
|
||||
let blob_root = self.storage_path.join(".blobs");
|
||||
Arc::new(MediaMetadataService::new(db_pool.clone(), blob_root))
|
||||
Arc::new(MediaMetadataService::new(
|
||||
db_pool.clone(),
|
||||
dedup.clone(),
|
||||
self.config.temp_dir.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Creates the trash service
|
||||
@@ -1137,13 +1142,13 @@ impl AppServiceFactory {
|
||||
pub fn create_face_indexing_service(
|
||||
&self,
|
||||
db_pool: &Arc<PgPool>,
|
||||
dedup: &Arc<crate::infrastructure::services::dedup_service::DedupService>,
|
||||
) -> Arc<crate::infrastructure::services::face_indexing_service::FaceIndexingService> {
|
||||
let blob_root = self.storage_path.join(".blobs");
|
||||
let analyzer = self.build_face_analyzer();
|
||||
Arc::new(
|
||||
crate::infrastructure::services::face_indexing_service::FaceIndexingService::new(
|
||||
db_pool.clone(),
|
||||
blob_root,
|
||||
dedup.clone(),
|
||||
analyzer,
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user