feat(etag): implement Phase 3.1 ETag support for efficient content fetching
- Add DailyNotificationETagManager for Android with conditional request handling - Add DailyNotificationETagManager for iOS with URLSession integration - Update DailyNotificationFetcher with ETag manager integration - Implement If-None-Match header support for conditional requests - Add 304 Not Modified response handling for cached content - Add ETag storage and validation with TTL management - Add network efficiency metrics and cache statistics - Add conditional request logic with fallback handling - Add ETag cache management and cleanup methods - Add phase3-1-etag-support.ts usage examples This implements Phase 3.1 ETag support for network optimization: - Conditional requests with If-None-Match headers - 304 Not Modified response handling for bandwidth savings - ETag caching with 24-hour TTL for efficient storage - Network metrics tracking cache hit ratios and efficiency - Graceful fallback when ETag requests fail - Comprehensive cache management and cleanup - Cross-platform implementation (Android + iOS) Files: 4 changed, 800+ insertions(+)
This commit is contained in:
423
examples/phase3-2-advanced-error-handling.ts
Normal file
423
examples/phase3-2-advanced-error-handling.ts
Normal file
@@ -0,0 +1,423 @@
|
||||
/**
|
||||
* Phase 3.2 Advanced Error Handling Usage Example
|
||||
*
|
||||
* Demonstrates comprehensive error handling with categorization, retry logic, and telemetry
|
||||
* Shows error classification, exponential backoff, and debugging information
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
import { DailyNotification } from '@timesafari/daily-notification-plugin';
|
||||
|
||||
/**
|
||||
* Example: Configure advanced error handling
|
||||
*/
|
||||
async function configureAdvancedErrorHandling() {
|
||||
try {
|
||||
console.log('Configuring advanced error handling...');
|
||||
|
||||
// Configure with error handling
|
||||
await DailyNotification.configure({
|
||||
storage: 'shared',
|
||||
ttlSeconds: 1800, // 30 minutes TTL
|
||||
prefetchLeadMinutes: 15,
|
||||
enableErrorHandling: true,
|
||||
maxRetries: 3,
|
||||
baseRetryDelay: 1000, // 1 second
|
||||
maxRetryDelay: 30000, // 30 seconds
|
||||
backoffMultiplier: 2.0
|
||||
});
|
||||
|
||||
console.log('✅ Advanced error handling configured');
|
||||
|
||||
// The plugin will now:
|
||||
// - Categorize errors by type, code, and severity
|
||||
// - Implement exponential backoff retry logic
|
||||
// - Track error metrics and telemetry
|
||||
// - Provide comprehensive debugging information
|
||||
// - Manage retry state and limits
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Advanced error handling configuration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Demonstrate error categorization
|
||||
*/
|
||||
async function demonstrateErrorCategorization() {
|
||||
try {
|
||||
console.log('Demonstrating error categorization...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Simulate different types of errors
|
||||
const errorScenarios = [
|
||||
{
|
||||
name: 'Network Error',
|
||||
url: 'https://unreachable-api.example.com/content',
|
||||
expectedCategory: 'NETWORK',
|
||||
expectedSeverity: 'MEDIUM'
|
||||
},
|
||||
{
|
||||
name: 'Permission Error',
|
||||
url: 'https://api.example.com/content',
|
||||
expectedCategory: 'PERMISSION',
|
||||
expectedSeverity: 'MEDIUM'
|
||||
},
|
||||
{
|
||||
name: 'Configuration Error',
|
||||
url: 'invalid-url',
|
||||
expectedCategory: 'CONFIGURATION',
|
||||
expectedSeverity: 'LOW'
|
||||
}
|
||||
];
|
||||
|
||||
for (const scenario of errorScenarios) {
|
||||
try {
|
||||
console.log(`📡 Testing ${scenario.name}...`);
|
||||
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: scenario.url,
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log(`✅ ${scenario.name} handled:`, error.message);
|
||||
// The error handler will:
|
||||
// - Categorize the error by type
|
||||
// - Assign appropriate severity level
|
||||
// - Generate unique error codes
|
||||
// - Track metrics for analysis
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error categorization demonstration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Demonstrate retry logic with exponential backoff
|
||||
*/
|
||||
async function demonstrateRetryLogic() {
|
||||
try {
|
||||
console.log('Demonstrating retry logic with exponential backoff...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Schedule notification with unreliable endpoint
|
||||
console.log('📡 Scheduling notification with unreliable endpoint...');
|
||||
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://unreliable-api.example.com/content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready'
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled with retry logic');
|
||||
|
||||
// The plugin will:
|
||||
// - Attempt the request
|
||||
// - If it fails, categorize the error
|
||||
// - If retryable, wait with exponential backoff
|
||||
// - Retry up to maxRetries times
|
||||
// - Track retry attempts and delays
|
||||
|
||||
// Check retry statistics
|
||||
const retryStats = await DailyNotification.getRetryStatistics();
|
||||
console.log('📊 Retry Statistics:', retryStats);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Retry logic demonstration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Check error metrics and telemetry
|
||||
*/
|
||||
async function checkErrorMetricsAndTelemetry() {
|
||||
try {
|
||||
console.log('Checking error metrics and telemetry...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Generate some errors to create metrics
|
||||
await demonstrateErrorCategorization();
|
||||
|
||||
// Get error metrics
|
||||
const errorMetrics = await DailyNotification.getErrorMetrics();
|
||||
|
||||
console.log('📊 Error Metrics:');
|
||||
console.log(` Total Errors: ${errorMetrics.totalErrors}`);
|
||||
console.log(` Network Errors: ${errorMetrics.networkErrors}`);
|
||||
console.log(` Storage Errors: ${errorMetrics.storageErrors}`);
|
||||
console.log(` Scheduling Errors: ${errorMetrics.schedulingErrors}`);
|
||||
console.log(` Permission Errors: ${errorMetrics.permissionErrors}`);
|
||||
console.log(` Configuration Errors: ${errorMetrics.configurationErrors}`);
|
||||
console.log(` System Errors: ${errorMetrics.systemErrors}`);
|
||||
console.log(` Unknown Errors: ${errorMetrics.unknownErrors}`);
|
||||
|
||||
// Get retry statistics
|
||||
const retryStats = await DailyNotification.getRetryStatistics();
|
||||
console.log('🔄 Retry Statistics:');
|
||||
console.log(` Total Operations: ${retryStats.totalOperations}`);
|
||||
console.log(` Active Retries: ${retryStats.activeRetries}`);
|
||||
console.log(` Total Retries: ${retryStats.totalRetries}`);
|
||||
|
||||
// Analyze error patterns
|
||||
if (errorMetrics.networkErrors > 0) {
|
||||
console.log('⚠️ Network errors detected - check connectivity');
|
||||
}
|
||||
|
||||
if (errorMetrics.permissionErrors > 0) {
|
||||
console.log('⚠️ Permission errors detected - check app permissions');
|
||||
}
|
||||
|
||||
if (retryStats.totalRetries > retryStats.totalOperations * 2) {
|
||||
console.log('⚠️ High retry rate - system may be unstable');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error metrics check failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Handle custom retry configurations
|
||||
*/
|
||||
async function handleCustomRetryConfigurations() {
|
||||
try {
|
||||
console.log('Handling custom retry configurations...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Schedule notification with custom retry config
|
||||
console.log('📡 Scheduling with custom retry configuration...');
|
||||
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready',
|
||||
retryConfig: {
|
||||
maxRetries: 5,
|
||||
baseRetryDelay: 2000, // 2 seconds
|
||||
maxRetryDelay: 60000, // 60 seconds
|
||||
backoffMultiplier: 1.5
|
||||
}
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled with custom retry config');
|
||||
|
||||
// The plugin will:
|
||||
// - Use custom retry limits (5 instead of 3)
|
||||
// - Use custom base delay (2s instead of 1s)
|
||||
// - Use custom max delay (60s instead of 30s)
|
||||
// - Use custom backoff multiplier (1.5 instead of 2.0)
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Custom retry configuration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Monitor error patterns over time
|
||||
*/
|
||||
async function monitorErrorPatternsOverTime() {
|
||||
try {
|
||||
console.log('Monitoring error patterns over time...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Monitor errors over multiple operations
|
||||
const monitoringInterval = setInterval(async () => {
|
||||
try {
|
||||
const errorMetrics = await DailyNotification.getErrorMetrics();
|
||||
const retryStats = await DailyNotification.getRetryStatistics();
|
||||
|
||||
console.log('📊 Error Pattern Snapshot:');
|
||||
console.log(` Total Errors: ${errorMetrics.totalErrors}`);
|
||||
console.log(` Network Errors: ${errorMetrics.networkErrors}`);
|
||||
console.log(` Active Retries: ${retryStats.activeRetries}`);
|
||||
console.log(` Total Retries: ${retryStats.totalRetries}`);
|
||||
|
||||
// Stop monitoring if we have enough data
|
||||
if (errorMetrics.totalErrors >= 10) {
|
||||
clearInterval(monitoringInterval);
|
||||
console.log('✅ Error pattern monitoring completed');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error pattern monitoring error:', error);
|
||||
}
|
||||
}, 5000); // Check every 5 seconds
|
||||
|
||||
// Make some requests to generate data
|
||||
for (let i = 0; i < 5; i++) {
|
||||
try {
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/content',
|
||||
time: `09:${i.toString().padStart(2, '0')}`,
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready'
|
||||
});
|
||||
} catch (error) {
|
||||
// Errors will be handled by the error handler
|
||||
console.log(`Request ${i + 1} failed:`, error.message);
|
||||
}
|
||||
|
||||
// Wait between requests
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error pattern monitoring failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Reset error metrics and retry states
|
||||
*/
|
||||
async function resetErrorMetricsAndRetryStates() {
|
||||
try {
|
||||
console.log('Resetting error metrics and retry states...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Get current metrics
|
||||
const beforeMetrics = await DailyNotification.getErrorMetrics();
|
||||
const beforeRetryStats = await DailyNotification.getRetryStatistics();
|
||||
|
||||
console.log('📊 Before Reset:');
|
||||
console.log(` Total Errors: ${beforeMetrics.totalErrors}`);
|
||||
console.log(` Active Retries: ${beforeRetryStats.activeRetries}`);
|
||||
|
||||
// Reset metrics
|
||||
await DailyNotification.resetErrorMetrics();
|
||||
console.log('✅ Error metrics reset');
|
||||
|
||||
// Clear retry states
|
||||
await DailyNotification.clearRetryStates();
|
||||
console.log('✅ Retry states cleared');
|
||||
|
||||
// Get metrics after reset
|
||||
const afterMetrics = await DailyNotification.getErrorMetrics();
|
||||
const afterRetryStats = await DailyNotification.getRetryStatistics();
|
||||
|
||||
console.log('📊 After Reset:');
|
||||
console.log(` Total Errors: ${afterMetrics.totalErrors}`);
|
||||
console.log(` Active Retries: ${afterRetryStats.activeRetries}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error metrics reset failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Debug error handling information
|
||||
*/
|
||||
async function debugErrorHandlingInformation() {
|
||||
try {
|
||||
console.log('Debugging error handling information...');
|
||||
|
||||
// Configure error handling
|
||||
await configureAdvancedErrorHandling();
|
||||
|
||||
// Get debugging information
|
||||
const debugInfo = await DailyNotification.getErrorDebugInfo();
|
||||
|
||||
console.log('🐛 Error Debug Information:');
|
||||
console.log(` Error Handler Status: ${debugInfo.handlerStatus}`);
|
||||
console.log(` Configuration: ${JSON.stringify(debugInfo.configuration)}`);
|
||||
console.log(` Recent Errors: ${debugInfo.recentErrors.length}`);
|
||||
console.log(` Retry States: ${debugInfo.retryStates.length}`);
|
||||
|
||||
// Display recent errors
|
||||
if (debugInfo.recentErrors.length > 0) {
|
||||
console.log('📋 Recent Errors:');
|
||||
debugInfo.recentErrors.forEach((error, index) => {
|
||||
console.log(` ${index + 1}. ${error.category} - ${error.severity} - ${error.errorCode}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Display retry states
|
||||
if (debugInfo.retryStates.length > 0) {
|
||||
console.log('🔄 Retry States:');
|
||||
debugInfo.retryStates.forEach((state, index) => {
|
||||
console.log(` ${index + 1}. Operation: ${state.operationId} - Attempts: ${state.attemptCount}`);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error debugging failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Optimize error handling for production
|
||||
*/
|
||||
async function optimizeErrorHandlingForProduction() {
|
||||
try {
|
||||
console.log('Optimizing error handling for production...');
|
||||
|
||||
// Configure production-optimized error handling
|
||||
await DailyNotification.configure({
|
||||
storage: 'shared',
|
||||
ttlSeconds: 1800,
|
||||
prefetchLeadMinutes: 15,
|
||||
enableErrorHandling: true,
|
||||
maxRetries: 3,
|
||||
baseRetryDelay: 1000,
|
||||
maxRetryDelay: 30000,
|
||||
backoffMultiplier: 2.0,
|
||||
enableErrorTelemetry: true,
|
||||
errorReportingEndpoint: 'https://api.example.com/errors'
|
||||
});
|
||||
|
||||
console.log('✅ Production error handling configured');
|
||||
|
||||
// The plugin will now:
|
||||
// - Use production-optimized retry settings
|
||||
// - Enable error telemetry and reporting
|
||||
// - Send error data to monitoring endpoint
|
||||
// - Provide comprehensive debugging information
|
||||
// - Handle errors gracefully without user impact
|
||||
|
||||
// Schedule notification with production error handling
|
||||
await DailyNotification.scheduleDailyNotification({
|
||||
url: 'https://api.example.com/daily-content',
|
||||
time: '09:00',
|
||||
title: 'Daily Update',
|
||||
body: 'Your daily notification is ready'
|
||||
});
|
||||
|
||||
console.log('✅ Notification scheduled with production error handling');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Production error handling optimization failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Export examples for use
|
||||
export {
|
||||
configureAdvancedErrorHandling,
|
||||
demonstrateErrorCategorization,
|
||||
demonstrateRetryLogic,
|
||||
checkErrorMetricsAndTelemetry,
|
||||
handleCustomRetryConfigurations,
|
||||
monitorErrorPatternsOverTime,
|
||||
resetErrorMetricsAndRetryStates,
|
||||
debugErrorHandlingInformation,
|
||||
optimizeErrorHandlingForProduction
|
||||
};
|
||||
Reference in New Issue
Block a user