9.5 KiB
9.5 KiB
API Error Handling & Resilience System
This document describes the comprehensive error handling infrastructure added to the GridPilot website to handle API connectivity issues, request errors, and provide graceful degradation.
Overview
The system provides:
- Enhanced error classification with detailed error types
- Automatic retry logic with exponential backoff
- Circuit breaker pattern to prevent cascading failures
- Connection health monitoring with real-time status
- User-friendly error messages for production
- Developer-friendly debugging tools for development
- Graceful degradation with fallbacks and caching
- Offline mode detection
Core Components
1. Enhanced Error Classification (ApiError)
Location: lib/api/base/ApiError.ts
Error Types:
NETWORK_ERROR- Connection failed, CORS issuesAUTH_ERROR- 401/403 authentication issuesVALIDATION_ERROR- 400 bad requestNOT_FOUND- 404 resource not foundSERVER_ERROR- 500+ server issuesRATE_LIMIT_ERROR- 429 too many requestsTIMEOUT_ERROR- Request timeoutCANCELED_ERROR- Request aborted
Features:
- Automatic error type classification
- User-friendly vs developer-friendly messages
- Retry capability detection
- Connectivity issue detection
- Severity levels for logging
2. Retry Handler & Circuit Breaker (RetryHandler.ts)
Location: lib/api/base/RetryHandler.ts
Retry Logic:
- Exponential backoff with jitter
- Configurable max retries (default: 3)
- Configurable timeout (default: 30s)
- Abort support for cancellation
Circuit Breaker:
- Tracks failures per endpoint
- Opens after threshold (default: 5 failures)
- Half-open state for recovery testing
- Automatic reset after timeout
3. Connection Monitor (ApiConnectionMonitor.ts)
Location: lib/api/base/ApiConnectionMonitor.ts
Features:
- Real-time connection status tracking
- Health check polling (every 30s)
- Reliability percentage calculation
- Event emitter for status changes
- Request/response time tracking
Statuses:
connected- Healthy APIdegraded- Reduced reliabilitydisconnected- Unavailablechecking- Health check in progress
4. Enhanced BaseApiClient (BaseApiClient.ts)
Location: lib/api/base/BaseApiClient.ts
Enhancements:
- Automatic error classification
- Retry logic integration
- Circuit breaker usage
- Connection monitoring
- Timeout handling
- Request cancellation
Usage:
const client = new BaseApiClient(
baseUrl,
errorReporter,
logger,
{ timeout: 30000, retry: true }
);
// All methods now support retry and graceful degradation
const data = await client.get('/api/endpoint');
5. Error UI Components
Location: components/errors/
Components:
ErrorDisplay.tsx- User-friendly error screenDevErrorPanel.tsx- Developer debugging panelApiErrorBoundary.tsx- React error boundaryApiStatusToolbar.tsx- Real-time status toolbarNotificationIntegration.tsx- Notification system integration
6. Graceful Degradation (GracefulDegradation.ts)
Location: lib/api/base/GracefulDegradation.ts
Features:
- Response caching with TTL
- Fallback data support
- Offline mode detection
- Service wrapper for easy usage
Usage:
import { withGracefulDegradation, GracefulService } from './GracefulDegradation';
// Direct usage
const data = await withGracefulDegradation(
() => apiClient.getData(),
{
fallback: defaultData,
timeout: 5000,
useCache: true
}
);
// Service wrapper
const userService = new GracefulService(
'user-data',
() => apiClient.getUser(),
defaultUser
);
const user = await userService.get();
7. Enhanced Error Reporter (EnhancedErrorReporter.ts)
Location: lib/infrastructure/EnhancedErrorReporter.ts
Features:
- Environment-specific handling
- User notification integration
- Error buffering for batch reporting
- Custom error handlers
- External service integration (placeholder)
Integration in Application
Layout Integration
// apps/website/app/layout.tsx
import { NotificationIntegration } from '@/components/errors/NotificationIntegration';
import { ApiErrorBoundary } from '@/components/errors/ApiErrorBoundary';
import { ApiStatusToolbar } from '@/components/errors/ApiStatusToolbar';
export default function RootLayout({ children }) {
return (
<html>
<body>
<NotificationProvider>
<NotificationIntegration />
<ApiErrorBoundary>
{/* Your app content */}
{children}
{/* Development toolbar */}
{process.env.NODE_ENV === 'development' && (
<ApiStatusToolbar position="bottom-right" autoHide={true} />
)}
</ApiErrorBoundary>
</NotificationProvider>
</body>
</html>
);
}
Service Integration
// lib/services/DriverService.ts
import { BaseApiClient } from '@/lib/api/base/BaseApiClient';
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
import { ConsoleLogger } from '@/lib/infrastructure/ConsoleLogger';
// Enhanced service with error handling
export class DriverService {
private apiClient: BaseApiClient;
private errorReporter: EnhancedErrorReporter;
constructor() {
const logger = new ConsoleLogger();
this.errorReporter = new EnhancedErrorReporter(logger, {
showUserNotifications: true,
logToConsole: true,
reportToExternal: process.env.NODE_ENV === 'production',
});
this.apiClient = new BaseApiClient(
getWebsiteApiBaseUrl(),
this.errorReporter,
logger,
{ timeout: 30000, retry: true }
);
}
async getDriverProfile(driverId: string): Promise<DriverProfileViewModel | null> {
try {
const dto = await this.apiClient.getDriverProfile(driverId);
return new DriverProfileViewModel(dto);
} catch (error) {
// Error already handled by BaseApiClient
// Return null for graceful degradation
return null;
}
}
}
Development Tools
DevToolbar Integration
The enhanced DevToolbar includes:
- Real-time API status indicator
- Reliability percentage
- Circuit breaker status
- Health check button
- Stats reset
- Test error trigger
ApiStatusToolbar
A floating toolbar that shows:
- Current connection status
- Request statistics
- Circuit breaker states
- Quick actions for testing
Error Handling Patterns
1. Automatic Retry
// Automatically retries failed requests
const data = await client.get('/api/data');
2. Graceful Fallback
const data = await withGracefulDegradation(
() => client.get('/api/data'),
{ fallback: defaultData }
);
3. Error Boundary
<ApiErrorBoundary>
<MyComponent />
</ApiErrorBoundary>
4. Manual Error Handling
try {
const data = await client.get('/api/data');
} catch (error) {
if (isApiError(error)) {
if (error.isRetryable()) {
// Show retry button
}
if (error.isConnectivityIssue()) {
// Show connection error
}
}
}
Environment-Specific Behavior
Development
- Detailed error messages with stack traces
- Developer error panel with full context
- API status toolbar always visible
- Console logging with full details
- Test error triggers
Production
- User-friendly error messages
- Modal notifications for critical errors
- Toast notifications for warnings
- No sensitive data in error messages
- Automatic error reporting to external services
Monitoring & Debugging
Connection Health
import { connectionMonitor } from '@/lib/api/base/ApiConnectionMonitor';
// Get current status
const status = connectionMonitor.getStatus();
// Get detailed health
const health = connectionMonitor.getHealth();
// Run manual health check
const result = await connectionMonitor.performHealthCheck();
Circuit Breaker Status
import { CircuitBreakerRegistry } from '@/lib/api/base/RetryHandler';
const registry = CircuitBreakerRegistry.getInstance();
const status = registry.getStatus();
Error Buffer
import { getGlobalErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
const reporter = getGlobalErrorReporter();
const errors = reporter.getBufferedErrors();
reporter.flush(); // Send batch
Best Practices
- Always use BaseApiClient for API calls
- Wrap critical components with ApiErrorBoundary
- Provide fallbacks for graceful degradation
- Use error classification for specific handling
- Monitor connection status for user feedback
- Test error scenarios in development
- Log appropriately based on severity
- Use caching for frequently accessed data
Troubleshooting
API Always Shows "Disconnected"
- Check API_BASE_URL environment variable
- Verify CORS configuration on API server
- Check browser console for network errors
- Use DevToolbar health check
Requests Not Retrying
- Verify retry option is enabled in BaseApiClient
- Check error type is retryable
- Review circuit breaker status
Notifications Not Showing
- Ensure NotificationProvider wraps your app
- Check NotificationIntegration is mounted
- Verify error severity levels
Circuit Breaker Stays Open
- Check API server health
- Reset circuit breakers via DevToolbar
- Review error logs for root cause
Future Enhancements
- External error reporting (Sentry, LogRocket)
- Persistent cache storage (IndexedDB)
- Offline queue for failed requests
- Performance metrics dashboard
- A/B testing for error recovery strategies