feat: 离线License批量删除;同步循环加固(启动即跑/pending自动握手/防重入/panic恢复,移至main启动);同步时间显示到秒

This commit is contained in:
Logan.Li committed 2026-09-14 22:08:43 +08:00
1 parent 30b87dec62
commit 252ae14aef
5 files changed
+79 -11

No files matched your search

+31 -5
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"log"
"sync/atomic"
"time"
"backend/internal/dto"
@@ -194,24 +195,49 @@ func formatApplied(m map[string]int) string {
// ============ 定时循环 ============
// StartSyncLoop 启动宽松节奏的定时双向同步(默认 10 分钟一轮,失败顺延下轮重试) // Logan.Li
// StartSyncLoop 启动宽松节奏的定时双向同步(默认 10 分钟一轮)。
// 行为:启动即先跑一轮;active 节点直接交换;pending 节点先自动握手(两侧
// 均已配置同钥时自动激活,无需人工点击);上一轮未结束时本轮跳过(防堆积)。 // Logan.Li
func (s *Service) StartSyncLoop(intervalMinutes int) {
if intervalMinutes <= 0 {
intervalMinutes = 10
}
go func() {
ticker := time.NewTicker(time.Duration(intervalMinutes) * time.Minute)
defer ticker.Stop()
for range ticker.C {
var running int32
runOnce := func() {
if !atomic.CompareAndSwapInt32(&running, 0, 1) {
return // 上一轮仍在进行,跳过本轮防堆积 // Logan.Li
}
defer atomic.StoreInt32(&running, 0)
defer func() {
if r := recover(); r != nil {
log.Printf("[同步] 本轮异常恢复: %v", r)
}
}()
var peers []model.PeerNode
s.db.Where("status = ?", model.PeerStatusActive).Find(&peers)
s.db.Where("status IN ?", []string{model.PeerStatusActive, model.PeerStatusPending}).Find(&peers)
for _, peer := range peers {
p := peer
// pending 先尝试握手(对端未配置/密钥不一致时静默失败,下轮再试) // Logan.Li
if p.Status == model.PeerStatusPending {
if _, err := s.TestHandshake(p.ID); err != nil {
continue
}
s.db.First(&p, p.ID)
}
if _, err := s.ExchangeOut(&p); err != nil {
log.Printf("[同步] 节点 %s 本轮失败: %v", peer.Name, err)
}
}
}
runOnce() // 启动即先跑一轮,不等首个间隔 // Logan.Li
ticker := time.NewTicker(time.Duration(intervalMinutes) * time.Minute)
defer ticker.Stop()
for range ticker.C {
runOnce()
}
}()
log.Printf("[同步] 定时双向同步已启动(每 %d 分钟)", intervalMinutes)
}
+4
View File
@@ -4,6 +4,7 @@ import (
"backend/config"
"backend/database"
licenseservice "backend/internal/service/license"
syncservice "backend/internal/service/sync"
"backend/router"
"context"
"log"
@@ -27,6 +28,9 @@ func main() {
// 启动在线状态清扫(超时未心跳的激活记录置为离线) // Logan.Li
licenseservice.StartOnlineSweeper(db, cfg.OnlineTTLMinutes)
// 启动节点定时双向同步(宽松节奏,默认 10 分钟) // Logan.Li
syncservice.NewService(db, cfg).StartSyncLoop(cfg.SyncIntervalMinutes)
// 初始化路由 // Logan.Li
r := router.SetupRouter(db, cfg)
-3
View File
@@ -96,9 +96,6 @@ func SetupRouter(db *gorm.DB, cfg *config.Config) *gin.Engine {
settingController := setting.NewSettingController(db)
syncController := synccontroller.NewController(db, cfg)
// 启动节点定时双向同步(宽松节奏,默认 10 分钟) // Logan.Li
syncController.Svc().StartSyncLoop(cfg.SyncIntervalMinutes)
api := r.Group("/api")
{
// ============ 节点互联(对端调用,HMAC 签名认证,非 JWT) ============