From 708aa3991a97f0a30c865686c7a80bb04afc45d3 Mon Sep 17 00:00:00 2001 From: MarcWieland Date: Mon, 8 Jun 2026 16:39:28 +0200 Subject: [PATCH] peformance verbesserungen --- .../Components/Pages/Home.razor | 27 ++++++++++++++++--- .../Components/Pages/Month.razor | 12 ++++++--- .../Components/Pages/Settings.razor | 8 ++++-- .../Components/Pages/UrlaubsMaximizer.razor | 9 +++++-- .../Services/ClientHolidayService.cs | 20 +++++++++++++- .../Services/ClientTimetrackerService.cs | 10 ++++++- 6 files changed, 73 insertions(+), 13 deletions(-) diff --git a/timetracker.Client/Components/Pages/Home.razor b/timetracker.Client/Components/Pages/Home.razor index b7da6e6..21e8dd4 100644 --- a/timetracker.Client/Components/Pages/Home.razor +++ b/timetracker.Client/Components/Pages/Home.razor @@ -358,20 +358,39 @@ else _userId = int.Parse(claim.Value); _monday = GetMonday(DateOnly.FromDateTime(DateTime.Today)); _settings = await TrackerService.GetSettingsAsync(_userId); - await LoadWeek(); - _totalOvertime = await TrackerService.GetTotalOvertimeAsync(_userId, _settings); + + var loadWeekTask = LoadWeek(); + var overtimeTask = TrackerService.GetTotalOvertimeAsync(_userId, _settings); + + await Task.WhenAll(loadWeekTask, overtimeTask); + _totalOvertime = await overtimeTask; _loading = false; } private async Task LoadWeek() { + Task> holidaysTask; if (_monday.Year != _holidayYear) { - var list = await HolidayService.GetHolidaysAsync(_monday.Year, _settings.GermanState); + holidaysTask = HolidayService.GetHolidaysAsync(_monday.Year, _settings.GermanState); + } + else + { + holidaysTask = Task.FromResult(new List()); + } + + var dbDaysTask = TrackerService.GetWeekAsync(_userId, _monday); + + await Task.WhenAll(holidaysTask, dbDaysTask); + + if (_monday.Year != _holidayYear) + { + var list = await holidaysTask; _holidays = list.ToDictionary(h => h.Date, h => h.Name); _holidayYear = _monday.Year; } - var dbDays = await TrackerService.GetWeekAsync(_userId, _monday); + + var dbDays = await dbDaysTask; _days = Enumerable.Range(0, 7).Select(i => { var date = _monday.AddDays(i); diff --git a/timetracker.Client/Components/Pages/Month.razor b/timetracker.Client/Components/Pages/Month.razor index 31c03e2..4c9628c 100644 --- a/timetracker.Client/Components/Pages/Month.razor +++ b/timetracker.Client/Components/Pages/Month.razor @@ -181,9 +181,15 @@ else private async Task LoadMonth() { - var workDays = await TrackerService.GetMonthAsync(_userId, _year, _month); - var holidays = await HolidayService.GetHolidaysAsync(_year, _settings.GermanState); - var vacations = await TrackerService.GetVacationDaysAsync(_userId, _year); + var workDaysTask = TrackerService.GetMonthAsync(_userId, _year, _month); + var holidaysTask = HolidayService.GetHolidaysAsync(_year, _settings.GermanState); + var vacationsTask = TrackerService.GetVacationDaysAsync(_userId, _year); + + await Task.WhenAll(workDaysTask, holidaysTask, vacationsTask); + + var workDays = await workDaysTask; + var holidays = await holidaysTask; + var vacations = await vacationsTask; var holidayMap = holidays.ToDictionary(h => h.Date, h => h.Name); var vacationSet = vacations.Select(v => v.Date).ToHashSet(); diff --git a/timetracker.Client/Components/Pages/Settings.razor b/timetracker.Client/Components/Pages/Settings.razor index 117c489..716e1f4 100644 --- a/timetracker.Client/Components/Pages/Settings.razor +++ b/timetracker.Client/Components/Pages/Settings.razor @@ -495,8 +495,12 @@ else if (claim == null) return; _userId = int.Parse(claim.Value); _settings = await TrackerService.GetSettingsAsync(_userId); - await LoadVacations(); - _holHolidays = await HolidayService.GetHolidaysAsync(_holYear, _settings.GermanState); + + var loadVacationsTask = LoadVacations(); + var loadHolidaysTask = HolidayService.GetHolidaysAsync(_holYear, _settings.GermanState); + + await Task.WhenAll(loadVacationsTask, loadHolidaysTask); + _holHolidays = await loadHolidaysTask; } private async Task LoadVacations() diff --git a/timetracker.Client/Components/Pages/UrlaubsMaximizer.razor b/timetracker.Client/Components/Pages/UrlaubsMaximizer.razor index 11e01ad..e6e095b 100644 --- a/timetracker.Client/Components/Pages/UrlaubsMaximizer.razor +++ b/timetracker.Client/Components/Pages/UrlaubsMaximizer.razor @@ -249,8 +249,13 @@ else private async Task LoadYear() { - var holidays = await HolidayService.GetHolidaysAsync(_year, _settings.GermanState); - var vacations = await TrackerService.GetVacationDaysAsync(_userId, _year); + var holidaysTask = HolidayService.GetHolidaysAsync(_year, _settings.GermanState); + var vacationsTask = TrackerService.GetVacationDaysAsync(_userId, _year); + + await Task.WhenAll(holidaysTask, vacationsTask); + + var holidays = await holidaysTask; + var vacations = await vacationsTask; _holidays = holidays.ToDictionary(h => h.Date, h => h.Name); _vacationSet = vacations.Select(v => v.Date).ToHashSet(); _remainingDays = Math.Max(0, _settings.VacationDaysPerYear - vacations.Count); diff --git a/timetracker.Client/Services/ClientHolidayService.cs b/timetracker.Client/Services/ClientHolidayService.cs index 4acdaf0..742dfd5 100644 --- a/timetracker.Client/Services/ClientHolidayService.cs +++ b/timetracker.Client/Services/ClientHolidayService.cs @@ -6,6 +6,7 @@ namespace timetracker.Client.Services; public class ClientHolidayService : IHolidayService { private readonly HttpClient _http; + private readonly Dictionary<(int Year, string StateCode), List> _holidayCache = new(); public ClientHolidayService(HttpClient http) { @@ -14,12 +15,21 @@ public class ClientHolidayService : IHolidayService public async Task> GetHolidaysAsync(int year, string? stateCode = null) { + var sc = stateCode ?? ""; + var key = (year, sc); + if (_holidayCache.TryGetValue(key, out var cached)) + { + return cached; + } + var url = $"api/holidays?year={year}"; if (!string.IsNullOrEmpty(stateCode)) { url += $"&stateCode={stateCode}"; } - return await _http.GetFromJsonAsync>(url) ?? []; + var result = await _http.GetFromJsonAsync>(url) ?? []; + _holidayCache[key] = result; + return result; } public async Task<(bool Success, string Message)> FetchAndStoreAsync(int year) @@ -30,6 +40,12 @@ public class ClientHolidayService : IHolidayService var result = await response.Content.ReadFromJsonAsync(); if (result != null) { + // Invalidate the cache for this year + var keysToRemove = _holidayCache.Keys.Where(k => k.Year == year).ToList(); + foreach (var k in keysToRemove) + { + _holidayCache.Remove(k); + } return (result.Success, result.Message); } } @@ -39,6 +55,8 @@ public class ClientHolidayService : IHolidayService public async Task DeleteAsync(int id) { await _http.DeleteAsync($"api/holidays/{id}"); + // Invalidate all caches since we deleted a holiday + _holidayCache.Clear(); } private class FetchResponse diff --git a/timetracker.Client/Services/ClientTimetrackerService.cs b/timetracker.Client/Services/ClientTimetrackerService.cs index cd35d5d..f8b5ee5 100644 --- a/timetracker.Client/Services/ClientTimetrackerService.cs +++ b/timetracker.Client/Services/ClientTimetrackerService.cs @@ -6,6 +6,7 @@ namespace timetracker.Client.Services; public class ClientTimetrackerService : ITimetrackerService { private readonly HttpClient _http; + private AppSettings? _cachedSettings; public ClientTimetrackerService(HttpClient http) { @@ -24,12 +25,19 @@ public class ClientTimetrackerService : ITimetrackerService public async Task GetSettingsAsync(int userId) { - return await _http.GetFromJsonAsync($"api/tracker/settings/{userId}") ?? new AppSettings { UserId = userId }; + if (_cachedSettings != null && _cachedSettings.UserId == userId) + { + return _cachedSettings; + } + var settings = await _http.GetFromJsonAsync($"api/tracker/settings/{userId}"); + _cachedSettings = settings ?? new AppSettings { UserId = userId }; + return _cachedSettings; } public async Task SaveSettingsAsync(AppSettings settings) { await _http.PostAsJsonAsync("api/tracker/settings", settings); + _cachedSettings = settings; } public async Task> GetVacationDaysAsync(int userId, int year)