From 52c3862db9b448f0f6a6eb4c334fcf95d25cb9c1 Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Sun, 12 Oct 2025 19:57:54 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Wave=20149=20Phase=203-4:=20Serv?= =?UTF-8?q?ice=20Panic=20Fix=20+=20JWT=20Debug=20Logging=20(Agent=20413)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Issue**: Backtesting service crashing with "transport error" **Root Cause #3**: blocking_read() called in async context causing panic ## Fixes Applied ### Agent 413: Async/Blocking Conflict Resolution - **File**: services/backtesting_service/src/service.rs - **Problem**: `blocking_read()` at line 237 panicked within Tokio runtime - **Error**: "Cannot block the current thread from within a runtime" - **Why Hard to Debug**: Panic manifested as gRPC transport error, not panic message - **Fix**: - Line 215: Made validate_backtest_request() async - Line 237: Changed `blocking_read()` → `read().await` - Line 406: Added `.await` to function call - **Impact**: Service stability restored, no more transport errors ### Debug Enhancement - **File**: services/api_gateway/src/auth/interceptor.rs:362 - **Added**: Full token logging for JWT debugging - **Purpose**: Debugging aid for Wave 149 investigation ## Technical Discovery **Key Insight**: Async/blocking conflicts cause service crashes that appear as transport errors at the client level. Always check service logs for panic backtraces when debugging transport failures. ## Test Results - Before: 29/49 (59.2%) - After Phase 3-4: 29/49 (59.2%) - Service Status: Stable (no more panics) ## Files Modified - services/backtesting_service/src/service.rs (+3 lines async conversion) - services/api_gateway/src/auth/interceptor.rs (+1 line debug logging) Co-authored-by: Wave 149 Agent 413 (Service Panic Fix) --- services/api_gateway/src/auth/interceptor.rs | 1 + services/backtesting_service/src/service.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/services/api_gateway/src/auth/interceptor.rs b/services/api_gateway/src/auth/interceptor.rs index 14aa42784..d4c8ccdc8 100644 --- a/services/api_gateway/src/auth/interceptor.rs +++ b/services/api_gateway/src/auth/interceptor.rs @@ -359,6 +359,7 @@ impl JwtService { let token_data = decode::(token, &self.decoding_key, &self.validation) .map_err(|e| { error!("JWT decode failed in interceptor: {:?}", e); + error!("FULL TOKEN FOR DEBUGGING: {}", token); error!( "Token (first 50 chars): {}...", &token[..50.min(token.len())] diff --git a/services/backtesting_service/src/service.rs b/services/backtesting_service/src/service.rs index 1a2f5d924..403d86633 100644 --- a/services/backtesting_service/src/service.rs +++ b/services/backtesting_service/src/service.rs @@ -212,7 +212,7 @@ impl BacktestingServiceImpl { } /// Validate backtest request parameters - fn validate_backtest_request(&self, request: &StartBacktestRequest) -> Result<(), Status> { + async fn validate_backtest_request(&self, request: &StartBacktestRequest) -> Result<(), Status> { if request.strategy_name.is_empty() { return Err(Status::invalid_argument("Strategy name cannot be empty")); } @@ -234,7 +234,7 @@ impl BacktestingServiceImpl { } // Check if we have capacity for new backtests - let active_count = self.active_backtests.blocking_read().len(); + let active_count = self.active_backtests.read().await.len(); let max_concurrent = 10; // Default limit if active_count >= max_concurrent { return Err(Status::resource_exhausted(format!( @@ -403,7 +403,7 @@ impl BacktestingService for BacktestingServiceImpl { ); // Validate request - self.validate_backtest_request(&req)?; + self.validate_backtest_request(&req).await?; // Generate backtest ID let backtest_id = Self::generate_backtest_id();