|
| 1 | +# Error Handling Enhancement Summary |
| 2 | + |
| 3 | +## What We Implemented |
| 4 | + |
| 5 | +### 1. Custom Exception Hierarchy (`oura_api_client/exceptions.py`) |
| 6 | +- **Base Exception**: `OuraAPIError` - Base class for all API errors with status code, endpoint, and response tracking |
| 7 | +- **Specific Exceptions**: |
| 8 | + - `OuraAuthenticationError` (401) |
| 9 | + - `OuraAuthorizationError` (403) |
| 10 | + - `OuraNotFoundError` (404) |
| 11 | + - `OuraRateLimitError` (429) - Includes `retry_after` support |
| 12 | + - `OuraClientError` (4xx) |
| 13 | + - `OuraServerError` (5xx) |
| 14 | + - `OuraConnectionError` - Network connection failures |
| 15 | + - `OuraTimeoutError` - Request timeouts |
| 16 | +- **Factory Function**: `create_api_error()` automatically creates the appropriate exception based on HTTP status code |
| 17 | + |
| 18 | +### 2. Retry Logic (`oura_api_client/utils/retry.py`) |
| 19 | +- **Exponential Backoff**: With configurable base delay, max delay, and optional jitter |
| 20 | +- **Smart Retry Detection**: Only retries on transient errors (5xx, connection, timeout, rate limit) |
| 21 | +- **Rate Limit Handling**: Respects `Retry-After` header from API |
| 22 | +- **Configurable**: Via `RetryConfig` class with options for: |
| 23 | + - `max_retries`: Maximum retry attempts (default: 3) |
| 24 | + - `base_delay`: Starting delay in seconds (default: 1.0) |
| 25 | + - `max_delay`: Maximum delay between retries (default: 60.0) |
| 26 | + - `jitter`: Whether to add random jitter (default: true) |
| 27 | + - `enabled`: Toggle retry on/off (default: true) |
| 28 | + |
| 29 | +### 3. Updated Client (`oura_api_client/api/client.py`) |
| 30 | +- Integrated retry logic into `_make_request()` method |
| 31 | +- Proper exception handling for all request types |
| 32 | +- Support for both retry-enabled and direct request modes |
| 33 | +- Clean separation of concerns with `_make_single_request()` and `_make_request_with_retry()` |
| 34 | + |
| 35 | +### 4. Comprehensive Tests (`tests/test_error_handling.py`) |
| 36 | +- 18 test cases covering: |
| 37 | + - Exception creation and behavior |
| 38 | + - Retry logic calculations |
| 39 | + - Client error handling |
| 40 | + - Rate limiting scenarios |
| 41 | + - Connection and timeout errors |
| 42 | + - Endpoint normalization |
| 43 | + - Retry configuration |
| 44 | + |
| 45 | +## Usage Examples |
| 46 | + |
| 47 | +### Basic Usage (Default Retry Enabled) |
| 48 | +```python |
| 49 | +client = OuraClient("your_token") |
| 50 | +# Automatically retries on transient errors |
| 51 | +``` |
| 52 | + |
| 53 | +### Custom Retry Configuration |
| 54 | +```python |
| 55 | +from oura_api_client import OuraClient, RetryConfig |
| 56 | + |
| 57 | +retry_config = RetryConfig( |
| 58 | + max_retries=5, |
| 59 | + base_delay=2.0, |
| 60 | + max_delay=120.0, |
| 61 | + jitter=True |
| 62 | +) |
| 63 | +client = OuraClient("your_token", retry_config=retry_config) |
| 64 | +``` |
| 65 | + |
| 66 | +### Disable Retry |
| 67 | +```python |
| 68 | +retry_config = RetryConfig(enabled=False) |
| 69 | +client = OuraClient("your_token", retry_config=retry_config) |
| 70 | +``` |
| 71 | + |
| 72 | +### Exception Handling |
| 73 | +```python |
| 74 | +from oura_api_client import ( |
| 75 | + OuraClient, |
| 76 | + OuraAuthenticationError, |
| 77 | + OuraRateLimitError, |
| 78 | + OuraServerError |
| 79 | +) |
| 80 | + |
| 81 | +client = OuraClient("your_token") |
| 82 | + |
| 83 | +try: |
| 84 | + data = client.daily_activity.get_daily_activity_documents() |
| 85 | +except OuraAuthenticationError: |
| 86 | + print("Invalid or expired token") |
| 87 | +except OuraRateLimitError as e: |
| 88 | + print(f"Rate limited. Retry after {e.retry_after} seconds") |
| 89 | +except OuraServerError: |
| 90 | + print("Server error - request was automatically retried") |
| 91 | +``` |
| 92 | + |
| 93 | +## Benefits |
| 94 | +1. **Resilience**: Automatic retry on transient failures |
| 95 | +2. **User Experience**: Clear, specific error messages |
| 96 | +3. **Rate Limit Compliance**: Respects API rate limits |
| 97 | +4. **Flexibility**: Configurable retry behavior |
| 98 | +5. **Backward Compatible**: Existing code continues to work |
0 commit comments