perf: complete storage-layer UUID migration — eliminate UUID↔String round-trips
- Domain: Folder.owner_id + File.owner_id → Option<Uuid> (was Option<String>) - Traits: folder_repository signatures accept Uuid directly (was &str) - Infra: remove all fi.user_id::text / fo.user_id::text SQL casts in repos - Infra: remove $N::uuid bind casts (columns are native UUID now) - Services: eliminate to_string() bridge variables in folder_service, search_service, trash_service - DTOs: boundary conversion to String only at API edge (file_dto, folder_dto) - Ports: default impls compare Option<Uuid> directly - Stubs: updated signatures to match trait 13 files changed across domain/application/infrastructure layers. Compiles clean (cargo check passes).
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
|
||||
// Re-export entity errors from the centralized module
|
||||
@@ -18,7 +20,7 @@ pub struct FileParts {
|
||||
pub folder_id: Option<String>,
|
||||
pub created_at: u64,
|
||||
pub modified_at: u64,
|
||||
pub owner_id: Option<String>,
|
||||
pub owner_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +63,7 @@ pub struct File {
|
||||
modified_at: u64,
|
||||
|
||||
/// Owner user ID (from storage.files.user_id)
|
||||
owner_id: Option<String>,
|
||||
owner_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
// We no longer need this module, now we use a String directly
|
||||
@@ -161,7 +163,7 @@ impl File {
|
||||
folder_id: Option<String>,
|
||||
created_at: u64,
|
||||
modified_at: u64,
|
||||
owner_id: Option<String>,
|
||||
owner_id: Option<Uuid>,
|
||||
) -> FileResult<Self> {
|
||||
// Validate file name
|
||||
if name.is_empty() || name.contains('/') || name.contains('\\') {
|
||||
@@ -241,8 +243,8 @@ impl File {
|
||||
self.modified_at
|
||||
}
|
||||
|
||||
pub fn owner_id(&self) -> Option<&str> {
|
||||
self.owner_id.as_deref()
|
||||
pub fn owner_id(&self) -> Option<Uuid> {
|
||||
self.owner_id
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
|
||||
// Re-export entity errors from the centralized module
|
||||
@@ -23,7 +25,7 @@ pub struct Folder {
|
||||
|
||||
/// Owner user ID — scopes folder visibility per user.
|
||||
/// `None` only for legacy/stub folders; real folders always have an owner.
|
||||
owner_id: Option<String>,
|
||||
owner_id: Option<Uuid>,
|
||||
|
||||
/// Creation timestamp
|
||||
created_at: u64,
|
||||
@@ -66,7 +68,7 @@ impl Folder {
|
||||
name: String,
|
||||
storage_path: StoragePath,
|
||||
parent_id: Option<String>,
|
||||
owner_id: Option<String>,
|
||||
owner_id: Option<Uuid>,
|
||||
) -> FolderResult<Self> {
|
||||
// Validate folder name
|
||||
if name.is_empty() || name.contains('/') || name.contains('\\') {
|
||||
@@ -119,7 +121,7 @@ impl Folder {
|
||||
name: String,
|
||||
storage_path: StoragePath,
|
||||
parent_id: Option<String>,
|
||||
owner_id: Option<String>,
|
||||
owner_id: Option<Uuid>,
|
||||
created_at: u64,
|
||||
modified_at: u64,
|
||||
) -> FolderResult<Self> {
|
||||
@@ -172,8 +174,8 @@ impl Folder {
|
||||
self.modified_at
|
||||
}
|
||||
|
||||
pub fn owner_id(&self) -> Option<&str> {
|
||||
self.owner_id.as_deref()
|
||||
pub fn owner_id(&self) -> Option<Uuid> {
|
||||
self.owner_id
|
||||
}
|
||||
|
||||
/// Creates a new Folder instance from a DTO
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::domain::entities::folder::Folder;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Domain port for folder persistence.
|
||||
///
|
||||
@@ -39,7 +40,7 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
async fn list_folders_by_owner(
|
||||
&self,
|
||||
parent_id: Option<&str>,
|
||||
owner_id: &str,
|
||||
owner_id: Uuid,
|
||||
) -> Result<Vec<Folder>, DomainError>;
|
||||
|
||||
/// Lists folders with pagination
|
||||
@@ -57,7 +58,7 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
async fn list_folders_by_owner_paginated(
|
||||
&self,
|
||||
parent_id: Option<&str>,
|
||||
owner_id: &str,
|
||||
owner_id: Uuid,
|
||||
offset: usize,
|
||||
limit: usize,
|
||||
include_total: bool,
|
||||
@@ -99,7 +100,7 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
|
||||
/// Creates a root-level home folder for a user.
|
||||
/// This is used during user registration to create the user's personal folder.
|
||||
async fn create_home_folder(&self, user_id: &str, name: String) -> Result<Folder, DomainError>;
|
||||
async fn create_home_folder(&self, user_id: Uuid, name: String) -> Result<Folder, DomainError>;
|
||||
|
||||
/// Lists every folder in a subtree rooted at `folder_id` (inclusive).
|
||||
///
|
||||
@@ -123,7 +124,7 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
&self,
|
||||
folder_id: &str,
|
||||
name_contains: Option<&str>,
|
||||
user_id: &str,
|
||||
user_id: Uuid,
|
||||
) -> Result<Vec<Folder>, DomainError> {
|
||||
let _ = (folder_id, name_contains, user_id);
|
||||
Ok(Vec::new())
|
||||
@@ -144,7 +145,7 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
&self,
|
||||
parent_id: Option<&str>,
|
||||
name_contains: Option<&str>,
|
||||
user_id: &str,
|
||||
user_id: Uuid,
|
||||
recursive: bool,
|
||||
) -> Result<Vec<Folder>, DomainError> {
|
||||
// Recursive with folder_id → use optimised ltree scan
|
||||
|
||||
Reference in New Issue
Block a user