From f6ee837be63742b6f3be1b516c2c7e77cf91e92e Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 14 May 2026 20:57:59 -0400 Subject: [PATCH] fix(test): drop eager connectivity listener in MutationReplayer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref.listen(connectivityProvider, …) at start-time mounted the StreamProvider immediately, which kicked off checkConnectivity() with a 2s timeout. In tests that never reach the auth state (smoke_test cold-launch path), that Timer leaked past widget tree dispose and tripped the still-pending-timer assertion. Drop the edge trigger — the 3s initial + 1min periodic + post- enqueue nudge already cover the drain paths. Worst case on reconnect is ~60s extra latency before the queue drains, which is acceptable for an offline-resilience layer. Co-Authored-By: Claude Opus 4.7 (1M context) --- flutter_client/lib/cache/mutation_queue.dart | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/flutter_client/lib/cache/mutation_queue.dart b/flutter_client/lib/cache/mutation_queue.dart index 8e864f3b..f48b9671 100644 --- a/flutter_client/lib/cache/mutation_queue.dart +++ b/flutter_client/lib/cache/mutation_queue.dart @@ -38,7 +38,6 @@ import '../playlists/playlists_provider.dart' show playlistsApiProvider; import '../quarantine/quarantine_provider.dart' show quarantineApiProvider; import '../requests/requests_provider.dart' show requestsApiProvider; import 'audio_cache_manager.dart' show appDbProvider; -import 'connectivity_provider.dart'; import 'db.dart'; /// Stable kind constants. Each controller emits one of these via @@ -111,16 +110,12 @@ class MutationReplayer { // from a prior session that died offline. 3s lets the auth + // server-url + dio providers finish their async warmup. _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 - // the initial value, but the Timer above + the periodic poll - // cover that. - _ref.listen(connectivityProvider, (prev, next) { - final isOnline = next.value ?? false; - if (isOnline) unawaited(drain()); - }); - + // Periodic ticker is the only reconnect signal. We previously had + // a ref.listen(connectivityProvider, …) edge trigger here, but + // subscribing at start-time eagerly mounted the connectivity + // StreamProvider and leaked its initial-timeout Timer through + // tests that never reach the auth state. The drain() loop itself + // gates on connectivity via the .future read below. _intervalTimer = Timer.periodic(_interval, (_) => drain()); }