Pulse/internal/alerts/history_concurrency_test.go
2025-10-11 23:29:47 +00:00

86 lines
1.6 KiB
Go

package alerts
import (
"fmt"
"os"
"path/filepath"
"sync"
"testing"
"time"
"github.com/rs/zerolog"
)
func TestHistoryManagerConcurrentAccess(t *testing.T) {
origLevel := zerolog.GlobalLevel()
zerolog.SetGlobalLevel(zerolog.Disabled)
defer zerolog.SetGlobalLevel(origLevel)
tempDir := t.TempDir()
hm := &HistoryManager{
dataDir: tempDir,
historyFile: filepath.Join(tempDir, HistoryFileName),
backupFile: filepath.Join(tempDir, HistoryBackupFileName),
history: make([]HistoryEntry, 0),
saveInterval: 50 * time.Millisecond,
stopChan: make(chan struct{}),
}
// Start periodic save and cleanup routines
hm.startPeriodicSave()
go hm.cleanupRoutine()
const iterations = 500
var wg sync.WaitGroup
wg.Add(4)
go func() {
defer wg.Done()
for i := 0; i < iterations; i++ {
hm.AddAlert(Alert{
ID: fmt.Sprintf("alert-%d", i),
Type: "test",
Level: AlertLevelWarning,
Message: "test alert",
StartTime: time.Now(),
})
}
}()
go func() {
defer wg.Done()
for i := 0; i < iterations; i++ {
hm.GetHistory(time.Now().Add(-1*time.Hour), 100)
hm.GetAllHistory(100)
}
}()
go func() {
defer wg.Done()
for i := 0; i < iterations; i++ {
hm.RemoveAlert(fmt.Sprintf("alert-%d", i))
time.Sleep(1 * time.Millisecond)
}
}()
go func() {
defer wg.Done()
for i := 0; i < iterations/10; i++ {
_ = hm.ClearAllHistory()
time.Sleep(5 * time.Millisecond)
}
}()
wg.Wait()
close(hm.stopChan)
if hm.saveTicker != nil {
hm.saveTicker.Stop()
}
// give final save a chance
time.Sleep(20 * time.Millisecond)
_ = os.RemoveAll(tempDir)
}