handleUDXOperation<T> static method
Future<T>
handleUDXOperation<T>(
- Future<
T> operation(), - String context, {
- UDXRetryConfig retryConfig = UDXRetryConfig.regular,
- bool shouldRetry(
- dynamic error
Handles UDX operations with comprehensive exception handling and retry logic
Implementation
static Future<T> handleUDXOperation<T>(
Future<T> Function() operation,
String context, {
UDXRetryConfig retryConfig = UDXRetryConfig.regular,
bool Function(dynamic error)? shouldRetry,
}) async {
int attempt = 0;
Duration delay = retryConfig.initialDelay;
while (attempt <= retryConfig.maxRetries) {
try {
_logger.fine('[UDXExceptionHandler] Executing operation: $context (attempt ${attempt + 1}/${retryConfig.maxRetries + 1})');
return await operation();
} catch (error, stackTrace) {
final classifiedException = classifyUDXException(error, context, stackTrace);
// If this is the last attempt or error is not retryable, throw
if (attempt >= retryConfig.maxRetries ||
!shouldRetryError(classifiedException, shouldRetry)) {
_logger.warning('[UDXExceptionHandler] Operation failed permanently: $context. Error: $classifiedException');
throw classifiedException;
}
// Log retry attempt
_logger.info('[UDXExceptionHandler] Operation failed, retrying: $context. Attempt ${attempt + 1}/${retryConfig.maxRetries + 1}. Error: $classifiedException');
// Calculate delay with exponential backoff and optional jitter
if (retryConfig.enableJitter) {
final jitter = _random.nextDouble() * 0.1; // 10% jitter
delay = Duration(
milliseconds: (delay.inMilliseconds * (1 + jitter)).round(),
);
}
await Future.delayed(delay);
// Update delay for next iteration
delay = Duration(
milliseconds: (delay.inMilliseconds * retryConfig.backoffMultiplier).round(),
);
if (delay > retryConfig.maxDelay) {
delay = retryConfig.maxDelay;
}
attempt++;
}
}
// This should never be reached, but just in case
throw UDXTransportException('Max retries exceeded', context, null);
}