diag(flutter): time-box connectivity check + trace album cold-cache path
Two changes to surface where detail-screen spinners hang: 1. Connectivity().checkConnectivity() goes over a platform channel that on some Android builds stalls. Wrap with a 2s timeout and default to "online" if it times out — being wrong about connectivity costs at most one failed fetch, but being stuck spins the UI forever. 2. albumProvider's cold-cache flow now debugPrints at every step: drift miss → connectivity result → API call → drift write → ack the re-emit. Also adds a 10s timeout on the API fetch and a 3s timeout on the connectivity await so a hang surfaces as an error-yielded empty AlbumRef instead of an infinite spinner. Once the operator's next test produces logs we can pinpoint which step is hanging. The diagnostic prints stay until the issue's root cause is confirmed; will be removed in a follow-up.
This commit is contained in:
+14
-1
@@ -17,6 +17,19 @@ final connectivityProvider = StreamProvider<bool>((ref) async* {
|
||||
bool isOnline(List<ConnectivityResult> rs) =>
|
||||
rs.any((r) => r != ConnectivityResult.none);
|
||||
|
||||
yield isOnline(await c.checkConnectivity());
|
||||
// checkConnectivity() goes over a platform channel and on some
|
||||
// Android builds it can stall. Fall back to "assume online" after
|
||||
// 2s so consumers waiting on .future never block forever — being
|
||||
// wrong about connectivity costs at most one failed request, but
|
||||
// being stuck spins the UI indefinitely.
|
||||
try {
|
||||
final initial = await c.checkConnectivity().timeout(
|
||||
const Duration(seconds: 2),
|
||||
onTimeout: () => const [ConnectivityResult.wifi],
|
||||
);
|
||||
yield isOnline(initial);
|
||||
} catch (_) {
|
||||
yield true;
|
||||
}
|
||||
yield* c.onConnectivityChanged.map(isOnline);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:drift/drift.dart' as drift;
|
||||
import 'package:flutter/foundation.dart' show debugPrint;
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../api/client.dart';
|
||||
@@ -154,24 +155,42 @@ final albumProvider = StreamProvider.family<
|
||||
|
||||
await for (final albumRows in albumQuery.watch()) {
|
||||
if (albumRows.isEmpty) {
|
||||
debugPrint('albumProvider($albumId): drift miss, attempting cold-cache fetch');
|
||||
// Cold cache fallback
|
||||
if (await ref.read(connectivityProvider.future)) {
|
||||
bool online;
|
||||
try {
|
||||
online = await ref
|
||||
.read(connectivityProvider.future)
|
||||
.timeout(const Duration(seconds: 3), onTimeout: () => true);
|
||||
} catch (e) {
|
||||
debugPrint('albumProvider($albumId): connectivity check threw $e — assuming online');
|
||||
online = true;
|
||||
}
|
||||
debugPrint('albumProvider($albumId): online=$online');
|
||||
if (online) {
|
||||
try {
|
||||
final api = await ref.read(libraryApiProvider.future);
|
||||
final fresh = await api.getAlbum(albumId);
|
||||
debugPrint('albumProvider($albumId): calling getAlbum');
|
||||
final fresh = await api
|
||||
.getAlbum(albumId)
|
||||
.timeout(const Duration(seconds: 10));
|
||||
debugPrint('albumProvider($albumId): got ${fresh.tracks.length} tracks, writing to drift');
|
||||
await db.batch((b) {
|
||||
b.insertAllOnConflictUpdate(db.cachedAlbums, [fresh.album.toDrift()]);
|
||||
b.insertAllOnConflictUpdate(db.cachedTracks,
|
||||
fresh.tracks.map((t) => t.toDrift()).toList());
|
||||
});
|
||||
debugPrint('albumProvider($albumId): drift write done; awaiting watch re-emit');
|
||||
// watch() re-emits with the populated rows; loop continues.
|
||||
} catch (_) {
|
||||
} catch (e, st) {
|
||||
debugPrint('albumProvider($albumId): cold-cache fetch failed: $e\n$st');
|
||||
yield (
|
||||
album: const AlbumRef(id: '', title: '', artistId: ''),
|
||||
tracks: const <TrackRef>[],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
debugPrint('albumProvider($albumId): offline, yielding empty');
|
||||
yield (
|
||||
album: const AlbumRef(id: '', title: '', artistId: ''),
|
||||
tracks: const <TrackRef>[],
|
||||
@@ -179,6 +198,7 @@ final albumProvider = StreamProvider.family<
|
||||
}
|
||||
continue;
|
||||
}
|
||||
debugPrint('albumProvider($albumId): drift hit (${albumRows.length} rows)');
|
||||
|
||||
final albumRow = albumRows.first;
|
||||
final album = albumRow.readTable(db.cachedAlbums).toRef(
|
||||
|
||||
Reference in New Issue
Block a user