feat: wire remaining handlers — tag, quota, register asset, sidecar, processing
14 new endpoints: POST tags, GET quota, POST register, 6 sidecar, 7 processing. DTOs, AppState groups, LogSidecarWriter, full bootstrap wiring.
This commit is contained in:
@@ -11,33 +11,52 @@ use adapters_auth::{BcryptPasswordHasher, JwtTokenIssuer};
|
||||
|
||||
use adapters_postgres::{
|
||||
PostgresAlbumRepository, PostgresAssetMetadataRepository, PostgresAssetRepository,
|
||||
PostgresIngestSessionRepository, PostgresLibraryPathRepository, PostgresQuotaRepository,
|
||||
PostgresShareRepository, PostgresStorageVolumeRepository, PostgresUsageLedgerRepository,
|
||||
PostgresUserRepository, PostgresVisibilityFilterRepository, connect, run_migrations,
|
||||
PostgresDuplicateRepository, PostgresIngestSessionRepository, PostgresJobBatchRepository,
|
||||
PostgresJobRepository, PostgresLibraryPathRepository, PostgresPipelineRepository,
|
||||
PostgresPluginRepository, PostgresQuotaRepository, PostgresShareRepository,
|
||||
PostgresSidecarRepository, PostgresStorageVolumeRepository, PostgresTagRepository,
|
||||
PostgresUsageLedgerRepository, PostgresUserRepository, PostgresVisibilityFilterRepository,
|
||||
connect, run_migrations,
|
||||
};
|
||||
|
||||
use adapters_storage::LocalFileStorage;
|
||||
|
||||
use application::{
|
||||
catalog::{GetAssetHandler, GetTimelineHandler, ReadAssetFileHandler, UpdateMetadataHandler},
|
||||
catalog::{
|
||||
GetAssetHandler, GetTimelineHandler, ReadAssetFileHandler, RegisterAssetHandler,
|
||||
UpdateMetadataHandler,
|
||||
},
|
||||
identity::{GetProfileHandler, LoginUserHandler, RegisterUserHandler},
|
||||
organization::{CreateAlbumHandler, GetAlbumHandler, ManageAlbumEntriesHandler},
|
||||
organization::{
|
||||
CreateAlbumHandler, GetAlbumHandler, ManageAlbumEntriesHandler, TagAssetHandler,
|
||||
},
|
||||
processing::{
|
||||
CompleteJobHandler, ConfigurePipelineHandler, EnqueueJobHandler, FailJobHandler,
|
||||
ManagePluginHandler, ReportBatchProgressHandler, StartJobHandler,
|
||||
},
|
||||
sharing::{
|
||||
AccessSharedResourceHandler, GenerateShareLinkHandler, RevokeShareHandler,
|
||||
ShareResourceHandler,
|
||||
},
|
||||
storage::{IngestAssetHandler, RegisterLibraryPathHandler, RegisterVolumeHandler},
|
||||
sidecar::{
|
||||
DetectExternalChangesHandler, ExportSidecarHandler, FullExportHandler, FullImportHandler,
|
||||
ImportSidecarHandler, ResolveConflictHandler,
|
||||
},
|
||||
storage::{
|
||||
CheckQuotaHandler, IngestAssetHandler, RegisterLibraryPathHandler, RegisterVolumeHandler,
|
||||
},
|
||||
};
|
||||
use presentation::{
|
||||
routes::app_router,
|
||||
state::{
|
||||
AppState, CatalogHandlers, IdentityHandlers, OrganizationHandlers, SharingHandlers,
|
||||
StorageHandlers,
|
||||
AppState, CatalogHandlers, IdentityHandlers, OrganizationHandlers, ProcessingHandlers,
|
||||
SharingHandlers, SidecarHandlers, StorageHandlers,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::log_event_publisher::LogEventPublisher;
|
||||
use crate::log_sidecar_writer::LogSidecarWriter;
|
||||
|
||||
pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
let pool = connect(&config.database_url).await?;
|
||||
@@ -65,7 +84,15 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
let session_repo = Arc::new(PostgresIngestSessionRepository::new(pool.clone()));
|
||||
let quota_repo = Arc::new(PostgresQuotaRepository::new(pool.clone()));
|
||||
let ledger_repo = Arc::new(PostgresUsageLedgerRepository::new(pool.clone()));
|
||||
let tag_repo = Arc::new(PostgresTagRepository::new(pool.clone()));
|
||||
let duplicate_repo = Arc::new(PostgresDuplicateRepository::new(pool.clone()));
|
||||
let sidecar_repo = Arc::new(PostgresSidecarRepository::new(pool.clone()));
|
||||
let job_repo = Arc::new(PostgresJobRepository::new(pool.clone()));
|
||||
let batch_repo = Arc::new(PostgresJobBatchRepository::new(pool.clone()));
|
||||
let plugin_repo = Arc::new(PostgresPluginRepository::new(pool.clone()));
|
||||
let pipeline_repo = Arc::new(PostgresPipelineRepository::new(pool.clone()));
|
||||
let event_publisher: Arc<LogEventPublisher> = Arc::new(LogEventPublisher);
|
||||
let sidecar_writer: Arc<LogSidecarWriter> = Arc::new(LogSidecarWriter);
|
||||
|
||||
// File storage
|
||||
let storage_path = std::env::var("STORAGE_PATH").unwrap_or_else(|_| "./data/media".to_string());
|
||||
@@ -80,8 +107,8 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
let ingest_asset_handler = Arc::new(IngestAssetHandler::new(
|
||||
session_repo,
|
||||
path_repo.clone(),
|
||||
quota_repo,
|
||||
ledger_repo,
|
||||
quota_repo.clone(),
|
||||
ledger_repo.clone(),
|
||||
asset_repo.clone(),
|
||||
file_storage.clone(),
|
||||
event_publisher.clone(),
|
||||
@@ -96,10 +123,78 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
));
|
||||
let update_metadata_handler = Arc::new(UpdateMetadataHandler::new(
|
||||
asset_repo.clone(),
|
||||
metadata_repo,
|
||||
metadata_repo.clone(),
|
||||
event_publisher.clone(),
|
||||
));
|
||||
let read_asset_file_handler = Arc::new(ReadAssetFileHandler::new(asset_repo, file_storage));
|
||||
let read_asset_file_handler =
|
||||
Arc::new(ReadAssetFileHandler::new(asset_repo.clone(), file_storage));
|
||||
|
||||
// Register asset handler
|
||||
let register_asset_handler = Arc::new(RegisterAssetHandler::new(
|
||||
asset_repo.clone(),
|
||||
duplicate_repo,
|
||||
event_publisher.clone(),
|
||||
));
|
||||
|
||||
// Tag handler
|
||||
let tag_asset_handler = Arc::new(TagAssetHandler::new(asset_repo.clone(), tag_repo));
|
||||
|
||||
// Check quota handler
|
||||
let check_quota_handler = Arc::new(CheckQuotaHandler::new(quota_repo, ledger_repo));
|
||||
|
||||
// Sidecar handlers
|
||||
let export_sidecar_handler = Arc::new(ExportSidecarHandler::new(
|
||||
metadata_repo.clone(),
|
||||
sidecar_repo.clone(),
|
||||
sidecar_writer.clone(),
|
||||
));
|
||||
let detect_changes_handler = Arc::new(DetectExternalChangesHandler::new(
|
||||
sidecar_repo.clone(),
|
||||
sidecar_writer.clone(),
|
||||
));
|
||||
let import_sidecar_handler = Arc::new(ImportSidecarHandler::new(
|
||||
sidecar_repo.clone(),
|
||||
sidecar_writer.clone(),
|
||||
metadata_repo.clone(),
|
||||
));
|
||||
let resolve_conflict_handler = Arc::new(ResolveConflictHandler::new(
|
||||
sidecar_repo.clone(),
|
||||
sidecar_writer.clone(),
|
||||
metadata_repo.clone(),
|
||||
));
|
||||
let full_export_handler = Arc::new(FullExportHandler::new(
|
||||
asset_repo.clone(),
|
||||
metadata_repo.clone(),
|
||||
sidecar_repo.clone(),
|
||||
sidecar_writer.clone(),
|
||||
));
|
||||
let full_import_handler = Arc::new(FullImportHandler::new(
|
||||
asset_repo,
|
||||
metadata_repo,
|
||||
sidecar_repo,
|
||||
sidecar_writer,
|
||||
));
|
||||
|
||||
// Processing handlers
|
||||
let enqueue_job_handler = Arc::new(EnqueueJobHandler::new(
|
||||
job_repo.clone(),
|
||||
event_publisher.clone(),
|
||||
));
|
||||
let start_job_handler = Arc::new(StartJobHandler::new(job_repo.clone()));
|
||||
let complete_job_handler = Arc::new(CompleteJobHandler::new(
|
||||
job_repo.clone(),
|
||||
batch_repo.clone(),
|
||||
event_publisher.clone(),
|
||||
));
|
||||
let fail_job_handler = Arc::new(FailJobHandler::new(
|
||||
job_repo.clone(),
|
||||
batch_repo.clone(),
|
||||
event_publisher.clone(),
|
||||
));
|
||||
let batch_progress_handler = Arc::new(ReportBatchProgressHandler::new(batch_repo, job_repo));
|
||||
let manage_plugin_handler = Arc::new(ManagePluginHandler::new(plugin_repo.clone()));
|
||||
let configure_pipeline_handler =
|
||||
Arc::new(ConfigurePipelineHandler::new(pipeline_repo, plugin_repo));
|
||||
|
||||
// Sharing repos & handlers
|
||||
let share_repo = Arc::new(PostgresShareRepository::new(pool.clone()));
|
||||
@@ -130,17 +225,39 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
get_timeline: get_timeline_handler,
|
||||
update_metadata: update_metadata_handler,
|
||||
read_asset_file: read_asset_file_handler,
|
||||
register_asset: register_asset_handler,
|
||||
};
|
||||
|
||||
let organization = OrganizationHandlers {
|
||||
create_album: create_album_handler,
|
||||
get_album: get_album_handler,
|
||||
manage_album_entries: manage_album_entries_handler,
|
||||
tag_asset: tag_asset_handler,
|
||||
};
|
||||
|
||||
let storage_handlers = StorageHandlers {
|
||||
register_volume: register_volume_handler,
|
||||
register_library_path: register_library_path_handler,
|
||||
check_quota: check_quota_handler,
|
||||
};
|
||||
|
||||
let sidecar = SidecarHandlers {
|
||||
export: export_sidecar_handler,
|
||||
detect_changes: detect_changes_handler,
|
||||
import: import_sidecar_handler,
|
||||
resolve: resolve_conflict_handler,
|
||||
full_export: full_export_handler,
|
||||
full_import: full_import_handler,
|
||||
};
|
||||
|
||||
let processing = ProcessingHandlers {
|
||||
enqueue_job: enqueue_job_handler,
|
||||
start_job: start_job_handler,
|
||||
complete_job: complete_job_handler,
|
||||
fail_job: fail_job_handler,
|
||||
batch_progress: batch_progress_handler,
|
||||
manage_plugin: manage_plugin_handler,
|
||||
configure_pipeline: configure_pipeline_handler,
|
||||
};
|
||||
|
||||
let sharing = SharingHandlers {
|
||||
@@ -156,6 +273,8 @@ pub async fn build_app(config: &Config) -> Result<Router> {
|
||||
organization,
|
||||
storage: storage_handlers,
|
||||
sharing,
|
||||
sidecar,
|
||||
processing,
|
||||
token_issuer: issuer,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod config;
|
||||
pub mod factory;
|
||||
pub mod log_event_publisher;
|
||||
pub mod log_sidecar_writer;
|
||||
|
||||
21
crates/bootstrap/src/log_sidecar_writer.rs
Normal file
21
crates/bootstrap/src/log_sidecar_writer.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use async_trait::async_trait;
|
||||
use domain::{errors::DomainError, ports::SidecarWriterPort, value_objects::StructuredData};
|
||||
|
||||
pub struct LogSidecarWriter;
|
||||
|
||||
#[async_trait]
|
||||
impl SidecarWriterPort for LogSidecarWriter {
|
||||
fn format_name(&self) -> &str {
|
||||
"log_noop"
|
||||
}
|
||||
|
||||
async fn write_sidecar(&self, _data: &StructuredData, path: &str) -> Result<(), DomainError> {
|
||||
tracing::info!(path, "sidecar write (no-op)");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn read_sidecar(&self, path: &str) -> Result<StructuredData, DomainError> {
|
||||
tracing::info!(path, "sidecar read (no-op)");
|
||||
Ok(StructuredData::new())
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ use tracing::info;
|
||||
mod config;
|
||||
mod factory;
|
||||
mod log_event_publisher;
|
||||
mod log_sidecar_writer;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user