Add automatic retry logic with exponential backoff to a Cubit method for transient failures
This skill adds automatic retry logic with exponential backoff to a Cubit method.
Adds the retry parameter to a mix() call so that failed methods automatically retry with configurable:
Ask the user which Cubit method should have retry logic, or identify methods that:
Add retry: retry to the mix() call:
import 'package:bloc_superpowers/bloc_superpowers.dart';
class UserCubit extends Cubit<User> {
UserCubit() : super(User());
void loadData() => mix(
key: this,
retry: retry, // Add this line
() async {
final user = await api.loadUser();
if (user == null) throw UserException('Failed to load user');
emit(user);
},
);
}
The default retry configuration:
Customize as needed:
void loadData() => mix(
key: this,
retry: retry(
maxRetries: 5, // 5 retries (6 total attempts)
initialDelay: 1.sec, // Start with 1 second delay
multiplier: 2.0, // Double each time: 1s → 2s → 4s → 8s → 10s
maxDelay: 10.sec, // Cap at 10 seconds
),
() async {
final user = await api.loadUser();
emit(user);
},
);
retry // 3 retries with defaults
retry(maxRetries: 5) // 5 retries
retry(maxRetries: 10) // 10 retries
Use for critical operations that must eventually succeed:
retry.unlimited // Retry forever with default timing
retry(maxRetries: -1) // Same as above
// Unlimited with custom timing
retry(initialDelay: 500.millis).unlimited
retry(initialDelay: 1.sec, maxDelay: 30.sec).unlimited
// Faster initial retry
retry(initialDelay: 100.millis)
// Slower backoff
retry(multiplier: 1.5)
// Higher cap
retry(maxDelay: 30.sec)
// Full customization
retry(
maxRetries: 5,
initialDelay: 500.millis,
multiplier: 1.5,
maxDelay: 15.sec,
)
The retry delay starts after the method execution completes (not from when it started).
Example with default settings and a method that takes 1 second to fail:
context.isFailed() and show in UserExceptionDialogCombine retry with internet connectivity check:
void loadData() => mix(
key: this,
checkInternet: checkInternet,
retry: retry,
() async {
final data = await api.getData();
emit(data);
},
);
For critical startup data, retry forever until internet is available:
void loadInitialData() => mix(
key: this,
checkInternet: checkInternet(maxRetryDelay: 1.sec),
retry: retry.unlimited,
() async {
final data = await api.getInitialData();
emit(data);
},
);
Use mix.ctx to access retry information inside the method:
void loadData() => mix.ctx(
key: this,
retry: retry,
(ctx) async {
final retryCtx = ctx.retry!;
final attempt = retryCtx.attempt; // Zero-based (0, 1, 2, ...)
final maxRetries = retryCtx.config.maxRetries;
print('Attempt ${attempt + 1} of ${maxRetries + 1}');
final data = await api.getData();
emit(data);
},
);
Good candidates for retry:
Not recommended for retry:
Ask the user:
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer