mirror of
https://github.com/apidoorman/doorman.git
synced 2026-02-09 19:18:38 -06:00
446 lines
14 KiB
Python
446 lines
14 KiB
Python
"""
|
|
Test Centralized Error Code Registry
|
|
Documents the implementation of centralized error code constants for API consistency
|
|
"""
|
|
|
|
def test_error_code_registry():
|
|
"""Test error code registry implementation"""
|
|
|
|
print("Centralized Error Code Registry - Implementation")
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("P1 Enhancement:")
|
|
print(" Error codes (GTW001, AUTH001) inconsistent across codebase")
|
|
print(" → Hard to search/refactor error codes")
|
|
print(" → Duplicate or conflicting error codes")
|
|
print(" → No single source of truth")
|
|
print(" → Developer confusion about available codes")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Implementation Location:")
|
|
print()
|
|
print(" File: backend-services/utils/error_codes.py")
|
|
print(" Class: ErrorCode")
|
|
print(" Total Error Codes: 150+")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Error Code Categories:")
|
|
print()
|
|
|
|
categories = [
|
|
{
|
|
'category': 'Authentication & Authorization',
|
|
'prefix': 'AUTH',
|
|
'range': 'AUTH001-AUTH999',
|
|
'count': 8,
|
|
'examples': ['AUTH_INVALID_CREDENTIALS', 'AUTH_TOKEN_EXPIRED']
|
|
},
|
|
{
|
|
'category': 'User Management',
|
|
'prefix': 'USR',
|
|
'range': 'USR001-USR999',
|
|
'count': 11,
|
|
'examples': ['USR_NOT_FOUND', 'USR_WEAK_PASSWORD']
|
|
},
|
|
{
|
|
'category': 'API Management',
|
|
'prefix': 'API',
|
|
'range': 'API001-API999',
|
|
'count': 10,
|
|
'examples': ['API_NOT_FOUND', 'API_ALREADY_EXISTS']
|
|
},
|
|
{
|
|
'category': 'Endpoint Management',
|
|
'prefix': 'END',
|
|
'range': 'END001-END999',
|
|
'count': 23,
|
|
'examples': ['END_NOT_FOUND', 'END_SERVER_INVALID']
|
|
},
|
|
{
|
|
'category': 'Role Management',
|
|
'prefix': 'ROLE',
|
|
'range': 'ROLE001-ROLE999',
|
|
'count': 13,
|
|
'examples': ['ROLE_NOT_FOUND', 'ROLE_NAME_IMMUTABLE']
|
|
},
|
|
{
|
|
'category': 'Group Management',
|
|
'prefix': 'GRP',
|
|
'range': 'GRP001-GRP999',
|
|
'count': 10,
|
|
'examples': ['GRP_NOT_FOUND', 'GRP_PERMISSION_DENIED']
|
|
},
|
|
{
|
|
'category': 'Subscription Management',
|
|
'prefix': 'SUB',
|
|
'range': 'SUB001-SUB999',
|
|
'count': 7,
|
|
'examples': ['SUB_NOT_FOUND', 'SUB_ALREADY_EXISTS']
|
|
},
|
|
{
|
|
'category': 'Routing',
|
|
'prefix': 'RTG',
|
|
'range': 'RTG001-RTG999',
|
|
'count': 10,
|
|
'examples': ['RTG_NOT_FOUND', 'RTG_PRIORITY_CONFLICT']
|
|
},
|
|
{
|
|
'category': 'Credit System',
|
|
'prefix': 'CRD',
|
|
'range': 'CRD001-CRD999',
|
|
'count': 22,
|
|
'examples': ['CRD_NOT_FOUND', 'CRD_API_KEY_REQUIRED']
|
|
},
|
|
{
|
|
'category': 'Gateway',
|
|
'prefix': 'GTW',
|
|
'range': 'GTW001-GTW999',
|
|
'count': 12,
|
|
'examples': ['GTW_UPSTREAM_ERROR', 'GTW_TIMEOUT']
|
|
},
|
|
{
|
|
'category': 'Configuration',
|
|
'prefix': 'CFG',
|
|
'range': 'CFG001-CFG999',
|
|
'count': 9,
|
|
'examples': ['CFG_PERMISSION_DENIED', 'CFG_NOT_FOUND']
|
|
},
|
|
{
|
|
'category': 'Security',
|
|
'prefix': 'SEC',
|
|
'range': 'SEC001-SEC999',
|
|
'count': 5,
|
|
'examples': ['SEC_PERMISSION_DENIED', 'SEC_INVALID_IP']
|
|
},
|
|
{
|
|
'category': 'Logging',
|
|
'prefix': 'LOG',
|
|
'range': 'LOG001-LOG999',
|
|
'count': 5,
|
|
'examples': ['LOG_INVALID_LEVEL', 'LOG_UPDATE_FAILED']
|
|
},
|
|
{
|
|
'category': 'Monitoring',
|
|
'prefix': 'MON',
|
|
'range': 'MON001-MON999',
|
|
'count': 3,
|
|
'examples': ['MON_PERMISSION_DENIED', 'MON_QUERY_FAILED']
|
|
},
|
|
{
|
|
'category': 'General/System',
|
|
'prefix': 'GEN/ISE',
|
|
'range': 'GEN001-ISE999',
|
|
'count': 5,
|
|
'examples': ['GEN_VALIDATION_ERROR', 'ISE_INTERNAL_ERROR']
|
|
}
|
|
]
|
|
|
|
for cat in categories:
|
|
print(f"{cat['category']}:")
|
|
print(f" Prefix: {cat['prefix']}")
|
|
print(f" Range: {cat['range']}")
|
|
print(f" Count: {cat['count']} error codes")
|
|
print(f" Examples: {', '.join(cat['examples'])}")
|
|
print()
|
|
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Naming Convention:")
|
|
print()
|
|
print(" Format: CATEGORY_DESCRIPTION = 'PREFIX###'")
|
|
print()
|
|
print(" Examples:")
|
|
print(" AUTH_INVALID_CREDENTIALS = 'AUTH001'")
|
|
print(" USER_NOT_FOUND = 'USR002'")
|
|
print(" API_ALREADY_EXISTS = 'API001'")
|
|
print(" GATEWAY_TIMEOUT = 'GTW002'")
|
|
print()
|
|
print(" Rules:")
|
|
print(" - Constant name: UPPERCASE_WITH_UNDERSCORES")
|
|
print(" - Error code value: PREFIX + 3-digit number")
|
|
print(" - Descriptive constant name (not just number)")
|
|
print(" - Sequential numbering within category")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Usage Examples:")
|
|
print()
|
|
print(" 1. With HTTPException:")
|
|
print()
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print()
|
|
print(" raise HTTPException(")
|
|
print(" status_code=401,")
|
|
print(" detail={")
|
|
print(" 'error_code': ErrorCode.AUTH_INVALID_CREDENTIALS,")
|
|
print(" 'message': 'Invalid username or password'")
|
|
print(" }")
|
|
print(" )")
|
|
print()
|
|
print(" 2. With ResponseModel:")
|
|
print()
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print()
|
|
print(" return ResponseModel(")
|
|
print(" status_code=404,")
|
|
print(" error_code=ErrorCode.USER_NOT_FOUND,")
|
|
print(" error_message='User not found'")
|
|
print(" ).dict()")
|
|
print()
|
|
print(" 3. In Conditional Logic:")
|
|
print()
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print()
|
|
print(" if not user:")
|
|
print(" logger.error(f'User retrieval failed with code {ErrorCode.USER_NOT_FOUND}')")
|
|
print(" return ResponseModel(")
|
|
print(" status_code=404,")
|
|
print(" error_code=ErrorCode.USER_NOT_FOUND,")
|
|
print(" error_message='User not found'")
|
|
print(" ).dict()")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Benefits:")
|
|
print()
|
|
print(" Code Quality:")
|
|
print(" ✓ Single source of truth for all error codes")
|
|
print(" ✓ Autocomplete in IDE (ErrorCode.)")
|
|
print(" ✓ Compile-time checking (no typos)")
|
|
print(" ✓ Easy to search/refactor (find usages)")
|
|
print()
|
|
print(" Consistency:")
|
|
print(" ✓ No duplicate error codes")
|
|
print(" ✓ No conflicting error codes")
|
|
print(" ✓ Consistent naming across codebase")
|
|
print(" ✓ Clear category boundaries")
|
|
print()
|
|
print(" Documentation:")
|
|
print(" ✓ All error codes in one place")
|
|
print(" ✓ Easy to generate error code reference")
|
|
print(" ✓ Comments explain each error")
|
|
print(" ✓ Grouped by category for clarity")
|
|
print()
|
|
print(" Maintainability:")
|
|
print(" ✓ Easy to add new error codes")
|
|
print(" ✓ Easy to deprecate old codes")
|
|
print(" ✓ Prevents accidental code conflicts")
|
|
print(" ✓ Version control friendly")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Migration Strategy:")
|
|
print()
|
|
print(" Phase 1: Add Constants (DONE)")
|
|
print(" - Created error_codes.py")
|
|
print(" - Defined all existing error codes")
|
|
print(" - Added comprehensive comments")
|
|
print()
|
|
print(" Phase 2: Gradual Adoption (Optional)")
|
|
print(" - Update new code to use ErrorCode constants")
|
|
print(" - Gradually refactor existing code")
|
|
print(" - No breaking changes (values unchanged)")
|
|
print()
|
|
print(" Phase 3: Enforcement (Future)")
|
|
print(" - Add lint rule to enforce constant usage")
|
|
print(" - Deprecate string literals")
|
|
print(" - Complete migration")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Example Refactor:")
|
|
print()
|
|
print(" BEFORE:")
|
|
print(" return ResponseModel(")
|
|
print(" status_code=404,")
|
|
print(" error_code='USR002', # What does USR002 mean?")
|
|
print(" error_message='User not found'")
|
|
print(" ).dict()")
|
|
print()
|
|
print(" AFTER:")
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print()
|
|
print(" return ResponseModel(")
|
|
print(" status_code=404,")
|
|
print(" error_code=ErrorCode.USER_NOT_FOUND, # Self-documenting")
|
|
print(" error_message='User not found'")
|
|
print(" ).dict()")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Backward Compatibility:")
|
|
print()
|
|
print(" String Values Unchanged:")
|
|
print(" - ErrorCode.AUTH_INVALID_CREDENTIALS == 'AUTH001'")
|
|
print(" - Can use constant or string interchangeably")
|
|
print(" - No breaking changes to API responses")
|
|
print()
|
|
print(" Alias Class:")
|
|
print(" - ErrorCodes (plural) = alias of ErrorCode")
|
|
print(" - Supports legacy imports")
|
|
print(" - Deprecated, use ErrorCode instead")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Adding New Error Codes:")
|
|
print()
|
|
print(" 1. Choose appropriate category:")
|
|
print(" - AUTH, USR, API, END, GTW, etc.")
|
|
print()
|
|
print(" 2. Find next available number:")
|
|
print(" - Check existing codes in category")
|
|
print(" - Use next sequential number")
|
|
print()
|
|
print(" 3. Add constant to ErrorCode class:")
|
|
print(" USER_EMAIL_TAKEN = 'USR017' # Email already in use")
|
|
print()
|
|
print(" 4. Add inline comment:")
|
|
print(" - Brief description of when error occurs")
|
|
print(" - Helps developers choose correct code")
|
|
print()
|
|
print(" 5. Use in code:")
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print()
|
|
print(" if existing_user:")
|
|
print(" return ResponseModel(")
|
|
print(" status_code=400,")
|
|
print(" error_code=ErrorCode.USER_EMAIL_TAKEN,")
|
|
print(" error_message='Email already in use'")
|
|
print(" ).dict()")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Error Code Ranges:")
|
|
print()
|
|
print(" Reserved Ranges:")
|
|
print(" 001-099: Common errors (CRUD operations)")
|
|
print(" 100-199: Validation errors")
|
|
print(" 200-299: Business logic errors")
|
|
print(" 300-399: Integration errors")
|
|
print(" 900-999: Unexpected/generic errors")
|
|
print()
|
|
print(" Examples:")
|
|
print(" USR001: User already exists (common)")
|
|
print(" USR002: User not found (common)")
|
|
print(" USR005: Weak password (validation)")
|
|
print(" USR016: Too many attributes (validation)")
|
|
print(" AUTH900: Unexpected auth error (generic)")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Error Response Format:")
|
|
print()
|
|
print(" Recommended Structure:")
|
|
print(" {")
|
|
print(" 'status_code': 404,")
|
|
print(" 'error_code': 'USR002', // from ErrorCode.USER_NOT_FOUND")
|
|
print(" 'error_message': 'User not found',")
|
|
print(" 'request_id': 'abc-123', // optional")
|
|
print(" 'details': {...} // optional")
|
|
print(" }")
|
|
print()
|
|
print(" Client Usage:")
|
|
print(" - Check error_code for programmatic handling")
|
|
print(" - Show error_message to users")
|
|
print(" - Log request_id for debugging")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Search & Documentation:")
|
|
print()
|
|
print(" Find all uses of an error code:")
|
|
print(" grep -r 'ErrorCode.USER_NOT_FOUND' .")
|
|
print(" # or")
|
|
print(" grep -r \"'USR002'\" .")
|
|
print()
|
|
print(" Generate error code reference:")
|
|
print(" python3 -c \"")
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print(" for attr in dir(ErrorCode):")
|
|
print(" if not attr.startswith('_'):")
|
|
print(" print(f'{attr} = {getattr(ErrorCode, attr)}')")
|
|
print(" \"")
|
|
print()
|
|
print(" IDE autocomplete:")
|
|
print(" from utils.error_codes import ErrorCode")
|
|
print(" ErrorCode. # Press Tab/Ctrl+Space for all error codes")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Testing Recommendations:")
|
|
print()
|
|
print(" 1. Test error code uniqueness:")
|
|
print(" - Ensure no duplicate error code values")
|
|
print(" - Check all codes are unique")
|
|
print()
|
|
print(" 2. Test error code format:")
|
|
print(" - Verify all codes match PREFIX### pattern")
|
|
print(" - Check prefix matches category")
|
|
print()
|
|
print(" 3. Test error code usage:")
|
|
print(" - Search codebase for string literals ('AUTH001')")
|
|
print(" - Verify migration to constants")
|
|
print()
|
|
print(" 4. Test backward compatibility:")
|
|
print(" - Verify ErrorCode.CONSTANT == 'VALUE'")
|
|
print(" - Check API responses unchanged")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("Future Enhancements:")
|
|
print()
|
|
print(" 1. Error code metadata:")
|
|
print(" - Add HTTP status code mapping")
|
|
print(" - Add suggested user messages")
|
|
print(" - Add severity levels")
|
|
print()
|
|
print(" 2. Error code documentation:")
|
|
print(" - Generate markdown reference")
|
|
print(" - Include in API docs")
|
|
print(" - Add to developer portal")
|
|
print()
|
|
print(" 3. Error code validation:")
|
|
print(" - Lint rule to enforce constant usage")
|
|
print(" - Pre-commit hook to check duplicates")
|
|
print(" - CI check for error code conflicts")
|
|
print()
|
|
print(" 4. Error code analytics:")
|
|
print(" - Track error code frequency")
|
|
print(" - Alert on unusual error patterns")
|
|
print(" - Dashboard for error monitoring")
|
|
print()
|
|
print("=" * 70)
|
|
print()
|
|
|
|
print("P1 Enhancement Impact:")
|
|
print(" Error codes inconsistent across codebase")
|
|
print()
|
|
print("Production Impact:")
|
|
print(" ✓ Single source of truth for all error codes")
|
|
print(" ✓ No duplicate or conflicting codes")
|
|
print(" ✓ Easy to search and refactor")
|
|
print(" ✓ IDE autocomplete for developers")
|
|
print(" ✓ Self-documenting code")
|
|
print(" ✓ Consistent error handling")
|
|
print()
|
|
|
|
if __name__ == '__main__':
|
|
test_error_code_registry()
|