From 2d2ac093e8fa7b948cecac3613cf21aac6829e77 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Mon, 23 Mar 2026 18:58:39 -0400 Subject: [PATCH 1/2] Fix wait stats cleanup: tab indentation and CancellationToken leak - Replace tab indentation with spaces in FetchPlanWaitStatsAsync doc comments to match file convention - Rewrite doc comment for clarity (explain why plan-level WTR differs) - Use existing _fetchCts instead of creating untracked CancellationTokenSource in OnWaitStatsCollapsedChanged Follow-up to PR #137. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Controls/QueryStoreGridControl.axaml.cs | 6 +++--- src/PlanViewer.Core/Services/QueryStoreService.cs | 15 +++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/PlanViewer.App/Controls/QueryStoreGridControl.axaml.cs b/src/PlanViewer.App/Controls/QueryStoreGridControl.axaml.cs index 1769992..077c394 100644 --- a/src/PlanViewer.App/Controls/QueryStoreGridControl.axaml.cs +++ b/src/PlanViewer.App/Controls/QueryStoreGridControl.axaml.cs @@ -462,9 +462,9 @@ private void OnWaitStatsCollapsedChanged(object? sender, bool collapsed) if (!collapsed && _slicerStartUtc.HasValue && _slicerEndUtc.HasValue) { - // Re-fetch wait stats when expanding - var cts = new CancellationTokenSource(); - _ = FetchWaitStatsAsync(_slicerStartUtc.Value, _slicerEndUtc.Value, cts.Token); + // Re-fetch wait stats when expanding — reuse the shared CTS + var ct = _fetchCts?.Token ?? CancellationToken.None; + _ = FetchWaitStatsAsync(_slicerStartUtc.Value, _slicerEndUtc.Value, ct); } } diff --git a/src/PlanViewer.Core/Services/QueryStoreService.cs b/src/PlanViewer.Core/Services/QueryStoreService.cs index dec2e83..aeb78f5 100644 --- a/src/PlanViewer.Core/Services/QueryStoreService.cs +++ b/src/PlanViewer.Core/Services/QueryStoreService.cs @@ -473,14 +473,13 @@ JOIN sys.query_store_runtime_stats_interval rsi return rows; } - /// - /// Per-plan wait stats aggregated for a time range, grouped by plan_id + category. - /// WaitRatio = SUM(total_query_wait_time_ms) / sum(rs.avg_duration*rs.count_executions) - /// ==> May be challenged. But at the detail level we use the plan duration use query stats. - /// So it is different from the other wait ratio calculation, which is based on the interval duration. - /// We can consider to align them in the future if needed. - /// - public static async Task> FetchPlanWaitStatsAsync( + /// + /// Per-plan wait stats aggregated for a time range, grouped by plan_id + category. + /// WaitRatio = SUM(total_query_wait_time_ms) / SUM(avg_duration * count_executions). + /// This differs from the global/hourly WTR (which divides by wall-clock interval) because + /// at plan level we measure what fraction of actual execution time was spent waiting. + /// + public static async Task> FetchPlanWaitStatsAsync( string connectionString, DateTime startUtc, DateTime endUtc, CancellationToken ct = default) { From 2d8c595a78062461f720d06ab7f734ccfc554f34 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Tue, 24 Mar 2026 22:32:45 -0400 Subject: [PATCH 2/2] Fix SkiaSharp native library version mismatch on Linux (#139) Avalonia.Skia 11.3.12 transitively pulls SkiaSharp.NativeAssets.Linux 2.88.9 (libSkiaSharp.so v88.1), but the managed SkiaSharp 3.119.0 requires native libs in the [119.0, 120.0) range. At publish time the old .so overwrites the correct one, causing a TypeInitializationException on startup. Pin SkiaSharp.NativeAssets.Linux to 3.119.0 so NuGet resolution picks the correct native library. macOS and Win32 were already at 3.119.0. Fixes #139 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/PlanViewer.App/PlanViewer.App.csproj | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/PlanViewer.App/PlanViewer.App.csproj b/src/PlanViewer.App/PlanViewer.App.csproj index 54f8908..689e095 100644 --- a/src/PlanViewer.App/PlanViewer.App.csproj +++ b/src/PlanViewer.App/PlanViewer.App.csproj @@ -33,6 +33,13 @@ + + +