Add repair worker
This commit is contained in:
72
pkg/repair/repair.go
Normal file
72
pkg/repair/repair.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package repair
|
||||
|
||||
import (
|
||||
"context"
|
||||
"goBlack/common"
|
||||
"goBlack/pkg/arr"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Start(ctx context.Context, config *common.Config, arrs *arr.Storage) error {
|
||||
ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
|
||||
logger := common.NewLogger("Repair", os.Stdout)
|
||||
defer stop()
|
||||
|
||||
duration, err := parseSchedule(config.Repair.Interval)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse schedule: %v", err)
|
||||
}
|
||||
|
||||
if config.Repair.RunOnStart {
|
||||
logger.Printf("Running initial repair")
|
||||
if err := repair(arrs); err != nil {
|
||||
log.Printf("Error during initial repair: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(duration)
|
||||
defer ticker.Stop()
|
||||
|
||||
if strings.Contains(config.Repair.Interval, ":") {
|
||||
logger.Printf("Starting repair worker, scheduled daily at %s", config.Repair.Interval)
|
||||
} else {
|
||||
logger.Printf("Starting repair worker with %v interval", duration)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
logger.Println("Repair worker stopped")
|
||||
return nil
|
||||
case t := <-ticker.C:
|
||||
logger.Printf("Running repair at %v", t.Format("15:04:05"))
|
||||
if err := repair(arrs); err != nil {
|
||||
logger.Printf("Error during repair: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// If using time-of-day schedule, reset the ticker for next day
|
||||
if strings.Contains(config.Repair.Interval, ":") {
|
||||
nextDuration, err := parseSchedule(config.Repair.Interval)
|
||||
if err != nil {
|
||||
logger.Printf("Error calculating next schedule: %v", err)
|
||||
return err
|
||||
}
|
||||
ticker.Reset(nextDuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func repair(arrs *arr.Storage) error {
|
||||
for _, a := range arrs.GetAll() {
|
||||
go a.Repair("")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
70
pkg/repair/utils.go
Normal file
70
pkg/repair/utils.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package repair
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func parseSchedule(schedule string) (time.Duration, error) {
|
||||
if schedule == "" {
|
||||
return time.Hour, nil // default 60m
|
||||
}
|
||||
|
||||
// Check if it's a time-of-day format (HH:MM)
|
||||
if strings.Contains(schedule, ":") {
|
||||
return parseTimeOfDay(schedule)
|
||||
}
|
||||
|
||||
// Otherwise treat as duration interval
|
||||
return parseDurationInterval(schedule)
|
||||
}
|
||||
|
||||
func parseTimeOfDay(schedule string) (time.Duration, error) {
|
||||
now := time.Now()
|
||||
scheduledTime, err := time.Parse("15:04", schedule)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid time format: %s. Use HH:MM in 24-hour format", schedule)
|
||||
}
|
||||
|
||||
// Convert scheduled time to today
|
||||
scheduleToday := time.Date(
|
||||
now.Year(), now.Month(), now.Day(),
|
||||
scheduledTime.Hour(), scheduledTime.Minute(), 0, 0,
|
||||
now.Location(),
|
||||
)
|
||||
|
||||
if scheduleToday.Before(now) {
|
||||
scheduleToday = scheduleToday.Add(24 * time.Hour)
|
||||
}
|
||||
|
||||
return scheduleToday.Sub(now), nil
|
||||
}
|
||||
|
||||
func parseDurationInterval(interval string) (time.Duration, error) {
|
||||
if len(interval) < 2 {
|
||||
return 0, fmt.Errorf("invalid interval format: %s", interval)
|
||||
}
|
||||
|
||||
numStr := interval[:len(interval)-1]
|
||||
unit := interval[len(interval)-1]
|
||||
|
||||
num, err := strconv.Atoi(numStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid number in interval: %s", numStr)
|
||||
}
|
||||
|
||||
switch unit {
|
||||
case 'm':
|
||||
return time.Duration(num) * time.Minute, nil
|
||||
case 'h':
|
||||
return time.Duration(num) * time.Hour, nil
|
||||
case 'd':
|
||||
return time.Duration(num) * 24 * time.Hour, nil
|
||||
case 's':
|
||||
return time.Duration(num) * time.Second, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid unit in interval: %c", unit)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user