diff --git a/Dashboard/MainWindow.xaml.cs b/Dashboard/MainWindow.xaml.cs index 3cd34e2f..2c093a3c 100644 --- a/Dashboard/MainWindow.xaml.cs +++ b/Dashboard/MainWindow.xaml.cs @@ -902,7 +902,7 @@ public void UpdateAllTabBadges(Dictionary healthData /// Updates a server tab badge from AlertHealthResult (used by the alert engine). /// Constructs a minimal ServerHealthStatus for the badge evaluation. /// - private void UpdateTabBadgeFromAlertHealth(string serverId, AlertHealthResult health) + private void UpdateTabBadgeFromAlertHealth(string serverId, AlertHealthResult health, long prevDeadlockCount) { if (!_tabBadges.ContainsKey(serverId)) return; @@ -920,14 +920,22 @@ private void UpdateTabBadgeFromAlertHealth(string serverId, AlertHealthResult he }; /* Set deadlock count twice to generate a delta. - First set establishes baseline (delta=0), second set creates actual delta. */ - if (_previousDeadlockCounts.TryGetValue(serverId, out var prevDlCount)) - { - status.DeadlockCount = prevDlCount; - status.DeadlockCount = health.DeadlockCount; - } + First set establishes baseline (delta=0), second set creates actual delta. + Uses the previous count captured BEFORE EvaluateAlertConditionsAsync updated it. */ + status.DeadlockCount = prevDeadlockCount; + status.DeadlockCount = health.DeadlockCount; UpdateTabBadge(serverId, status); + + /* Also update sub-tab badges (Locking, Memory, Resource Metrics) in open ServerTab instances */ + foreach (var tabItem in ServerTabControl.Items.OfType()) + { + if (tabItem.Content is ServerTab serverTab && serverTab.ServerId == serverId) + { + serverTab.UpdateBadges(status, _alertStateService); + break; + } + } } #region Independent Alert Engine @@ -982,11 +990,15 @@ private async Task CheckAllServerAlertsAsync() if (health.IsOnline) { + /* Capture previous deadlock count BEFORE EvaluateAlertConditionsAsync updates it, + so the badge delta calculation sees the correct baseline. */ + var prevDeadlockCount = _previousDeadlockCounts.TryGetValue(server.Id, out var pdc) ? pdc : 0; + await EvaluateAlertConditionsAsync(server.Id, server.DisplayName, health, databaseService); /* Update tab badges from alert health data. This ensures badges update even when the NOC view isn't active. */ - await Dispatcher.InvokeAsync(() => UpdateTabBadgeFromAlertHealth(server.Id, health)); + await Dispatcher.InvokeAsync(() => UpdateTabBadgeFromAlertHealth(server.Id, health, prevDeadlockCount)); } } catch (Exception ex) diff --git a/Lite/Database/DuckDbInitializer.cs b/Lite/Database/DuckDbInitializer.cs index 53b56aa3..809fb1ea 100644 --- a/Lite/Database/DuckDbInitializer.cs +++ b/Lite/Database/DuckDbInitializer.cs @@ -320,7 +320,8 @@ Safe to ALTER because this table uses INSERT (not appender). */ _logger?.LogInformation("Running migration to v9: adding dismissed column to config_alert_log"); try { - await ExecuteNonQueryAsync(connection, "ALTER TABLE config_alert_log ADD COLUMN IF NOT EXISTS dismissed BOOLEAN NOT NULL DEFAULT false"); + /* DuckDB does not support ADD COLUMN with NOT NULL — use nullable with DEFAULT */ + await ExecuteNonQueryAsync(connection, "ALTER TABLE config_alert_log ADD COLUMN IF NOT EXISTS dismissed BOOLEAN DEFAULT false"); } catch {