domain: add Sidecar Sync entities and ports (SidecarRecord, SidecarConfig, SidecarWriterPort)
This commit is contained in:
@@ -45,3 +45,9 @@ pub use share_target::{ShareTarget, TargetType};
|
||||
pub use share_link::{LinkAccessLevel, ShareLink};
|
||||
pub use invite_code::InviteCode;
|
||||
pub use visibility_filter::VisibilityFilter;
|
||||
|
||||
mod sidecar_record;
|
||||
mod sidecar_config;
|
||||
|
||||
pub use sidecar_record::{SidecarRecord, SyncStatus};
|
||||
pub use sidecar_config::{ConflictPolicy, SidecarConfig, SyncMode};
|
||||
|
||||
30
crates/domain/src/entities/sidecar_config.rs
Normal file
30
crates/domain/src/entities/sidecar_config.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum SyncMode {
|
||||
Auto,
|
||||
Scheduled,
|
||||
Manual,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum ConflictPolicy {
|
||||
DbWins,
|
||||
FileWins,
|
||||
RequireUserDecision,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct SidecarConfig {
|
||||
pub export_base_path: String,
|
||||
pub sync_mode: SyncMode,
|
||||
pub conflict_resolution_policy: ConflictPolicy,
|
||||
}
|
||||
|
||||
impl Default for SidecarConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
export_base_path: "/kphotos/sidecars".to_string(),
|
||||
sync_mode: SyncMode::Auto,
|
||||
conflict_resolution_policy: ConflictPolicy::DbWins,
|
||||
}
|
||||
}
|
||||
}
|
||||
57
crates/domain/src/entities/sidecar_record.rs
Normal file
57
crates/domain/src/entities/sidecar_record.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use crate::value_objects::{Checksum, DateTimeStamp, SystemId};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum SyncStatus {
|
||||
InSync,
|
||||
PendingWrite,
|
||||
PendingRead,
|
||||
Conflict,
|
||||
Error,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct SidecarRecord {
|
||||
pub asset_id: SystemId,
|
||||
pub sync_status: SyncStatus,
|
||||
pub sidecar_storage_path: String,
|
||||
pub last_synced_at: Option<DateTimeStamp>,
|
||||
pub last_known_file_hash: Option<Checksum>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl SidecarRecord {
|
||||
pub fn new(asset_id: SystemId, path: impl Into<String>) -> Self {
|
||||
Self {
|
||||
asset_id,
|
||||
sync_status: SyncStatus::PendingWrite,
|
||||
sidecar_storage_path: path.into(),
|
||||
last_synced_at: None,
|
||||
last_known_file_hash: None,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_synced(&mut self, file_hash: Checksum) {
|
||||
self.sync_status = SyncStatus::InSync;
|
||||
self.last_synced_at = Some(DateTimeStamp::now());
|
||||
self.last_known_file_hash = Some(file_hash);
|
||||
self.error_message = None;
|
||||
}
|
||||
|
||||
pub fn mark_pending_write(&mut self) {
|
||||
self.sync_status = SyncStatus::PendingWrite;
|
||||
}
|
||||
|
||||
pub fn mark_pending_read(&mut self) {
|
||||
self.sync_status = SyncStatus::PendingRead;
|
||||
}
|
||||
|
||||
pub fn mark_conflict(&mut self) {
|
||||
self.sync_status = SyncStatus::Conflict;
|
||||
}
|
||||
|
||||
pub fn mark_error(&mut self, message: impl Into<String>) {
|
||||
self.sync_status = SyncStatus::Error;
|
||||
self.error_message = Some(message.into());
|
||||
}
|
||||
}
|
||||
@@ -45,3 +45,9 @@ mod visibility_filter_repo;
|
||||
|
||||
pub use share_repo::ShareRepository;
|
||||
pub use visibility_filter_repo::VisibilityFilterRepository;
|
||||
|
||||
mod sidecar_repo;
|
||||
mod sidecar_writer;
|
||||
|
||||
pub use sidecar_repo::SidecarRepository;
|
||||
pub use sidecar_writer::SidecarWriterPort;
|
||||
|
||||
10
crates/domain/src/ports/sidecar_repo.rs
Normal file
10
crates/domain/src/ports/sidecar_repo.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::{entities::{SidecarRecord, SyncStatus}, errors::DomainError, value_objects::SystemId};
|
||||
|
||||
#[async_trait]
|
||||
pub trait SidecarRepository: Send + Sync {
|
||||
async fn find_by_asset(&self, asset_id: &SystemId) -> Result<Option<SidecarRecord>, DomainError>;
|
||||
async fn find_by_status(&self, status: SyncStatus) -> Result<Vec<SidecarRecord>, DomainError>;
|
||||
async fn save(&self, record: &SidecarRecord) -> Result<(), DomainError>;
|
||||
async fn delete(&self, asset_id: &SystemId) -> Result<(), DomainError>;
|
||||
}
|
||||
9
crates/domain/src/ports/sidecar_writer.rs
Normal file
9
crates/domain/src/ports/sidecar_writer.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use async_trait::async_trait;
|
||||
use crate::{errors::DomainError, value_objects::StructuredData};
|
||||
|
||||
#[async_trait]
|
||||
pub trait SidecarWriterPort: Send + Sync {
|
||||
fn format_name(&self) -> &str;
|
||||
async fn write_sidecar(&self, data: &StructuredData, path: &str) -> Result<(), DomainError>;
|
||||
async fn read_sidecar(&self, path: &str) -> Result<StructuredData, DomainError>;
|
||||
}
|
||||
Reference in New Issue
Block a user