Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type ScoringEngine struct {
Config *config.ConfigSettings
CredentialsMutex map[uint]*sync.Mutex
UptimePerService map[uint]map[string]db.Uptime
uptimeMu sync.RWMutex
SlaPerService map[uint]map[string]int
EnginePauseWg *sync.WaitGroup
IsEnginePaused bool
Expand Down Expand Up @@ -81,9 +82,11 @@ func (se *ScoringEngine) Start() {
se.CurrentRound = uint(t.ID) + 1
}

se.uptimeMu.Lock()
if err := db.LoadUptimes(&se.UptimePerService); err != nil {
slog.Error("failed to load uptimes", "error", err)
}
se.uptimeMu.Unlock()

if err := db.LoadSLAs(&se.SlaPerService, se.Config.MiscSettings.SlaThreshold); err != nil {
slog.Error("failed to load SLAs", "error", err)
Expand Down Expand Up @@ -201,6 +204,14 @@ func (se *ScoringEngine) GetUptimePerService() map[uint]map[string]db.Uptime {
return se.UptimePerService
}

func (se *ScoringEngine) RLockUptime() {
se.uptimeMu.RLock()
}

func (se *ScoringEngine) RUnlockUptime() {
se.uptimeMu.RUnlock()
}

// GetActiveTasks returns all active and recently completed tasks
func (se *ScoringEngine) GetActiveTasks() (map[string]any, error) {
ctx := context.Background()
Expand Down Expand Up @@ -312,7 +323,9 @@ func (se *ScoringEngine) ResetScores() error {
se.RedisClient.Publish(context.Background(), "events", "reset")

se.CurrentRound = 1
se.uptimeMu.Lock()
se.UptimePerService = make(map[uint]map[string]db.Uptime)
se.uptimeMu.Unlock()
se.SlaPerService = make(map[uint]map[string]int)
slog.Info("Scores reset and Redis queues cleared successfully")

Expand Down Expand Up @@ -536,6 +549,7 @@ func (se *ScoringEngine) processCollectedResults(results []checks.Result) {
return
}

se.uptimeMu.Lock()
for _, result := range results {
// Update uptime and SLA maps
if _, ok := se.UptimePerService[result.TeamID]; !ok {
Expand Down Expand Up @@ -575,6 +589,7 @@ func (se *ScoringEngine) processCollectedResults(results []checks.Result) {
}
}
}
se.uptimeMu.Unlock()

slog.Debug("Successfully processed results for round", "round", se.CurrentRound, "total", len(dbResults))

Expand Down
2 changes: 2 additions & 0 deletions www/api/graphs.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func GetUptimeStatus(w http.ResponseWriter, r *http.Request) {
}
teams = slices.DeleteFunc(teams, func(team db.TeamSchema) bool { return !team.Active })

eng.RLockUptime()
uptime := eng.GetUptimePerService()

// TODO: make db unique function or get from config
Expand Down Expand Up @@ -205,6 +206,7 @@ func GetUptimeStatus(w http.ResponseWriter, r *http.Request) {
s.Data = points
series = append(series, s)
}
eng.RUnlockUptime()

if shouldScrub(r) {
for i := range series {
Expand Down
5 changes: 4 additions & 1 deletion www/api/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,19 @@ func GetTeamSummary(w http.ResponseWriter, r *http.Request) {
Uptime float64 `json:"Uptime"`
}

eng.RLockUptime()
uptimeMap := eng.GetUptimePerService()
var s []summary
for _, v := range summaries {
uptime := eng.UptimePerService[teamID][v["ServiceName"].(string)]
uptime := uptimeMap[teamID][v["ServiceName"].(string)]
s = append(s, summary{
ServiceName: v["ServiceName"].(string),
SlaCount: v["SlaCount"].(int),
Last10Rounds: v["Last10Rounds"].([]db.RoundSchema),
Uptime: float64(uptime.PassedChecks) / float64(uptime.TotalChecks),
})
}
eng.RUnlockUptime()

WriteJSON(w, http.StatusOK, s)
}
Expand Down