From 2fc5ae42a3de84ef9ffa12106789dbef56223e9a Mon Sep 17 00:00:00 2001 From: Florian THIERRY Date: Tue, 14 Jul 2026 20:50:26 +0200 Subject: [PATCH] WIP Implement the video adapter to merge FS files and DB files. --- backend/application/src/video/service.rs | 4 +- .../domain/src/video/model/library_item.rs | 4 +- backend/domain/src/video/port.rs | 6 +- backend/infrastructure/src/video/adapter.rs | 78 +++++++++---------- 4 files changed, 45 insertions(+), 47 deletions(-) diff --git a/backend/application/src/video/service.rs b/backend/application/src/video/service.rs index 8f5c200..10c8536 100644 --- a/backend/application/src/video/service.rs +++ b/backend/application/src/video/service.rs @@ -5,7 +5,7 @@ use std::io::{BufRead, BufReader}; use std::path::Path; use std::io::Read; use lumiere_domain::video::error::VideoError; -use lumiere_domain::video::model::library_item::{LibraryItem, ReadLibraryItem}; +use lumiere_domain::video::model::library_item::{LibraryItem, LibraryRawItem}; use lumiere_domain::video::port::VideoPort; #[derive(Clone)] @@ -21,7 +21,7 @@ impl VideoService { pub fn list_root_folder(self) -> Result, VideoError> { let read_items_with_possibly_no_id = self.video_port.list_root_folder()?; let items_with_id = read_items_with_possibly_no_id.iter() - .map(ReadLibraryItem::map_to_library_item) + .map(LibraryRawItem::map_to_library_item) .collect(); self.video_port.save_all(items_with_id); Ok(items_with_id) diff --git a/backend/domain/src/video/model/library_item.rs b/backend/domain/src/video/model/library_item.rs index b272393..d66dda7 100644 --- a/backend/domain/src/video/model/library_item.rs +++ b/backend/domain/src/video/model/library_item.rs @@ -12,12 +12,12 @@ pub struct LibraryItem { pub r#type: LibraryItemType, } -pub struct ReadLibraryItem { +pub struct LibraryRawItem { pub id: Option, pub name: String, pub r#type: LibraryItemType, } -impl ReadLibraryItem { +impl LibraryRawItem { pub fn map_to_library_item(&self) -> LibraryItem { LibraryItem { id: self.id.unwrap_or(Uuid::new_v4()), diff --git a/backend/domain/src/video/port.rs b/backend/domain/src/video/port.rs index 5af453c..9aab745 100644 --- a/backend/domain/src/video/port.rs +++ b/backend/domain/src/video/port.rs @@ -1,11 +1,11 @@ use uuid::Uuid; use crate::video::error::VideoError; -use crate::video::model::library_item::{LibraryItem, ReadLibraryItem}; +use crate::video::model::library_item::{LibraryItem, LibraryRawItem}; use crate::video::model::video::Video; pub trait VideoPort: Send + Sync { - fn list_root_folder(&self) -> Result, VideoError>; - fn list_folder(&self, folder_id: Uuid) -> Result, VideoError>; + fn list_root_folder(&self) -> Result, VideoError>; + fn list_folder(&self, folder_id: Uuid) -> Result, VideoError>; fn get_video_stream(&self, video_id: Uuid) -> Result; fn save(&self, library_item: &LibraryItem) -> Result<(), VideoError>; fn clone_box(&self) -> Box; diff --git a/backend/infrastructure/src/video/adapter.rs b/backend/infrastructure/src/video/adapter.rs index 8a33027..89b307f 100644 --- a/backend/infrastructure/src/video/adapter.rs +++ b/backend/infrastructure/src/video/adapter.rs @@ -1,8 +1,10 @@ use lumiere_domain::video::error::VideoError; -use lumiere_domain::video::model::library_item::{LibraryItem, ReadLibraryItem}; +use lumiere_domain::video::model::library_item::{LibraryItem, LibraryRawItem}; use lumiere_domain::video::model::video::Video; use lumiere_domain::video::port::VideoPort; use uuid::Uuid; +use std::env; +use std::fs; pub struct VideoAdapter { @@ -13,21 +15,18 @@ impl VideoAdapter { Self {} } - pub fn get_root_folder_read_library_items(&self) -> Result, VideoError> { - use std::env; - use std::fs; - + fn get_root_folder_read_library_items(&self) -> Result, VideoError> { // Get the root_folder path from environment variable - let root_folder = env::var("ROOT_FOLDER").map_err(|_| VideoError::ConfigurationError("ROOT_FOLDER environment variable not set"))?; + let root_folder = env::var("ROOT_FOLDER").map_err(|_| VideoError::FolderBrowsingTechnicalIssue)?; // List all elements inside this folder on the file system let entries = fs::read_dir(root_folder) - .map_err(|e| VideoError::FileSystemError(e.to_string()))?; + .map_err(|e| VideoError::FolderBrowsingTechnicalIssue)?; // Map all those elements into ReadLibraryItem objects - let mut items: Vec = Vec::new(); + let mut items: Vec = Vec::new(); for entry in entries { - let entry = entry.map_err(|e| VideoError::FileSystemError(e.to_string()))?; + let entry = entry.map_err(|e| VideoError::FolderBrowsingTechnicalIssue)?; let path = entry.path(); // Determine if it's a file or directory @@ -39,7 +38,7 @@ impl VideoAdapter { }; // Create ReadLibraryItem with None for ID (will be generated later) - let item = ReadLibraryItem { + let item = LibraryRawItem { id: None, name: entry.file_name().to_string_lossy().into_owned(), r#type: item_type, @@ -51,46 +50,45 @@ impl VideoAdapter { Ok(items) } - pub fn get_all_library_items_from_db(&self) -> Result, VideoError> { - todo!() + pub fn get_all_library_items_from_db(&self) -> Result, VideoError> { + Ok(vec!()) + } + + fn merge_item_lists(file_system_items: Vec, db_items: Vec) -> Vec { + let mut all_items: Vec = Vec::new(); + + db_items.iter().for_each(|item| all_items.push(*item)); + + file_system_items.iter() + .filter(|file_system_item| Self::does_item_belong_to_db_items(&db_items, file_system_item)) + .for_each(|file_system_item| all_items.push(*file_system_item)); + + all_items + } + + fn does_item_belong_to_db_items(database_items: &Vec, file_system_item: &LibraryRawItem) -> bool { + database_items.iter() + .any(|database_item| { + if let Some(item_id) = file_system_item.id { + database_item.id == Some(item_id) + } else { + false + } + }) } } impl VideoPort for VideoAdapter { - fn list_root_folder(&self) -> Result, VideoError> { - use std::thread; - - // In parallel: call both methods + fn list_root_folder(&self) -> Result, VideoError> { let file_system_items = self.get_root_folder_read_library_items()?; let db_items = self.get_all_library_items_from_db()?; - - // Merge the two lists. If an item from files has the same id as one from DB, use the DB version - let mut merged: Vec = Vec::new(); - - // First add all DB items (they have IDs) - for db_item in db_items { - merged.push(db_item); - } - - // Then add file system items only if they don't exist in DB - for fs_item in file_system_items { - let exists_in_db = merged.iter().any(|db_item| { - if let Some(fs_id) = fs_item.id { - db_item.id == Some(fs_id) - } else { - false - } - }); - - if !exists_in_db { - merged.push(fs_item); - } - } + + let merged = Self::merge_item_lists(file_system_items, db_items); Ok(merged) } - fn list_folder(&self, folder_id: Uuid) -> Result, VideoError> { + fn list_folder(&self, folder_id: Uuid) -> Result, VideoError> { todo!() }