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 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; } }