|
|
|
|
| package alerts_test
|
|
|
| import (
|
| "testing"
|
|
|
| "github.com/henrygd/beszel/internal/alerts"
|
| beszelTests "github.com/henrygd/beszel/internal/tests"
|
| "github.com/stretchr/testify/assert"
|
| "github.com/stretchr/testify/require"
|
| )
|
|
|
| func TestSystemAlertsCachePopulateAndFilter(t *testing.T) {
|
| hub, user := beszelTests.GetHubWithUser(t)
|
| defer hub.Cleanup()
|
|
|
| systems, err := beszelTests.CreateSystems(hub, 2, user.Id, "up")
|
| require.NoError(t, err)
|
| system1 := systems[0]
|
| system2 := systems[1]
|
|
|
| statusAlert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "Status",
|
| "system": system1.Id,
|
| "user": user.Id,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| cpuAlert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "CPU",
|
| "system": system1.Id,
|
| "user": user.Id,
|
| "value": 80,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| memoryAlert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "Memory",
|
| "system": system2.Id,
|
| "user": user.Id,
|
| "value": 90,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| cache := alerts.NewAlertsCache(hub)
|
| cache.PopulateFromDB(false)
|
|
|
| statusAlerts := cache.GetAlertsByName(system1.Id, "Status")
|
| require.Len(t, statusAlerts, 1)
|
| assert.Equal(t, statusAlert.Id, statusAlerts[0].Id)
|
|
|
| nonStatusAlerts := cache.GetAlertsExcludingNames(system1.Id, "Status")
|
| require.Len(t, nonStatusAlerts, 1)
|
| assert.Equal(t, cpuAlert.Id, nonStatusAlerts[0].Id)
|
|
|
| system2Alerts := cache.GetSystemAlerts(system2.Id)
|
| require.Len(t, system2Alerts, 1)
|
| assert.Equal(t, memoryAlert.Id, system2Alerts[0].Id)
|
| }
|
|
|
| func TestSystemAlertsCacheLazyLoadUpdateAndDelete(t *testing.T) {
|
| hub, user := beszelTests.GetHubWithUser(t)
|
| defer hub.Cleanup()
|
|
|
| systems, err := beszelTests.CreateSystems(hub, 1, user.Id, "up")
|
| require.NoError(t, err)
|
| systemRecord := systems[0]
|
|
|
| statusAlert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "Status",
|
| "system": systemRecord.Id,
|
| "user": user.Id,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| cache := alerts.NewAlertsCache(hub)
|
| require.Len(t, cache.GetSystemAlerts(systemRecord.Id), 1, "first lookup should lazy-load alerts for the system")
|
|
|
| cpuAlert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "CPU",
|
| "system": systemRecord.Id,
|
| "user": user.Id,
|
| "value": 80,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| cache.Update(cpuAlert)
|
|
|
| nonStatusAlerts := cache.GetAlertsExcludingNames(systemRecord.Id, "Status")
|
| require.Len(t, nonStatusAlerts, 1)
|
| assert.Equal(t, cpuAlert.Id, nonStatusAlerts[0].Id)
|
|
|
| cache.Delete(statusAlert)
|
| assert.Empty(t, cache.GetAlertsByName(systemRecord.Id, "Status"), "deleted alerts should be removed from the in-memory cache")
|
| }
|
|
|
| func TestSystemAlertsCacheRefreshReturnsLatestCopy(t *testing.T) {
|
| hub, user := beszelTests.GetHubWithUser(t)
|
| defer hub.Cleanup()
|
|
|
| systems, err := beszelTests.CreateSystems(hub, 1, user.Id, "up")
|
| require.NoError(t, err)
|
| system := systems[0]
|
|
|
| alert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "Status",
|
| "system": system.Id,
|
| "user": user.Id,
|
| "min": 1,
|
| "triggered": false,
|
| })
|
| require.NoError(t, err)
|
|
|
| cache := alerts.NewAlertsCache(hub)
|
| snapshot := cache.GetSystemAlerts(system.Id)[0]
|
| assert.False(t, snapshot.Triggered)
|
|
|
| alert.Set("triggered", true)
|
| require.NoError(t, hub.Save(alert))
|
|
|
| refreshed, ok := cache.Refresh(snapshot)
|
| require.True(t, ok)
|
| assert.Equal(t, snapshot.Id, refreshed.Id)
|
| assert.True(t, refreshed.Triggered, "refresh should return the updated cached value rather than the stale snapshot")
|
|
|
| require.NoError(t, hub.Delete(alert))
|
| _, ok = cache.Refresh(snapshot)
|
| assert.False(t, ok, "refresh should report false when the cached alert no longer exists")
|
| }
|
|
|
| func TestAlertManagerCacheLifecycle(t *testing.T) {
|
| hub, user := beszelTests.GetHubWithUser(t)
|
| defer hub.Cleanup()
|
|
|
| systems, err := beszelTests.CreateSystems(hub, 1, user.Id, "up")
|
| require.NoError(t, err)
|
| system := systems[0]
|
|
|
|
|
| alert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
|
| "name": "CPU",
|
| "system": system.Id,
|
| "user": user.Id,
|
| "value": 80,
|
| "min": 1,
|
| })
|
| require.NoError(t, err)
|
|
|
| am := hub.AlertManager
|
| cache := am.GetSystemAlertsCache()
|
|
|
|
|
| assert.Len(t, cache.GetSystemAlerts(system.Id), 1)
|
| assert.Equal(t, alert.Id, cache.GetSystemAlerts(system.Id)[0].Id)
|
| assert.EqualValues(t, 80, cache.GetSystemAlerts(system.Id)[0].Value)
|
|
|
|
|
| alert.Set("value", 85)
|
| require.NoError(t, hub.Save(alert))
|
|
|
|
|
| cachedAlerts := cache.GetSystemAlerts(system.Id)
|
| assert.Len(t, cachedAlerts, 1)
|
| assert.EqualValues(t, 85, cachedAlerts[0].Value)
|
|
|
|
|
| require.NoError(t, hub.Delete(alert))
|
|
|
|
|
| assert.Empty(t, cache.GetSystemAlerts(system.Id), "alert should be removed from cache after PocketBase delete")
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|