# Training Service - Developer Guide ## Quick Reference for Common Tasks ### Using Constants Always use constants instead of magic numbers: ```python from app.core import constants as const # ✅ Good if len(sales_data) < const.MIN_DATA_POINTS_REQUIRED: raise ValueError("Insufficient data") # ❌ Bad if len(sales_data) < 30: raise ValueError("Insufficient data") ``` ### Timezone Handling Always use timezone utilities: ```python from app.utils.timezone_utils import ensure_timezone_aware, prepare_prophet_datetime # ✅ Good - Ensure timezone-aware dt = ensure_timezone_aware(user_input_date) # ✅ Good - Prepare for Prophet df = prepare_prophet_datetime(df, 'ds') # ❌ Bad - Manual timezone handling if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) ``` ### Error Handling Always raise exceptions, never return empty lists: ```python # ✅ Good if not data: raise ValueError(f"No data available for {tenant_id}") # ❌ Bad if not data: logger.error("No data") return [] ``` ### Database Sessions Use context manager correctly: ```python # ✅ Good async with self.database_manager.get_session() as session: await session.execute(query) # ❌ Bad async with self.database_manager.get_session()() as session: # Double call! await session.execute(query) ``` ### Parallel Execution Use asyncio.gather for concurrent operations: ```python # ✅ Good - Parallel tasks = [train_product(pid) for pid in product_ids] results = await asyncio.gather(*tasks, return_exceptions=True) # ❌ Bad - Sequential results = [] for pid in product_ids: result = await train_product(pid) results.append(result) ``` ### HTTP Client Configuration Timeouts are configured automatically in DataClient: ```python # No need to configure timeouts manually # They're set in DataClient.__init__() using constants client = DataClient() # Timeouts already configured ``` ## File Organization ### Core Modules - `core/constants.py` - All configuration constants - `core/config.py` - Service settings - `core/database.py` - Database configuration ### Utilities - `utils/timezone_utils.py` - Timezone handling functions - `utils/__init__.py` - Utility exports ### ML Components - `ml/trainer.py` - Main training orchestration - `ml/prophet_manager.py` - Prophet model management - `ml/data_processor.py` - Data preprocessing ### Services - `services/data_client.py` - External service communication - `services/training_service.py` - Training job management - `services/training_orchestrator.py` - Training pipeline coordination ## Common Pitfalls ### ❌ Don't Create Legacy Aliases ```python # ❌ Bad MyNewClass = OldClassName # Removed! ``` ### ❌ Don't Use Magic Numbers ```python # ❌ Bad if score > 0.8: # What does 0.8 mean? # ✅ Good if score > const.IMPROVEMENT_SIGNIFICANCE_THRESHOLD: ``` ### ❌ Don't Return Empty Lists on Error ```python # ❌ Bad except Exception as e: logger.error(f"Failed: {e}") return [] # ✅ Good except Exception as e: logger.error(f"Failed: {e}") raise RuntimeError(f"Operation failed: {e}") ``` ### ❌ Don't Handle Timezones Manually ```python # ❌ Bad if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) # ✅ Good from app.utils.timezone_utils import ensure_timezone_aware dt = ensure_timezone_aware(dt) ``` ## Testing Checklist Before submitting code: - [ ] All magic numbers replaced with constants - [ ] Timezone handling uses utility functions - [ ] Errors raise exceptions (not return empty collections) - [ ] Database sessions use single `get_session()` call - [ ] Parallel operations use `asyncio.gather` - [ ] No legacy compatibility aliases - [ ] No commented-out code - [ ] Logging uses structured logging ## Performance Guidelines ### Training Jobs - ✅ Use parallel execution for multiple products - ✅ Reduce Optuna trials for low-volume products - ✅ Use constants for all thresholds - ⚠️ Monitor memory usage during parallel training ### Database Operations - ✅ Use repository pattern - ✅ Batch operations when possible - ✅ Close sessions properly - ⚠️ Connection pool limits not yet configured ### HTTP Requests - ✅ Timeouts configured automatically - ✅ Use shared clients from `shared/clients` - ⚠️ Circuit breaker not yet implemented - ⚠️ Request retries delegated to base client ## Debugging Tips ### Training Failures 1. Check logs for data validation errors 2. Verify timezone consistency in date ranges 3. Check minimum data point requirements 4. Review Prophet error messages ### Performance Issues 1. Check if parallel training is being used 2. Verify Optuna trial counts 3. Monitor database connection usage 4. Check HTTP timeout configurations ### Data Quality Issues 1. Review validation errors in logs 2. Check zero-ratio thresholds 3. Verify product classification 4. Review date range alignment ## Migration from Old Code ### If You Find Legacy Code 1. Check if alias exists (should be removed) 2. Update imports to use new names 3. Remove backward compatibility wrappers 4. Update documentation ### If You Find Magic Numbers 1. Add constant to `core/constants.py` 2. Update usage to reference constant 3. Document what the number represents ### If You Find Manual Timezone Handling 1. Import from `utils/timezone_utils` 2. Use appropriate utility function 3. Remove manual implementation ## Getting Help - Review `IMPLEMENTATION_SUMMARY.md` for recent changes - Check constants in `core/constants.py` for configuration - Look at `utils/timezone_utils.py` for timezone functions - Refer to analysis report for architectural decisions --- *Last Updated: 2025-10-07* *Status: Current*