//! Common traits for Veza Rust services //! //! This module defines shared traits that can be implemented by different //! services to provide a consistent interface and enable easy testing. use async_trait::async_trait; use std::collections::HashMap; use uuid::Uuid; use crate::VezaResult; /// Authentication provider trait #[async_trait] pub trait AuthProvider: Send + Sync { /// Validate a JWT token async fn validate_token(&self, token: &str) -> VezaResult; /// Generate a new JWT token async fn generate_token(&self, claims: &AuthClaims) -> VezaResult; /// Refresh a token async fn refresh_token(&self, refresh_token: &str) -> VezaResult; /// Revoke a token async fn revoke_token(&self, token: &str) -> VezaResult<()>; /// Check if a user has permission for a resource async fn check_permission(&self, user_id: Uuid, resource: &str, action: &str) -> VezaResult; } /// Message store trait for chat functionality #[async_trait] pub trait MessageStore: Send + Sync { /// Store a message async fn store_message(&self, message: &Message) -> VezaResult<()>; /// Get messages for a conversation async fn get_messages(&self, conversation_id: Uuid, limit: u32, offset: u32) -> VezaResult>; /// Get a specific message async fn get_message(&self, message_id: Uuid) -> VezaResult>; /// Update a message async fn update_message(&self, message_id: Uuid, content: &str) -> VezaResult<()>; /// Delete a message async fn delete_message(&self, message_id: Uuid) -> VezaResult<()>; /// Mark messages as read async fn mark_as_read(&self, user_id: Uuid, conversation_id: Uuid, message_id: Uuid) -> VezaResult<()>; /// Get unread count for a user async fn get_unread_count(&self, user_id: Uuid) -> VezaResult; } /// Stream provider trait for audio streaming #[async_trait] pub trait StreamProvider: Send + Sync { /// Get stream URL for a track async fn get_stream_url(&self, track_id: Uuid, user_id: Uuid) -> VezaResult; /// Validate stream access async fn validate_access(&self, track_id: Uuid, user_id: Uuid) -> VezaResult; /// Get track metadata async fn get_track_metadata(&self, track_id: Uuid) -> VezaResult; /// Get audio chunk async fn get_audio_chunk(&self, track_id: Uuid, chunk_index: u32) -> VezaResult>; /// Get playlist async fn get_playlist(&self, playlist_id: Uuid, user_id: Uuid) -> VezaResult; /// Create playlist async fn create_playlist(&self, user_id: Uuid, name: &str, tracks: Vec) -> VezaResult; } /// Cache provider trait #[async_trait] pub trait CacheProvider: Send + Sync { /// Get a value from cache async fn get(&self, key: &str) -> VezaResult> where T: serde::de::DeserializeOwned; /// Set a value in cache async fn set(&self, key: &str, value: &T, ttl: Option) -> VezaResult<()> where T: serde::Serialize; /// Delete a value from cache async fn delete(&self, key: &str) -> VezaResult<()>; /// Check if a key exists async fn exists(&self, key: &str) -> VezaResult; /// Get multiple values async fn get_many(&self, keys: &[String]) -> VezaResult> where T: serde::de::DeserializeOwned; /// Set multiple values async fn set_many(&self, values: HashMap, ttl: Option) -> VezaResult<()> where T: serde::Serialize; /// Clear cache async fn clear(&self) -> VezaResult<()>; /// Get cache statistics async fn stats(&self) -> VezaResult; } /// Database provider trait #[async_trait] pub trait DatabaseProvider: Send + Sync { /// Execute a query async fn execute(&self, query: &str, params: &[serde_json::Value]) -> VezaResult; /// Query a single row async fn query_one(&self, query: &str, params: &[serde_json::Value]) -> VezaResult> where T: serde::de::DeserializeOwned; /// Query multiple rows async fn query_many(&self, query: &str, params: &[serde_json::Value]) -> VezaResult> where T: serde::de::DeserializeOwned; /// Begin a transaction /// Note: This returns a type-erased transaction provider /// Implementations should return their concrete transaction type async fn begin_transaction(&self) -> VezaResult<()>; /// Health check async fn health_check(&self) -> VezaResult<()>; } /// Transaction provider trait #[async_trait] pub trait TransactionProvider: Send + Sync { /// Execute a query in transaction async fn execute(&self, query: &str, params: &[serde_json::Value]) -> VezaResult; /// Query a single row in transaction async fn query_one(&self, query: &str, params: &[serde_json::Value]) -> VezaResult> where T: serde::de::DeserializeOwned; /// Query multiple rows in transaction async fn query_many(&self, query: &str, params: &[serde_json::Value]) -> VezaResult> where T: serde::de::DeserializeOwned; /// Commit transaction async fn commit(self: Box) -> VezaResult<()>; /// Rollback transaction async fn rollback(self: Box) -> VezaResult<()>; } /// Rate limiter trait #[async_trait] pub trait RateLimiter: Send + Sync { /// Check if a request is allowed async fn is_allowed(&self, key: &str, limit: u32, window: u64) -> VezaResult; /// Get remaining requests async fn get_remaining(&self, key: &str, limit: u32, window: u64) -> VezaResult; /// Reset rate limit for a key async fn reset(&self, key: &str) -> VezaResult<()>; /// Get rate limit info async fn get_info(&self, key: &str, limit: u32, window: u64) -> VezaResult; } /// Metrics provider trait #[async_trait] pub trait MetricsProvider: Send + Sync { /// Increment a counter async fn increment_counter(&self, name: &str, labels: &[(&str, &str)]) -> VezaResult<()>; /// Increment a counter by a value async fn increment_counter_by(&self, name: &str, value: f64, labels: &[(&str, &str)]) -> VezaResult<()>; /// Set a gauge value async fn set_gauge(&self, name: &str, value: f64, labels: &[(&str, &str)]) -> VezaResult<()>; /// Observe a histogram value async fn observe_histogram(&self, name: &str, value: f64, labels: &[(&str, &str)]) -> VezaResult<()>; /// Observe a summary value async fn observe_summary(&self, name: &str, value: f64, labels: &[(&str, &str)]) -> VezaResult<()>; /// Get metrics as string async fn get_metrics(&self) -> VezaResult; } /// Logger trait pub trait Logger: Send + Sync { /// Log a trace message fn trace(&self, message: &str, fields: &[(&str, String)]); /// Log a debug message fn debug(&self, message: &str, fields: &[(&str, String)]); /// Log an info message fn info(&self, message: &str, fields: &[(&str, String)]); /// Log a warning message fn warn(&self, message: &str, fields: &[(&str, String)]); /// Log an error message fn error(&self, message: &str, fields: &[(&str, String)]); /// Create a child logger with additional fields fn child(&self, fields: &[(&str, String)]) -> Box; } /// WebSocket handler trait #[async_trait] pub trait WebSocketHandler: Send + Sync { /// Handle a new connection async fn handle_connect(&self, user_id: Uuid, connection_id: Uuid) -> VezaResult<()>; /// Handle a message async fn handle_message(&self, user_id: Uuid, connection_id: Uuid, message: &str) -> VezaResult<()>; /// Handle a disconnection async fn handle_disconnect(&self, user_id: Uuid, connection_id: Uuid) -> VezaResult<()>; /// Broadcast a message to all users in a conversation async fn broadcast_to_conversation(&self, conversation_id: Uuid, message: &str, exclude_user: Option) -> VezaResult<()>; /// Send a message to a specific user async fn send_to_user(&self, user_id: Uuid, message: &str) -> VezaResult<()>; } /// File storage trait #[async_trait] pub trait FileStorage: Send + Sync { /// Store a file async fn store_file(&self, path: &str, content: &[u8]) -> VezaResult; /// Get a file async fn get_file(&self, path: &str) -> VezaResult>; /// Delete a file async fn delete_file(&self, path: &str) -> VezaResult<()>; /// Check if a file exists async fn file_exists(&self, path: &str) -> VezaResult; /// Get file metadata async fn get_file_metadata(&self, path: &str) -> VezaResult; /// List files in a directory async fn list_files(&self, path: &str) -> VezaResult>; } /// Notification service trait #[async_trait] pub trait NotificationService: Send + Sync { /// Send a push notification async fn send_push_notification(&self, user_id: Uuid, title: &str, body: &str, data: &HashMap) -> VezaResult<()>; /// Send an in-app notification async fn send_in_app_notification(&self, user_id: Uuid, message: &str, data: &HashMap) -> VezaResult<()>; /// Send an email async fn send_email(&self, to: &str, subject: &str, body: &str) -> VezaResult<()>; /// Send an SMS async fn send_sms(&self, to: &str, message: &str) -> VezaResult<()>; } /// Health check trait #[async_trait] pub trait HealthCheck: Send + Sync { /// Check if the service is healthy async fn is_healthy(&self) -> VezaResult; /// Get detailed health information async fn get_health_info(&self) -> VezaResult; /// Get service name fn service_name(&self) -> &str; /// Get service version fn service_version(&self) -> &str; } // Data types used by traits #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AuthClaims { pub user_id: Uuid, pub username: String, pub email: String, pub roles: Vec, pub exp: u64, pub iat: u64, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AuthResult { pub access_token: String, pub refresh_token: String, pub expires_in: u64, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Message { pub id: Uuid, pub conversation_id: Uuid, pub user_id: Uuid, pub content: String, pub message_type: String, pub created_at: chrono::DateTime, pub updated_at: chrono::DateTime, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct TrackMetadata { pub id: Uuid, pub title: String, pub artist: String, pub album: String, pub duration: u32, pub file_size: u64, pub format: String, pub bitrate: u32, pub sample_rate: u32, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Playlist { pub id: Uuid, pub name: String, pub user_id: Uuid, pub tracks: Vec, pub created_at: chrono::DateTime, pub updated_at: chrono::DateTime, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct CacheStats { pub hits: u64, pub misses: u64, pub keys: u64, pub memory_usage: u64, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct RateLimitInfo { pub limit: u32, pub remaining: u32, pub reset_time: u64, pub retry_after: Option, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct FileMetadata { pub path: String, pub size: u64, pub mime_type: String, pub created_at: chrono::DateTime, pub modified_at: chrono::DateTime, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct HealthInfo { pub status: String, pub version: String, pub uptime: u64, pub dependencies: HashMap, pub metrics: HashMap, }