//! Risk Data Repository //! //! Production-ready risk management data layer for high-frequency trading systems. //! Provides repositories for `VaR` calculations, compliance logging, position limits, //! and risk data models with `PostgreSQL` and Redis integration. #![allow(missing_docs)] // Internal implementation details // Allow pedantic lints for repository implementation #![allow(clippy::missing_docs_in_private_items)] #![allow(clippy::clone_on_ref_ptr)] #![allow(clippy::str_to_string)] #![deny(clippy::unwrap_used, clippy::expect_used)] use std::sync::Arc; pub mod compliance; pub mod limits; pub mod models; pub mod var; // Import the repository traits and implementations use crate::compliance::{ComplianceRepository, ComplianceRepositoryImpl}; use crate::limits::{LimitsRepository, LimitsRepositoryImpl}; use crate::var::{VarRepository, VarRepositoryImpl}; /// Configuration for the risk data repository #[derive(Debug, Clone)] pub struct RiskDataConfig { /// `PostgreSQL` database URL pub database_url: String, /// Redis connection URL pub redis_url: String, /// Maximum database connections pub max_connections: u32, /// Connection timeout in seconds pub connection_timeout_secs: u64, } impl Default for RiskDataConfig { fn default() -> Self { Self { database_url: "postgresql://localhost/foxhunt".to_owned(), redis_url: "redis://localhost:6379".to_owned(), max_connections: 10, connection_timeout_secs: 30, } } } /// Main risk data repository facade providing access to all risk data operations #[derive(Debug, Clone)] pub struct RiskDataRepository { var_repo: Arc, compliance_repo: Arc, limits_repo: Arc, } impl RiskDataRepository { /// Create a new risk data repository with the given configuration /// /// # Errors /// Returns error if the operation fails pub async fn new(config: RiskDataConfig) -> Result { let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(config.max_connections) .acquire_timeout(std::time::Duration::from_secs( config.connection_timeout_secs, )) .connect(&config.database_url) .await?; let redis_client = redis::Client::open(config.redis_url)?; let redis_conn = redis::aio::ConnectionManager::new(redis_client).await?; let var_repo = Arc::new(VarRepositoryImpl::new(pool.clone(), redis_conn.clone())); let compliance_repo = Arc::new(ComplianceRepositoryImpl::new( pool.clone(), redis_conn.clone(), )); let limits_repo = Arc::new(LimitsRepositoryImpl::new(pool.clone(), redis_conn)); Ok(Self { var_repo, compliance_repo, limits_repo, }) } /// Get `VaR` repository pub fn var(&self) -> Arc { Arc::clone(&self.var_repo) } /// Get compliance repository pub fn compliance(&self) -> Arc { Arc::clone(&self.compliance_repo) } /// Get limits repository pub fn limits(&self) -> Arc { Arc::clone(&self.limits_repo) } } /// Common error types for risk data operations #[derive(Debug, thiserror::Error)] pub enum RiskDataError { /// Database connection or query error #[error("Database error: {0}")] Database(#[from] sqlx::Error), /// Redis cache operation error #[error("Redis error: {0}")] Redis(#[from] redis::RedisError), /// JSON serialization/deserialization error #[error("Serialization error: {0}")] Serialization(#[from] serde_json::Error), /// `VaR` calculation or modeling error #[error("VaR calculation error: {0}")] VarCalculation(String), /// Compliance rule validation error #[error("Compliance validation error: {0}")] ComplianceValidation(String), /// Position limits validation error #[error("Position limits validation error: {0}")] LimitsValidation(String), /// Configuration setup or validation error #[error("Configuration error: {0}")] Configuration(String), /// Invalid input data error #[error("Invalid data: {0}")] InvalidData(String), } /// Result type for risk data operations pub type RiskDataResult = Result; #[cfg(test)] #[allow(clippy::unwrap_used, clippy::expect_used)] mod tests { use super::*; #[test] fn test_risk_data_config_default() { let config = RiskDataConfig::default(); assert_eq!(config.database_url, "postgresql://localhost/foxhunt"); assert_eq!(config.redis_url, "redis://localhost:6379"); assert_eq!(config.max_connections, 10); assert_eq!(config.connection_timeout_secs, 30); } #[test] fn test_risk_data_error_display() { let error = RiskDataError::VarCalculation("Test error".to_string()); assert_eq!(error.to_string(), "VaR calculation error: Test error"); } }