82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package jobs
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"stock-user-system/internal/config"
|
|
"stock-user-system/internal/services"
|
|
)
|
|
|
|
var chinaLoc, _ = time.LoadLocation("Asia/Shanghai")
|
|
|
|
// StartStockSyncScheduler 启动盘后数据同步调度器。
|
|
func StartStockSyncScheduler(cfg *config.Config, svc *services.StockSyncService) {
|
|
if !cfg.DataSyncEnabled {
|
|
log.Println("stock sync scheduler disabled")
|
|
return
|
|
}
|
|
|
|
hour, minute, err := parseSyncTime(cfg.DataSyncTime)
|
|
if err != nil {
|
|
log.Printf("invalid DATA_SYNC_TIME %q, scheduler not started: %v", cfg.DataSyncTime, err)
|
|
return
|
|
}
|
|
|
|
go func() {
|
|
for {
|
|
next := nextSyncTime(hour, minute, cfg.DataSyncWeekdays)
|
|
wait := time.Until(next)
|
|
log.Printf("next stock sync scheduled at %s (in %v)", next.Format(time.RFC3339), wait)
|
|
time.Sleep(wait)
|
|
|
|
if _, err := svc.Sync(context.Background(), "schedule"); err != nil {
|
|
log.Printf("scheduled stock sync failed: %v", err)
|
|
} else {
|
|
log.Println("scheduled stock sync completed")
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func parseSyncTime(s string) (int, int, error) {
|
|
parts := strings.Split(s, ":")
|
|
if len(parts) != 2 {
|
|
return 0, 0, fmt.Errorf("expected HH:MM")
|
|
}
|
|
h, err := strconv.Atoi(parts[0])
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
m, err := strconv.Atoi(parts[1])
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
if h < 0 || h > 23 || m < 0 || m > 59 {
|
|
return 0, 0, fmt.Errorf("invalid time")
|
|
}
|
|
return h, m, nil
|
|
}
|
|
|
|
func nextSyncTime(hour, minute int, weekdaysOnly bool) time.Time {
|
|
now := time.Now().In(chinaLoc)
|
|
today := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, chinaLoc)
|
|
|
|
candidate := today
|
|
if now.Equal(candidate) || now.After(candidate) {
|
|
candidate = candidate.Add(24 * time.Hour)
|
|
}
|
|
|
|
if weekdaysOnly {
|
|
for candidate.Weekday() == time.Saturday || candidate.Weekday() == time.Sunday {
|
|
candidate = candidate.Add(24 * time.Hour)
|
|
}
|
|
}
|
|
|
|
return candidate
|
|
}
|