domain: add domain errors, events, and services module scaffold
This commit is contained in:
@@ -6,8 +6,12 @@ pub enum DomainError {
|
|||||||
Conflict(String),
|
Conflict(String),
|
||||||
#[error("Unauthorized: {0}")]
|
#[error("Unauthorized: {0}")]
|
||||||
Unauthorized(String),
|
Unauthorized(String),
|
||||||
|
#[error("Forbidden: {0}")]
|
||||||
|
Forbidden(String),
|
||||||
#[error("Validation error: {0}")]
|
#[error("Validation error: {0}")]
|
||||||
Validation(String),
|
Validation(String),
|
||||||
|
#[error("Quota exceeded: {0}")]
|
||||||
|
QuotaExceeded(String),
|
||||||
#[error("Internal error: {0}")]
|
#[error("Internal error: {0}")]
|
||||||
Internal(String),
|
Internal(String),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,49 @@
|
|||||||
use uuid::Uuid;
|
use crate::value_objects::{DateTimeStamp, SystemId};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum DomainEvent {
|
pub enum DomainEvent {
|
||||||
UserRegistered { user_id: Uuid },
|
AssetIngested {
|
||||||
UserLoggedIn { user_id: Uuid },
|
asset_id: SystemId,
|
||||||
|
owner_user_id: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
MetadataUpdated {
|
||||||
|
asset_id: SystemId,
|
||||||
|
updated_by: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
AssetDeleted {
|
||||||
|
asset_id: SystemId,
|
||||||
|
deleted_by: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
ShareCreated {
|
||||||
|
scope_id: SystemId,
|
||||||
|
shareable_id: SystemId,
|
||||||
|
created_by: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
ShareRevoked {
|
||||||
|
scope_id: SystemId,
|
||||||
|
revoked_by: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
SidecarSyncRequested {
|
||||||
|
asset_id: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
JobEnqueued {
|
||||||
|
job_id: SystemId,
|
||||||
|
job_type: String,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
JobCompleted {
|
||||||
|
job_id: SystemId,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
|
JobFailed {
|
||||||
|
job_id: SystemId,
|
||||||
|
error: String,
|
||||||
|
timestamp: DateTimeStamp,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ pub mod entities;
|
|||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod ports;
|
pub mod ports;
|
||||||
|
pub mod services;
|
||||||
pub mod value_objects;
|
pub mod value_objects;
|
||||||
|
|||||||
1
crates/domain/src/services/metadata_resolver.rs
Normal file
1
crates/domain/src/services/metadata_resolver.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// Metadata resolver — will be implemented in Task 9
|
||||||
3
crates/domain/src/services/mod.rs
Normal file
3
crates/domain/src/services/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod metadata_resolver;
|
||||||
|
pub mod permission_service;
|
||||||
|
pub mod quota_checker;
|
||||||
1
crates/domain/src/services/permission_service.rs
Normal file
1
crates/domain/src/services/permission_service.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// Permission service — will be implemented in Task 5
|
||||||
1
crates/domain/src/services/quota_checker.rs
Normal file
1
crates/domain/src/services/quota_checker.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// Quota checker — will be implemented in Task 7
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
mod events;
|
||||||
mod value_objects;
|
mod value_objects;
|
||||||
|
|||||||
14
crates/domain/tests/events.rs
Normal file
14
crates/domain/tests/events.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use domain::events::DomainEvent;
|
||||||
|
use domain::value_objects::{DateTimeStamp, SystemId};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn asset_ingested_serde_roundtrip() {
|
||||||
|
let event = DomainEvent::AssetIngested {
|
||||||
|
asset_id: SystemId::new(),
|
||||||
|
owner_user_id: SystemId::new(),
|
||||||
|
timestamp: DateTimeStamp::now(),
|
||||||
|
};
|
||||||
|
let json = serde_json::to_string(&event).unwrap();
|
||||||
|
let back: DomainEvent = serde_json::from_str(&json).unwrap();
|
||||||
|
assert!(matches!(back, DomainEvent::AssetIngested { .. }));
|
||||||
|
}
|
||||||
@@ -14,7 +14,9 @@ impl IntoResponse for AppError {
|
|||||||
DomainError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
|
DomainError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
|
||||||
DomainError::Conflict(msg) => (StatusCode::CONFLICT, msg.clone()),
|
DomainError::Conflict(msg) => (StatusCode::CONFLICT, msg.clone()),
|
||||||
DomainError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg.clone()),
|
DomainError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg.clone()),
|
||||||
|
DomainError::Forbidden(msg) => (StatusCode::FORBIDDEN, msg.clone()),
|
||||||
DomainError::Validation(msg) => (StatusCode::UNPROCESSABLE_ENTITY, msg.clone()),
|
DomainError::Validation(msg) => (StatusCode::UNPROCESSABLE_ENTITY, msg.clone()),
|
||||||
|
DomainError::QuotaExceeded(msg) => (StatusCode::PAYLOAD_TOO_LARGE, msg.clone()),
|
||||||
DomainError::Internal(msg) => {
|
DomainError::Internal(msg) => {
|
||||||
tracing::error!("Internal error: {msg}");
|
tracing::error!("Internal error: {msg}");
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
|
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
|
||||||
|
|||||||
Reference in New Issue
Block a user