78 lines
1.4 KiB
Dart
78 lines
1.4 KiB
Dart
import 'dart:async';
|
|
|
|
|
|
class RelinkScheduler {
|
|
RelinkScheduler({
|
|
this.maxAttempts = 3,
|
|
this.backoffs = const [
|
|
Duration.zero,
|
|
Duration(seconds: 2),
|
|
Duration(seconds: 5),
|
|
],
|
|
}) : assert(maxAttempts > 0),
|
|
assert(backoffs.isNotEmpty);
|
|
|
|
final int maxAttempts;
|
|
final List<Duration> backoffs;
|
|
|
|
int _attempts = 0;
|
|
bool _pending = false;
|
|
Timer? _backoffTimer;
|
|
Timer? _sustainTimer;
|
|
|
|
|
|
bool get pending => _pending;
|
|
|
|
|
|
int get attempts => _attempts;
|
|
|
|
|
|
bool schedule({
|
|
required void Function(Duration delay) onRelink,
|
|
required void Function() onGiveUp,
|
|
}) {
|
|
if (_pending) return false;
|
|
|
|
|
|
_sustainTimer?.cancel();
|
|
|
|
if (_attempts >= maxAttempts) {
|
|
onGiveUp();
|
|
return false;
|
|
}
|
|
final backoffIndex = _attempts.clamp(0, backoffs.length - 1);
|
|
final delay = backoffs[backoffIndex];
|
|
_attempts++;
|
|
|
|
_pending = true;
|
|
_backoffTimer?.cancel();
|
|
_backoffTimer = Timer(delay, () {
|
|
_pending = false;
|
|
onRelink(delay);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
|
|
void armSustain({Duration sustain = const Duration(seconds: 30)}) {
|
|
_sustainTimer?.cancel();
|
|
_sustainTimer = Timer(sustain, () => _attempts = 0);
|
|
}
|
|
|
|
|
|
void cancelPending() {
|
|
_backoffTimer?.cancel();
|
|
_pending = false;
|
|
}
|
|
|
|
|
|
void reset() => _attempts = 0;
|
|
|
|
|
|
void dispose() {
|
|
_backoffTimer?.cancel();
|
|
_sustainTimer?.cancel();
|
|
_pending = false;
|
|
}
|
|
}
|