watchSemesterRecords method
Watches aggregated academic records grouped by semester.
Emits cached data immediately, then triggers a background network fetch if data is empty or stale. The stream re-emits automatically when the DB is updated.
Network errors during background refresh are absorbed — the stream continues showing stale (or empty) data rather than erroring.
Implementation
Stream<List<SemesterRecordData>> watchSemesterRecords() async* {
const ttl = Duration(days: 3);
// Watch academic summaries as the trigger signal. Score data changes
// atomically in a transaction, so this catches all updates.
await for (final _
in _database.select(_database.userAcademicSummaries).watch()) {
final user = await _database.select(_database.users).getSingleOrNull();
if (user == null) {
yield [];
continue;
}
final records = await _buildSemesterRecordData(user.id);
if (records.isEmpty) {
try {
await refreshSemesterRecords();
} catch (_) {
// Absorb: yield empty below so UI exits loading state
}
}
yield records;
// Re-read user to get the latest scoreDataFetchedAt
final freshUser = await _database
.select(_database.users)
.getSingleOrNull();
final age = switch (freshUser?.scoreDataFetchedAt) {
final t? => DateTime.now().difference(t),
null => ttl,
};
if (age >= ttl) {
try {
await refreshSemesterRecords();
} catch (_) {
// Absorb: stale data is shown via stream
}
}
}
}