From ddc7206a73a39041ad2933204c1e8de57cac9bdf Mon Sep 17 00:00:00 2001 From: Tomi Eckert Date: Thu, 15 Jan 2026 20:03:45 +0100 Subject: [PATCH] optim(redmine): hour stats are also improved --- Blueberry.Redmine/RedmineApiClient.cs | 41 ++++++++++++++++++--------- Blueberry/Blueberry.csproj | 2 +- Blueberry/HoursWindow.xaml.cs | 13 +++++++-- Blueberry/UpdateManager.cs | 2 +- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Blueberry.Redmine/RedmineApiClient.cs b/Blueberry.Redmine/RedmineApiClient.cs index 1350621..21ead09 100644 --- a/Blueberry.Redmine/RedmineApiClient.cs +++ b/Blueberry.Redmine/RedmineApiClient.cs @@ -1,6 +1,7 @@ using Blueberry.Redmine.Dto; using Microsoft.Extensions.Logging; using System.ComponentModel.DataAnnotations; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; @@ -118,11 +119,14 @@ namespace Blueberry.Redmine private async Task> SendRequestWithPagingAsync(HttpMethod method, string endpoint, int limit, Func> itemParser, IProgress<(int current, int total)>? progress = null, object? payload = null, CancellationToken? token = null) where TResponse : IResponseList { + var sw = new Stopwatch(); + sw.Start(); + var offset = 0; List returnList = []; - _logger.LogDebug("Starting paged request to {Endpoint} with limit {Limit}", endpoint, limit); + _logger.LogDebug("Starting paged request to {Endpoint} with limit {Limit}", endpoint.Split('?')[0], limit); var path = ""; if (endpoint.Contains('?')) @@ -131,7 +135,7 @@ namespace Blueberry.Redmine path = $"{endpoint}?limit={limit}&offset={offset}"; var responseList = await SendRequestAsync(HttpMethod.Get, path, token: token) - ?? throw new NullReferenceException(); + ?? throw new NullReferenceException(); var total = responseList.TotalCount; @@ -140,16 +144,20 @@ namespace Blueberry.Redmine offset += limit; if (offset >= responseList.TotalCount) + { + _logger.LogDebug(" + Single request retrieved all {TotalItems} items", returnList.Count); return returnList; + } var remain = total - offset; var tasks = new Task[(int)Math.Ceiling((double)remain / limit)]; - _logger.LogDebug("Spawning {TaskCount} tasks for remaining {Remaining} items out of {Total}", tasks.Length, remain, total); - List<(int id, IEnumerable items)> responses = []; + var preparationTime = sw.ElapsedMilliseconds; + sw.Restart(); + for (int i = 0; i < tasks.Length; i++) { var id = i; @@ -178,25 +186,32 @@ namespace Blueberry.Redmine progress.Report((current, tasks.Length)); } - var completed = tasks.Count(t => t.IsCompleted); - _logger.LogDebug("{Completed}/{Total} tasks completed", completed, tasks.Length); await Task.Delay(250); } await Task.WhenAll(tasks); - await Task.Delay(100); - - var notCompleted = tasks.Where(t => !t.IsCompletedSuccessfully).ToList(); - _logger.LogDebug("{NotCompleted} tasks did not complete successfully", notCompleted.Count); - - _logger.LogDebug("All tasks completed, aggregating {total} results from {count} responses", responses.Select(x=>x.items).Count(), responses.Count); + await Task.Delay(50); + var executionTime = sw.ElapsedMilliseconds; + sw.Restart(); foreach (var resp in responses.OrderBy(x => x.id)) { returnList.AddRange(resp.items); } - _logger.LogDebug("Aggregated total of {TotalItems} items", returnList.Count); + _logger.LogDebug(" + Aggregated total of {TotalItems} items from {Count} responses", returnList.Count, responses.Count); + + var aggregationTime = sw.ElapsedMilliseconds; + sw.Stop(); + + // log times + _logger.LogDebug(" + Paging completed in:\n Preparation: {Preparation}ms\n Execution: {Execution}ms\n Aggregation: {Aggregation}ms\n Total: {Total}ms" + , preparationTime, executionTime, aggregationTime, preparationTime + executionTime + aggregationTime); + + // log avarege time per task and per item, round them to whole ms + _logger.LogDebug(" + Average time per task: {AvgTask}ms, Average time per item: {AvgItem}ms", + Math.Round((double)(preparationTime + executionTime) / tasks.Length + 1), + Math.Round((double)(executionTime) / returnList.Count)); return returnList; } diff --git a/Blueberry/Blueberry.csproj b/Blueberry/Blueberry.csproj index 817ab66..6018944 100644 --- a/Blueberry/Blueberry.csproj +++ b/Blueberry/Blueberry.csproj @@ -1,7 +1,7 @@  - WinExe + Exe net8.0-windows10.0.17763.0 enable enable diff --git a/Blueberry/HoursWindow.xaml.cs b/Blueberry/HoursWindow.xaml.cs index a5e0b31..9e7cd0d 100644 --- a/Blueberry/HoursWindow.xaml.cs +++ b/Blueberry/HoursWindow.xaml.cs @@ -3,6 +3,7 @@ using Blueberry.Redmine.Dto; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Windows; using Wpf.Ui.Controls; using static System.Runtime.InteropServices.JavaScript.JSType; @@ -120,6 +121,10 @@ namespace Blueberry var firstDate = userCalendar.SelectedDates.First(); var lastDate = userCalendar.SelectedDates.Last(); + var newTicketTask = _manager.GetIssuesAsync(user.Id, createdFrom: selectedDates.First(), createdTo: selectedDates.Last()); + var closedTicketTask = _manager.GetIssuesAsync(user.Id, isOpen: false, updatedFrom: selectedDates.First(), updatedTo: selectedDates.Last()); + var currentTicketTask = _manager.GetUserOpenIssuesAsync(user.Id); + var h = await _manager.GetTimeForUserAsync(user.Id, firstDate, lastDate); var list = new List(); @@ -178,9 +183,11 @@ namespace Blueberry foreach (var item in orderedHours) Hours.Add(item); - var newTickets = await _manager.GetIssuesAsync(user.Id, createdFrom: selectedDates.First(), createdTo: selectedDates.Last()); - var closedTickets = await _manager.GetIssuesAsync(user.Id, isOpen: false, updatedFrom: selectedDates.First(), updatedTo: selectedDates.Last()); - var currentTickets = await _manager.GetUserOpenIssuesAsync(user.Id); + await Task.WhenAll(newTicketTask, closedTicketTask, currentTicketTask); + + var newTickets = newTicketTask.Result; + var closedTickets = closedTicketTask.Result; + var currentTickets = currentTicketTask.Result; var total = hours.Sum(x => double.Parse(x.Hours)); totalHoursTextBlock.Text = total.ToString(); diff --git a/Blueberry/UpdateManager.cs b/Blueberry/UpdateManager.cs index cf04fb5..6528f3c 100644 --- a/Blueberry/UpdateManager.cs +++ b/Blueberry/UpdateManager.cs @@ -8,7 +8,7 @@ namespace Blueberry public static class UpdateManager { private const string releaseUrl = "https://git.technopunk.space/api/v1/repos/tomi/Blueberry/releases/latest"; - public const string CurrentVersion = "0.2.5"; + public const string CurrentVersion = "0.2.6"; private static readonly string appDir = AppDomain.CurrentDomain.BaseDirectory; private static readonly string zipPath = Path.Combine(appDir, "blueberry_update.zip"); private static readonly HttpClient client = new();