fix: Klassenlehrer-Übersicht rief Schülerreport bislang live statt gecacht ab
Die Übersicht wirkte beim Öffnen spürbar zeitverzögert, obwohl Fehlzeiten und Klassenbuch schon lokal gecacht waren (Nutzer-Feedback: "fühlt sich an wie ein Live-Pull mit CSV-Parsing"). Grund: genau das passierte - der Schülerreport (Namen fürs Roster) lief komplett am Cache vorbei bei jedem Öffnen live gegen WebUntis. Neues UntisStudentRosterCacheEntry/UntisStudentRosterCacheRepository (gleiches "kein db.OnChange"-Prinzip wie die bestehenden Caches) plus UntisReportCacheService.GetStudentRosterAsync - ohne heißes/kaltes Fenster, da eine Klassenliste keine Historie hat, nur dieselbe Stundenschwelle "gilt der letzte Abruf noch als frisch". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,11 +29,39 @@ public sealed class UntisReportCacheService(
|
||||
WebUntisIntegrationService untis,
|
||||
IUntisAbsenceCacheRepository absenceCache,
|
||||
IUntisClassRegisterCacheRepository classRegisterCache,
|
||||
IUntisStudentRosterCacheRepository rosterCache,
|
||||
IUntisCacheFetchStateRepository fetchState)
|
||||
{
|
||||
private static readonly TimeSpan HotWindowRefreshInterval = TimeSpan.FromHours(1);
|
||||
private const int HotWindowDays = 14;
|
||||
|
||||
/// Roster hat anders als Fehlzeiten/Klassenbuch keine Historie (nur "aktueller Stand einer
|
||||
/// Klasse") - deshalb ohne heißes/kaltes Fenster, nur "gilt der letzte Abruf noch als frisch".
|
||||
/// Behebt, dass die Klassenlehrer-Übersicht bei jedem Öffnen spürbar verzögert wirkte: der
|
||||
/// Roster-Abruf lief bislang komplett am Cache vorbei live gegen WebUntis (Nutzer-Feedback).
|
||||
public async Task<IReadOnlyList<UntisStudentRosterCacheEntry>> GetStudentRosterAsync(string className,
|
||||
bool forceRefresh = false, CancellationToken token = default)
|
||||
{
|
||||
var state = fetchState.Get(className, UntisCacheKind.Roster);
|
||||
if (NeedsRefresh(state, forceRefresh, DateTime.UtcNow))
|
||||
{
|
||||
var fresh = await untis.GetStudentsAsync(className, token);
|
||||
rosterCache.ReplaceAll(className, fresh.Students.Select(s => new UntisStudentRosterCacheEntry
|
||||
{
|
||||
ClassName = className, ExternKey = s.ExternKey, DisplayName = s.DisplayName,
|
||||
}));
|
||||
fetchState.Save(new UntisCacheFetchState
|
||||
{
|
||||
Id = state?.Id ?? Guid.NewGuid(), ClassName = className, Kind = UntisCacheKind.Roster,
|
||||
HotWindowFetchedAt = DateTime.UtcNow,
|
||||
});
|
||||
}
|
||||
return rosterCache.GetByClass(className);
|
||||
}
|
||||
|
||||
private static bool NeedsRefresh(UntisCacheFetchState? state, bool forceRefresh, DateTime utcNow) =>
|
||||
forceRefresh || state?.HotWindowFetchedAt is null || utcNow - state.HotWindowFetchedAt >= HotWindowRefreshInterval;
|
||||
|
||||
public async Task<IReadOnlyList<UntisClassAbsenceEntryDto>> GetAbsencesAsync(string className,
|
||||
DateOnly start, DateOnly end, bool forceRefresh = false, CancellationToken token = default)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user