Files
nodemaster/models/progress.go
T
2026-07-27 14:41:04 +02:00

60 lines
1.6 KiB
Go

package models
import (
"strings"
"sync"
"time"
)
// RunState is the in-memory, non-persisted status of a backup target's current
// or most recent run. It intentionally lives outside cfg/persist(): a crash or
// restart should never leave a stale "still running" flag behind.
type RunState struct {
Running bool `json:"running"`
TargetID string `json:"target_id"`
Method BackupMethod `json:"method,omitempty"`
Percent float64 `json:"percent"`
ETA string `json:"eta,omitempty"`
Message string `json:"message,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
}
var (
progressMu sync.RWMutex
progress = map[string]RunState{}
)
// progressKey builds the scoped key a target's run state is stored under.
// scope is "node" or "svc:<serviceID>".
func progressKey(scope, targetID string) string {
return scope + ":" + targetID
}
func setProgress(key string, s RunState) {
progressMu.Lock()
defer progressMu.Unlock()
progress[key] = s
}
// GetProgress returns the current run state for a single target, if any is known.
func GetProgress(scope, targetID string) (RunState, bool) {
progressMu.RLock()
defer progressMu.RUnlock()
s, ok := progress[progressKey(scope, targetID)]
return s, ok
}
// GetProgressForScope returns all known run states for a scope ("node" or "svc:<id>").
func GetProgressForScope(scope string) []RunState {
prefix := scope + ":"
progressMu.RLock()
defer progressMu.RUnlock()
result := make([]RunState, 0)
for k, s := range progress {
if strings.HasPrefix(k, prefix) {
result = append(result, s)
}
}
return result
}