ResilienceContext
The ResilienceContext
class provides contextual information and state management throughout the execution of a resilience pipeline.
Overview
The resilience context is passed through the entire execution chain, allowing strategies to share state, cancel operations, and access execution metadata. It serves as the communication channel between different strategies and the application.
class ResilienceContext {
ResilienceContext();
ResilienceContext.withCancellationToken(CancellationToken cancellationToken);
CancellationToken get cancellationToken;
bool get isCancellationRequested;
Map<String, dynamic> get properties;
void setProperty(String key, dynamic value);
T? getProperty<T>(String key);
bool hasProperty(String key);
void removeProperty(String key);
void clearProperties();
}
Constructors
ResilienceContext()
Creates a new resilience context with a default cancellation token.
final context = ResilienceContext();
ResilienceContext.withCancellationToken(CancellationToken cancellationToken)
Creates a new resilience context with the specified cancellation token.
Parameters:
cancellationToken
- The cancellation token for operation cancellation
final cancellationToken = CancellationToken();
final context = ResilienceContext.withCancellationToken(cancellationToken);
Properties
cancellationToken
Gets the cancellation token associated with this context.
Type: CancellationToken
final token = context.cancellationToken;
if (token.isCancellationRequested) {
// Handle cancellation
}
isCancellationRequested
Gets a value indicating whether cancellation has been requested.
Type: bool
if (context.isCancellationRequested) {
throw OperationCancelledException();
}
properties
Gets the properties dictionary for storing custom data.
Type: Map<String, dynamic>
final props = context.properties;
print('Total properties: ${props.length}');
Methods
setProperty(String key, dynamic value)
Sets a property value in the context.
Parameters:
key
- The property keyvalue
- The property value
context.setProperty('userId', '12345');
context.setProperty('retryCount', 0);
context.setProperty('startTime', DateTime.now());
getProperty<T>(String key)
Gets a property value from the context with type casting.
Parameters:
key
- The property key
Returns: T?
- The property value cast to type T, or null if not found
final userId = context.getProperty<String>('userId');
final retryCount = context.getProperty<int>('retryCount') ?? 0;
final startTime = context.getProperty<DateTime>('startTime');
hasProperty(String key)
Checks if a property exists in the context.
Parameters:
key
- The property key
Returns: bool
- True if the property exists, false otherwise
if (context.hasProperty('cacheKey')) {
final cacheKey = context.getProperty<String>('cacheKey');
// Use cached value
}
removeProperty(String key)
Removes a property from the context.
Parameters:
key
- The property key to remove
context.removeProperty('temporaryData');
clearProperties()
Removes all properties from the context.
context.clearProperties();
Usage Examples
Basic Context Usage
final context = ResilienceContext();
// Execute with context
final result = await pipeline.execute(
(context) async {
// Check for cancellation
if (context.isCancellationRequested) {
throw OperationCancelledException();
}
return await apiCall();
},
context: context,
);
Context with Cancellation
final cancellationToken = CancellationToken();
final context = ResilienceContext.withCancellationToken(cancellationToken);
// Cancel after 10 seconds
Timer(Duration(seconds: 10), () {
cancellationToken.cancel();
});
try {
final result = await pipeline.execute(
(context) async {
context.cancellationToken.throwIfCancellationRequested();
return await longRunningOperation();
},
context: context,
);
} on OperationCancelledException {
print('Operation was cancelled');
}
Sharing State Between Strategies
final context = ResilienceContext();
final pipeline = ResiliencePipelineBuilder()
.addRetry(RetryStrategyOptions(
onRetry: (context, args) {
// Track retry attempts
final retryCount = context.getProperty<int>('retryCount') ?? 0;
context.setProperty('retryCount', retryCount + 1);
},
))
.addCircuitBreaker(CircuitBreakerStrategyOptions(
onOpened: (context, args) {
// Access retry information
final retryCount = context.getProperty<int>('retryCount') ?? 0;
print('Circuit opened after $retryCount retries');
},
))
.build();
Request Tracking
final context = ResilienceContext();
context.setProperty('requestId', 'req-12345');
context.setProperty('userId', 'user-67890');
context.setProperty('startTime', DateTime.now());
final result = await pipeline.execute(
(context) async {
final requestId = context.getProperty<String>('requestId');
final userId = context.getProperty<String>('userId');
print('Processing request $requestId for user $userId');
return await processRequest(requestId, userId);
},
context: context,
);
final endTime = DateTime.now();
final startTime = context.getProperty<DateTime>('startTime')!;
final duration = endTime.difference(startTime);
print('Request completed in ${duration.inMilliseconds}ms');
Caching with Context
final context = ResilienceContext();
final result = await pipeline.execute(
(context) async {
final cacheKey = 'data-${userId}';
// Check cache first
if (context.hasProperty(cacheKey)) {
return context.getProperty<String>(cacheKey)!;
}
// Fetch from service
final data = await fetchUserData(userId);
// Cache for future use
context.setProperty(cacheKey, data);
return data;
},
context: context,
);
Best Practices
Property Naming
Use descriptive, namespaced property keys to avoid conflicts:
context.setProperty('app.userId', userId);
context.setProperty('retry.attemptCount', attemptCount);
context.setProperty('circuitBreaker.lastFailureTime', DateTime.now());
Cleanup
Remove temporary properties when no longer needed:
// Set temporary data
context.setProperty('temp.calculationResult', result);
// Use the data
final temp = context.getProperty('temp.calculationResult');
// Clean up
context.removeProperty('temp.calculationResult');
Type Safety
Always specify types when getting properties:
// Good
final count = context.getProperty<int>('retryCount') ?? 0;
// Avoid
final count = context.getProperty('retryCount') ?? 0; // Type is dynamic