Skip to content

Persist the Lite alert email cooldown across restarts (#981)#986

Merged
erikdarlingdata merged 1 commit into
devfrom
feature/981-alert-cooldown-persist
May 22, 2026
Merged

Persist the Lite alert email cooldown across restarts (#981)#986
erikdarlingdata merged 1 commit into
devfrom
feature/981-alert-cooldown-persist

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Problem

Split out from #976. The reporter saw the same alerts pop up several times, hours after the originating event.

EmailAlertService deduplicated alert emails with an in-memory ConcurrentDictionary<string, DateTime> cooldown keyed {serverId}:{metricName}. It was never persisted, so restarting Lite cleared every cooldown — an alert email sent minutes before the restart could be sent again immediately after.

Change

The first time each alert key is evaluated, the cooldown is seeded from config_alert_log via the new GetLastEmailSentUtcAsync — the most recent alert_time for that server/metric where an email actually succeeded (notification_type IN ('email','email+webhook') AND send_error IS NULL, which is exactly when _cooldowns is updated after SendEmailAsync). The in-memory dictionary stays authoritative once seeded, so it's one small read per key per app session.

Test plan

  • dotnet build Lite/PerformanceMonitorLite.csproj -c Debug — full rebuild, 0 warnings, 0 errors.
  • The cooldown query was run against DuckDB with representative config_alert_log rows: it correctly returns the most recent successful email send, excluding a later row with a send_error (failed send) and a tray-only row, and returns null when there's no history for the key.
  • Column names verified against the config_alert_log INSERT in LogAlertAsync.

🤖 Generated with Claude Code

EmailAlertService deduplicated alert emails with an in-memory
ConcurrentDictionary cooldown keyed {serverId}:{metricName}. It was
never persisted, so restarting Lite cleared every cooldown and an alert
email sent minutes before the restart could be sent again immediately.

The first time each alert key is evaluated, the cooldown is now seeded
from config_alert_log via GetLastEmailSentUtcAsync - the most recent
alert_time for that server/metric where an email actually succeeded
(notification_type IN ('email','email+webhook') AND send_error IS NULL,
mirroring exactly when _cooldowns is updated after SendEmailAsync). The
in-memory dictionary stays authoritative once seeded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit ecf9318 into dev May 22, 2026
2 checks passed
@erikdarlingdata erikdarlingdata deleted the feature/981-alert-cooldown-persist branch May 22, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant