80 lines
1.4 KiB
Go
80 lines
1.4 KiB
Go
package watchdog
|
|
|
|
import (
|
|
"log/slog"
|
|
"orbits-server/internal/server/bootstrap"
|
|
"orbits-server/internal/server/database"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type State struct {
|
|
FS map[string]struct{}
|
|
DB map[string]database.File
|
|
}
|
|
|
|
type Result struct {
|
|
FSOrphans []string
|
|
DBOrphans []database.File
|
|
}
|
|
|
|
func Kickoff(env bootstrap.Environment, db *gorm.DB) {
|
|
interval := time.Second * time.Duration(env.WatchdogInterval)
|
|
ticker := time.NewTicker(interval)
|
|
|
|
go func() {
|
|
defer ticker.Stop()
|
|
|
|
run(env, db)
|
|
|
|
running := false
|
|
for range ticker.C {
|
|
if running {
|
|
slog.Warn("watchdog is still running, skipping tick")
|
|
continue
|
|
}
|
|
|
|
running = true
|
|
|
|
func() {
|
|
defer func() { running = false }()
|
|
run(env, db)
|
|
}()
|
|
}
|
|
}()
|
|
}
|
|
|
|
// the watchdog has 2 tasks
|
|
// 1 revoke expires keys
|
|
// 2 remove / sync orphaned files/db records
|
|
func run(env bootstrap.Environment, db *gorm.DB) {
|
|
slog.Debug("watchdog cycle start")
|
|
|
|
revokeExpired(db)
|
|
|
|
fsState, err := scanFS(env)
|
|
if err != nil {
|
|
slog.Error("scanFS failed", "error", err)
|
|
return
|
|
}
|
|
|
|
dbState, err := scanDB(db)
|
|
if err != nil {
|
|
slog.Error("scanDB failed", "error", err)
|
|
return
|
|
}
|
|
|
|
result := reconcile(fsState, dbState)
|
|
|
|
if len(result.FSOrphans) > 0 {
|
|
slog.Info("filesystem orphans detected")
|
|
applyFS(env, db, result.FSOrphans)
|
|
}
|
|
|
|
if len(result.DBOrphans) > 0 {
|
|
slog.Info("database orphans detected")
|
|
applyDB(db, result.DBOrphans)
|
|
}
|
|
}
|