feat: serve derivative files via GET /assets/{id}/derivatives/{profile}
- ReadDerivativeHandler queries DerivativeRepository + FileStoragePort - Profile URL param: thumbnail, thumbnail_large, web_optimized, video_sd - Immutable cache headers (derivatives don't change once generated) - Wired into bootstrap catalog service builder
This commit is contained in:
@@ -7,4 +7,7 @@ pub use commands::update_metadata::{UpdateMetadataCommand, UpdateMetadataHandler
|
||||
pub use queries::get_asset::{GetAssetHandler, GetAssetQuery};
|
||||
pub use queries::get_timeline::{GetTimelineHandler, GetTimelineQuery};
|
||||
pub use queries::read_asset_file::{AssetFileResult, ReadAssetFileHandler, ReadAssetFileQuery};
|
||||
pub use queries::read_derivative::{
|
||||
DerivativeFileResult, ReadDerivativeHandler, ReadDerivativeQuery,
|
||||
};
|
||||
pub use visibility::VisibilityFilteredAssetRepository;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod get_asset;
|
||||
pub mod get_timeline;
|
||||
pub mod read_asset_file;
|
||||
pub mod read_derivative;
|
||||
|
||||
68
crates/application/src/catalog/queries/read_derivative.rs
Normal file
68
crates/application/src/catalog/queries/read_derivative.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use bytes::Bytes;
|
||||
use domain::{
|
||||
entities::{DerivativeProfile, GenerationStatus},
|
||||
errors::DomainError,
|
||||
ports::{DerivativeRepository, FileStoragePort},
|
||||
value_objects::SystemId,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct ReadDerivativeQuery {
|
||||
pub asset_id: SystemId,
|
||||
pub profile: DerivativeProfile,
|
||||
}
|
||||
|
||||
pub struct DerivativeFileResult {
|
||||
pub data: Bytes,
|
||||
pub mime_type: String,
|
||||
}
|
||||
|
||||
pub struct ReadDerivativeHandler {
|
||||
derivative_repo: Arc<dyn DerivativeRepository>,
|
||||
file_storage: Arc<dyn FileStoragePort>,
|
||||
}
|
||||
|
||||
impl ReadDerivativeHandler {
|
||||
pub fn new(
|
||||
derivative_repo: Arc<dyn DerivativeRepository>,
|
||||
file_storage: Arc<dyn FileStoragePort>,
|
||||
) -> Self {
|
||||
Self {
|
||||
derivative_repo,
|
||||
file_storage,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn execute(
|
||||
&self,
|
||||
query: ReadDerivativeQuery,
|
||||
) -> Result<DerivativeFileResult, DomainError> {
|
||||
let derivative = self
|
||||
.derivative_repo
|
||||
.find_by_asset_and_profile(&query.asset_id, query.profile)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
DomainError::NotFound(format!(
|
||||
"Derivative {:?} not found for asset {}",
|
||||
query.profile, query.asset_id
|
||||
))
|
||||
})?;
|
||||
|
||||
if derivative.generation_status != GenerationStatus::Ready {
|
||||
return Err(DomainError::NotFound(format!(
|
||||
"Derivative {:?} not ready for asset {}",
|
||||
query.profile, query.asset_id
|
||||
)));
|
||||
}
|
||||
|
||||
let data = self
|
||||
.file_storage
|
||||
.read_file(&derivative.storage_path)
|
||||
.await?;
|
||||
|
||||
Ok(DerivativeFileResult {
|
||||
data,
|
||||
mime_type: derivative.mime_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user