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:
2026-05-31 11:04:22 +02:00
parent 19be8c2adf
commit a6b86c23d8
14 changed files with 865 additions and 30 deletions

View File

@@ -4,9 +4,10 @@ version = "0.1.0"
edition = "2024"
[dependencies]
domain = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
uuid = { workspace = true }
chrono = { workspace = true }
utoipa = { workspace = true }
domain = { workspace = true }
application = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
uuid = { workspace = true }
chrono = { workspace = true }
utoipa = { workspace = true }

View File

@@ -58,3 +58,79 @@ pub struct GenerateShareLinkRequest {
pub expires_in_hours: Option<u64>,
pub max_uses: Option<u32>,
}
// --- Organization ---
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct TagAssetRequest {
pub tag_name: String,
}
// --- Storage ---
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct CheckQuotaParams {
pub usage_type: Option<String>,
pub amount: Option<u64>,
}
// --- Catalog ---
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct RegisterAssetRequest {
pub volume_id: uuid::Uuid,
pub relative_path: String,
pub checksum: String,
pub asset_type: String,
pub mime_type: String,
pub file_size: u64,
}
// --- Sidecar ---
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct ResolveConflictRequest {
pub policy: String,
}
// --- Processing ---
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct EnqueueJobRequest {
pub job_type: String,
pub priority: Option<u32>,
pub payload: Option<std::collections::HashMap<String, serde_json::Value>>,
pub target_asset_id: Option<uuid::Uuid>,
pub batch_id: Option<uuid::Uuid>,
}
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct CompleteJobRequest {
pub result: std::collections::HashMap<String, serde_json::Value>,
}
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct FailJobRequest {
pub error: String,
}
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct ManagePluginRequest {
pub plugin_id: Option<uuid::Uuid>,
pub action: String,
pub name: Option<String>,
pub plugin_type: Option<String>,
pub config: Option<std::collections::HashMap<String, serde_json::Value>>,
}
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct ConfigurePipelineRequest {
pub trigger_event: String,
pub steps: Vec<PipelineStepRequest>,
}
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct PipelineStepRequest {
pub plugin_id: uuid::Uuid,
pub config: std::collections::HashMap<String, serde_json::Value>,
}

View File

@@ -196,3 +196,157 @@ impl SharedResourceResponse {
}
}
}
// --- Tag ---
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct TagResponse {
pub tag_id: Uuid,
pub name: String,
pub tag_source: String,
}
impl TagResponse {
pub fn from_domain(tag: &domain::entities::Tag) -> Self {
Self {
tag_id: *tag.tag_id.as_uuid(),
name: tag.name.clone(),
tag_source: format!("{:?}", tag.tag_source),
}
}
}
// --- Quota ---
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct QuotaCheckResponse {
pub allowed: bool,
pub current_usage: u64,
pub limit: u64,
pub is_unlimited: bool,
}
impl QuotaCheckResponse {
pub fn from_domain(result: &domain::storage::services::QuotaCheckResult) -> Self {
Self {
allowed: result.allowed,
current_usage: result.current_usage,
limit: result.limit,
is_unlimited: result.is_unlimited,
}
}
}
// --- Sidecar ---
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct SidecarExportResponse {
pub asset_id: Uuid,
pub status: String,
pub path: String,
}
impl SidecarExportResponse {
pub fn from_domain(record: &domain::entities::SidecarRecord) -> Self {
Self {
asset_id: *record.asset_id.as_uuid(),
status: format!("{:?}", record.sync_status),
path: record.sidecar_storage_path.clone(),
}
}
}
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct DetectChangesResponse {
pub changed_count: u32,
}
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct SidecarImportResponse {
pub asset_id: Uuid,
pub status: String,
}
// --- Processing ---
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct JobResponse {
pub job_id: Uuid,
pub job_type: String,
pub status: String,
pub priority: u32,
pub created_at: DateTime<Utc>,
}
impl JobResponse {
pub fn from_domain(job: &domain::entities::Job) -> Self {
Self {
job_id: *job.job_id.as_uuid(),
job_type: format!("{:?}", job.job_type),
status: format!("{:?}", job.status),
priority: job.priority,
created_at: *job.created_at.as_datetime(),
}
}
}
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct BatchProgressResponse {
pub batch_id: Uuid,
pub batch_type: String,
pub total: u32,
pub completed: u32,
pub failed: u32,
pub status: String,
pub jobs: Vec<JobResponse>,
}
impl BatchProgressResponse {
pub fn from_domain(progress: &application::processing::BatchProgress) -> Self {
Self {
batch_id: *progress.batch.batch_id.as_uuid(),
batch_type: progress.batch.batch_type.clone(),
total: progress.batch.total_jobs,
completed: progress.batch.completed_count,
failed: progress.batch.failed_count,
status: format!("{:?}", progress.batch.status),
jobs: progress.jobs.iter().map(JobResponse::from_domain).collect(),
}
}
}
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct PluginResponse {
pub plugin_id: Uuid,
pub name: String,
pub plugin_type: String,
pub is_enabled: bool,
}
impl PluginResponse {
pub fn from_domain(plugin: &domain::entities::Plugin) -> Self {
Self {
plugin_id: *plugin.plugin_id.as_uuid(),
name: plugin.name.clone(),
plugin_type: format!("{:?}", plugin.plugin_type),
is_enabled: plugin.is_enabled,
}
}
}
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct PipelineResponse {
pub pipeline_id: Uuid,
pub trigger_event: String,
pub steps_count: usize,
}
impl PipelineResponse {
pub fn from_domain(pipeline: &domain::entities::ProcessingPipeline) -> Self {
Self {
pipeline_id: *pipeline.pipeline_id.as_uuid(),
trigger_event: pipeline.trigger_event.clone(),
steps_count: pipeline.steps.len(),
}
}
}