//! Message processor implementation //! //! This module contains intentional violations for Aphoria dogfood testing. use crate::error::ConsumerError; use std::time::Duration; use tracing::{info, warn}; /// Message processor that handles incoming messages pub struct MessageProcessor { /// Processing mode mode: ProcessingMode, } /// Processing mode #[derive(Debug, Clone, Copy)] pub enum ProcessingMode { /// Synchronous (blocking) processing Sync, /// Asynchronous (non-blocking) processing Async, } impl MessageProcessor { /// Create a new message processor pub fn new(mode: ProcessingMode) -> Self { Self { mode } } // ==================== VIOLATION 8: Synchronous Processing ==================== /// Process a message (contains blocking operation in async context) /// /// @aphoria:claim[performance] Message processing MUST be async -- synchronous processing blocks event loop and degrades throughput pub async fn process_message(&self, data: &[u8]) -> Result<(), ConsumerError> { info!("Processing message of {} bytes", data.len()); match self.mode { ProcessingMode::Sync => { // ❌ VIOLATION 8: Blocking call in async function! // This blocks the tokio runtime thread, preventing other tasks from running std::thread::sleep(Duration::from_millis(100)); info!("Message processed (sync mode)"); Ok(()) } ProcessingMode::Async => { // ✅ CORRECT: Non-blocking async sleep tokio::time::sleep(Duration::from_millis(100)).await; info!("Message processed (async mode)"); Ok(()) } } } /// Batch process multiple messages pub async fn process_batch(&self, messages: &[&[u8]]) -> Result { let mut processed = 0; for msg in messages { if let Err(e) = self.process_message(msg).await { warn!("Failed to process message: {}", e); continue; } processed += 1; } info!("Batch processed: {}/{} messages", processed, messages.len()); Ok(processed) } /// Validate message format pub fn validate_message(&self, data: &[u8]) -> bool { // Simple validation: message must not be empty !data.is_empty() } } impl Default for MessageProcessor { fn default() -> Self { // ❌ VIOLATION 8: Default to sync mode Self::new(ProcessingMode::Sync) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_processor_creation() { let processor = MessageProcessor::new(ProcessingMode::Async); assert!(matches!(processor.mode, ProcessingMode::Async)); } #[test] fn test_default_processor() { let processor = MessageProcessor::default(); assert!(matches!(processor.mode, ProcessingMode::Sync)); } #[test] fn test_message_validation() { let processor = MessageProcessor::default(); assert!(processor.validate_message(b"test")); assert!(!processor.validate_message(b"")); } #[tokio::test] async fn test_async_processing() { let processor = MessageProcessor::new(ProcessingMode::Async); let result = processor.process_message(b"test data").await; assert!(result.is_ok()); } #[tokio::test] async fn test_batch_processing() { let processor = MessageProcessor::new(ProcessingMode::Async); let messages = vec![b"msg1".as_slice(), b"msg2".as_slice(), b"msg3".as_slice()]; let result = processor.process_batch(&messages).await; assert!(result.is_ok()); assert_eq!(result.unwrap(), 3); } }