feat: refactor watchdog
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package watchdog
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"orbits-server/internal/server/bootstrap"
|
||||
"orbits-server/internal/server/database"
|
||||
"orbits-server/internal/shared/utility"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func applyFS(env bootstrap.Environment, db *gorm.DB, fsOrphans []string) {
|
||||
for _, fp := range fsOrphans {
|
||||
|
||||
switch env.WatchdogSyncMode {
|
||||
|
||||
case "sync":
|
||||
f, err := os.Open(fp)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
func() {
|
||||
defer f.Close()
|
||||
|
||||
fileData, err := database.BuildFileRecord(
|
||||
f,
|
||||
filepath.Base(fp),
|
||||
env.ContentDirectory,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
database.CreateFile(db, fileData)
|
||||
os.Rename(fp, fileData.FilePath)
|
||||
}()
|
||||
|
||||
case "strict":
|
||||
utility.RemoveFile(fp)
|
||||
|
||||
case "dry":
|
||||
slog.Debug("dry mode", "file", fp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyDB(db *gorm.DB, dbOrphans []database.File) {
|
||||
for _, f := range dbOrphans {
|
||||
err := database.DeleteFileByID(db, f.ID)
|
||||
if err != nil {
|
||||
slog.Error("failed to apply database measures", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package watchdog
|
||||
|
||||
import (
|
||||
"orbits-server/internal/server/bootstrap"
|
||||
"orbits-server/internal/server/database"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func reconcile(fs map[string]struct{}, db map[string]database.File) Result {
|
||||
r := Result{}
|
||||
|
||||
for path := range fs {
|
||||
if _, ok := db[path]; !ok {
|
||||
r.FSOrphans = append(r.FSOrphans, path)
|
||||
}
|
||||
}
|
||||
|
||||
for path, f := range db {
|
||||
if _, ok := fs[path]; !ok {
|
||||
r.DBOrphans = append(r.DBOrphans, f)
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func scanFS(env bootstrap.Environment) (map[string]struct{}, error) {
|
||||
fsFiles, err := os.ReadDir(env.ContentDirectory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make(map[string]struct{})
|
||||
for _, f := range fsFiles {
|
||||
full := filepath.Join(env.ContentDirectory, f.Name())
|
||||
res[full] = struct{}{}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func scanDB(db *gorm.DB) (map[string]database.File, error) {
|
||||
files, err := database.ListFiles(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make(map[string]database.File)
|
||||
for _, f := range files {
|
||||
res[f.FilePath] = f
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
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)
|
||||
|
||||
for range ticker.C {
|
||||
run(env, db)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func run(env bootstrap.Environment, db *gorm.DB) {
|
||||
slog.Debug("watchdog cycle start")
|
||||
|
||||
fsState, err := scanFS(env)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dbState, err := scanDB(db)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user