fix(test): cancel one-shot Timers on CacheFiller / MutationReplayer dispose
Smoke test failed: "A Timer is still pending even after the widget tree was disposed." Both workers fired their initial-delay Timer via `Timer(duration, _sweep)` and stored only the periodic ticker in the cancellable field — the one-shot Timer leaked past dispose and tripped the test framework's invariant check. Track both as _initialTimer + _intervalTimer; cancel both in dispose(). Behavior is unchanged in production (ref.onDispose only fires on process death normally); this is purely a test-harness fix.
This commit is contained in:
+6
-4
@@ -37,7 +37,8 @@ class CacheFiller {
|
||||
CacheFiller(this._ref);
|
||||
final Ref _ref;
|
||||
|
||||
Timer? _timer;
|
||||
Timer? _initialTimer;
|
||||
Timer? _intervalTimer;
|
||||
bool _running = false;
|
||||
bool _disposed = false;
|
||||
|
||||
@@ -61,8 +62,8 @@ class CacheFiller {
|
||||
static const _maxIdsPerSweep = 200;
|
||||
|
||||
void start() {
|
||||
Timer(_initialDelay, _sweep);
|
||||
_timer = Timer.periodic(_interval, (_) => _sweep());
|
||||
_initialTimer = Timer(_initialDelay, _sweep);
|
||||
_intervalTimer = Timer.periodic(_interval, (_) => _sweep());
|
||||
}
|
||||
|
||||
Future<void> _sweep() async {
|
||||
@@ -217,7 +218,8 @@ class CacheFiller {
|
||||
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
_timer?.cancel();
|
||||
_initialTimer?.cancel();
|
||||
_intervalTimer?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -91,7 +91,8 @@ class MutationReplayer {
|
||||
MutationReplayer(this._ref);
|
||||
final Ref _ref;
|
||||
|
||||
Timer? _timer;
|
||||
Timer? _initialTimer;
|
||||
Timer? _intervalTimer;
|
||||
bool _running = false;
|
||||
bool _disposed = false;
|
||||
|
||||
@@ -109,7 +110,7 @@ class MutationReplayer {
|
||||
// Drain shortly after launch in case there are queued mutations
|
||||
// from a prior session that died offline. 3s lets the auth +
|
||||
// server-url + dio providers finish their async warmup.
|
||||
Timer(const Duration(seconds: 3), drain);
|
||||
_initialTimer = Timer(const Duration(seconds: 3), drain);
|
||||
|
||||
// Drain on every connectivity emission that resolves to online.
|
||||
// ref.listen fires on changes after subscription; we don't get
|
||||
@@ -120,7 +121,7 @@ class MutationReplayer {
|
||||
if (isOnline) unawaited(drain());
|
||||
});
|
||||
|
||||
_timer = Timer.periodic(_interval, (_) => drain());
|
||||
_intervalTimer = Timer.periodic(_interval, (_) => drain());
|
||||
}
|
||||
|
||||
/// Walk the queue oldest-first, replaying each mutation. Stops on
|
||||
@@ -214,7 +215,8 @@ class MutationReplayer {
|
||||
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
_timer?.cancel();
|
||||
_initialTimer?.cancel();
|
||||
_intervalTimer?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user