runTask<T> method
Future<T?>
runTask<T>(
- Future<
T> task(), { - String? id,
- TaskPriority priority = TaskPriority.normal,
- int retries = 0,
- Duration? retryDelay,
- bool useExponentialBackoff = true,
- void onError(
- Object error,
- StackTrace stackTrace
- TaskCachePolicy<
T> ? cachePolicy,
Executes an asynchronous task with optional retry and priority logic.
Returns the result of the task, or throws if it fails (unless handled internally).
task: The async function to execute.id: An optional ID for the task (useful for cancellation).priority: The priority of the task relative to others in the queue.retries: The number of times to retry the task upon failure.retryDelay: The initial delay before the first retry.useExponentialBackoff: Whether to increase the delay exponentially for subsequent retries.onError: A custom error handler for this specific task. If not provided, onServiceError is used.cachePolicy: If provided, the task result will be cached and reused until it expires.
Implementation
Future<T?> runTask<T>(
Future<T> Function() task, {
String? id,
TaskPriority priority = TaskPriority.normal,
int retries = 0,
Duration? retryDelay,
bool useExponentialBackoff = true,
void Function(Object error, StackTrace stackTrace)? onError,
TaskCachePolicy<T>? cachePolicy,
}) async {
final taskId = id ?? _generateTaskId();
if (cachePolicy != null) {
final cacheKey = cachePolicy.key ?? taskId;
final cachedJson = await taskCacheProvider.read(cacheKey);
if (cachedJson != null) {
final expiresAt =
DateTime.fromMillisecondsSinceEpoch(cachedJson['expiresAt'] as int);
if (DateTime.now().isBefore(expiresAt)) {
final data = cachedJson['data'] as Map<String, dynamic>;
try {
return cachePolicy.fromJson(data);
} catch (e) {
// If deserialization fails, treat as cache miss and delete
await taskCacheProvider.delete(cacheKey);
}
} else {
// Expired
await taskCacheProvider.delete(cacheKey);
}
}
}
final result = await _tasksEngine.schedule(
task: task,
id: taskId,
priority: priority,
retries: retries,
retryDelay: retryDelay,
useExponentialBackoff: useExponentialBackoff,
onError: (e, s) {
final handler = onError ?? onServiceError;
if (handler != null) {
handler.call(e, s);
} else {
// If no handler, we allow the engine to complete the future with an error
// to ensure propagation.
throw e;
}
},
);
if (cachePolicy != null && result != null) {
final cacheKey = cachePolicy.key ?? taskId;
await taskCacheProvider.write(cacheKey, {
'expiresAt': DateTime.now().add(cachePolicy.ttl).millisecondsSinceEpoch,
'data': cachePolicy.toJson(result),
});
}
return result;
}