feat: safe deletion, album/asset delete, trash, README update
- volume-aware deletion: read-only volumes remove DB only, writable volumes soft-delete to trash with configurable grace period - trash page with restore, worker purge sweep (TRASH_RETENTION_DAYS) - album delete endpoint + sidebar trash icon - asset delete from timeline selection toolbar - all listing queries exclude trashed assets (deleted_at IS NULL) - timeline ordered by EXIF capture date, date-summary endpoint - README rewritten with features, setup, full env var table
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use application::catalog::DeleteAssetHandler;
|
||||
use application::processing::{EnqueueJobHandler, ProcessNextJobHandler};
|
||||
use domain::ports::JobRepository;
|
||||
use domain::ports::{AssetRepository, JobRepository};
|
||||
|
||||
use crate::config::WorkerConfig;
|
||||
use crate::factories::{
|
||||
@@ -12,6 +13,9 @@ pub struct WorkerServices {
|
||||
pub process_next: Arc<ProcessNextJobHandler>,
|
||||
pub enqueue: Arc<EnqueueJobHandler>,
|
||||
pub job_repo: Arc<dyn JobRepository>,
|
||||
pub asset_repo: Arc<dyn AssetRepository>,
|
||||
pub delete_handler: Arc<DeleteAssetHandler>,
|
||||
pub trash_retention_days: u64,
|
||||
pub event_consumer:
|
||||
adapters_event_transport::EventConsumerAdapter<adapters_nats::NatsMessageSource>,
|
||||
}
|
||||
@@ -27,9 +31,8 @@ pub async fn build(config: &WorkerConfig) -> anyhow::Result<WorkerServices> {
|
||||
let event_store: Arc<dyn domain::ports::EventStore> =
|
||||
Arc::new(adapters_postgres::PostgresEventStore::new(pool.clone()));
|
||||
let repos = Repos::new(pool);
|
||||
let file_storage = Arc::new(adapters_storage::LocalFileStorage::new(
|
||||
&config.storage_path,
|
||||
));
|
||||
let file_storage: Arc<dyn domain::ports::FileStoragePort> =
|
||||
Arc::new(adapters_storage::LocalFileStorage::new(&config.storage_path));
|
||||
let sidecar_writer: Arc<dyn domain::ports::SidecarWriterPort> =
|
||||
Arc::new(adapters_sidecar::XmpSidecarWriter);
|
||||
|
||||
@@ -47,7 +50,7 @@ pub async fn build(config: &WorkerConfig) -> anyhow::Result<WorkerServices> {
|
||||
Arc::new(adapters_thumbnail::ImageThumbnailGenerator);
|
||||
let registry = Arc::new(build_plugin_registry(
|
||||
&repos,
|
||||
file_storage,
|
||||
file_storage.clone(),
|
||||
sidecar_writer,
|
||||
extractor,
|
||||
thumbnail_gen,
|
||||
@@ -60,7 +63,18 @@ pub async fn build(config: &WorkerConfig) -> anyhow::Result<WorkerServices> {
|
||||
event_pub.clone(),
|
||||
));
|
||||
let job_repo: Arc<dyn JobRepository> = repos.job.clone();
|
||||
let enqueue = Arc::new(build_enqueue_handler(&repos, event_pub));
|
||||
let asset_repo: Arc<dyn AssetRepository> = repos.asset.clone();
|
||||
let enqueue = Arc::new(build_enqueue_handler(&repos, event_pub.clone()));
|
||||
|
||||
let sidecar_repo: Arc<dyn domain::ports::SidecarRepository> = repos.sidecar.clone();
|
||||
let delete_handler = Arc::new(DeleteAssetHandler::new(
|
||||
repos.asset.clone(),
|
||||
repos.volume.clone(),
|
||||
repos.derivative.clone(),
|
||||
sidecar_repo,
|
||||
file_storage,
|
||||
event_pub,
|
||||
));
|
||||
|
||||
let consumer_source = adapters_nats::NatsMessageSource::new(nats_client);
|
||||
let event_consumer = adapters_event_transport::EventConsumerAdapter::new(consumer_source);
|
||||
@@ -69,6 +83,9 @@ pub async fn build(config: &WorkerConfig) -> anyhow::Result<WorkerServices> {
|
||||
process_next,
|
||||
enqueue,
|
||||
job_repo,
|
||||
asset_repo,
|
||||
delete_handler,
|
||||
trash_retention_days: config.trash_retention_days,
|
||||
event_consumer,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user