JetLeaf Resilience π
Fault tolerance and resilience patterns for JetLeaf applications.
Features
- π Declarative Retry Logic β Use
@Retryableannotations for transparent retry behavior - β±οΈ Flexible Backoff Strategies β Exponential, fixed, and random backoff policies
- π‘οΈ Recovery Mechanisms β Graceful degradation with
@Recovercallbacks - π Observability β Built-in retry listeners and statistics
- π― AOP Integration β Seamless method interception via JetLeaf's IoC container
- βοΈ Environment-Aware β Configure retry behavior via application properties
Installation
Add to your pubspec.yaml:
dependencies:
jetleaf_retry: ^1.0.0
Quick Start
Basic Retry
import 'package:jetleaf_resilience/jetleaf_resilience.dart';
class ApiService {
@Retryable(maxAttempts: 3)
Future<Response> fetchData() async {
return await httpClient.get('/api/data');
}
}
Retry with Backoff
@Retryable(
maxAttempts: 5,
backoff: Backoff(
delay: 1000, // 1 second initial delay
multiplier: 2.0, // Double delay each retry
maxDelay: 30000, // Cap at 30 seconds
random: true, // Add random jitter
),
)
Future<User> fetchUser(String id) async {
return await apiClient.getUser(id);
}
Retry Specific Exceptions
@Retryable(
maxAttempts: 3,
retryFor: [IOException, TimeoutException],
noRetryFor: [AuthenticationException],
)
Future<Data> fetchSecureData() async {
// Retries on IOException or TimeoutException
// Does NOT retry on AuthenticationException
return await secureApi.getData();
}
Recovery Callback
class DataService {
@Retryable(maxAttempts: 3, label: 'fetchUserData')
Future<UserData> fetchUserData(String userId) async {
return await apiClient.getUserData(userId);
}
@Recover(label: 'fetchUserData')
Future<UserData> fetchUserDataRecovery(Exception e, String userId) async {
// Fallback: return cached data
return await cache.getUserData(userId) ?? UserData.empty();
}
}
Configuration
Via Annotations
@Retryable(
maxAttempts: 5,
backoff: Backoff(
delay: 1000,
multiplier: 2.0,
maxDelay: 30000,
random: true,
),
retryFor: [IOException],
label: 'fetchCriticalData',
)
Via Environment Properties
@ConfigurationProperties(prefix: 'app.retry')
class RetryConfiguration implements EnvironmentAware {
late Environment _environment;
int get maxAttempts => _environment.getProperty('max-attempts', int, defaultValue: 3);
int get delay => _environment.getProperty('delay', int, defaultValue: 1000);
@override
void setEnvironment(Environment environment) {
_environment = environment;
}
}
Retry Listeners
Monitor retry operations for observability:
@RetryListenerAnnotation()
class MetricsRetryListener implements RetryListener {
@override
void onOpen(RetryContext context) {
print('π Retry operation started: ${context.getName()}');
}
@override
void onRetry(RetryContext context) {
print('β οΈ Retry attempt ${context.getAttemptCount()}');
}
@override
void onError(RetryContext context, Exception exception) {
print('β Error: $exception');
}
@override
void onClose(RetryContext context, Exception? lastException) {
print('β
Operation completed after ${context.getAttemptCount()} attempts');
}
}
Manual Retry Execution
For programmatic control:
final executor = RetryExecutor(
retryPolicy: SimpleRetryPolicy(maxAttempts: 3),
backoffPolicy: ExponentialBackoffPolicy(initialDelay: 1000),
listeners: [LoggingRetryListener()],
);
final result = await executor.execute(
callback: () async => await apiClient.fetchData(),
recovery: () async => cachedData,
);
Statistics
Track retry operations:
final factory = context.getPod<ResilienceFactory>();
final stats = factory.statistics;
print('Started: ${stats.getStartedCount()}');
print('Success: ${stats.getSuccessCount()}');
print('Exhausted: ${stats.getExhaustedCount()}');
print('Recovered: ${stats.getRecoveryCount()}');
Architecture
@Retryable method call
β
Proxy created by JetLeaf AOP
β
ResilienceFactory (intercepts method)
β
RetryExecutor.execute(RetryCallback, RecoveryCallback)
β
Policy and backoff control loop
β
Method succeeds β return result
β OR
Retries exhausted β call @Recover method
License
Part of the JetLeaf framework.
Libraries
- jetleaf_retry
- π JetLeaf Retry Library