Files
ssq-desk/internal/service/sync_service.go
2026-01-14 14:17:38 +08:00

149 lines
3.9 KiB
Go

package service
import (
"fmt"
"ssq-desk/internal/storage/models"
"ssq-desk/internal/storage/repository"
)
// SyncService 数据同步服务
type SyncService struct {
mysqlRepo repository.SsqRepository
sqliteRepo repository.SsqRepository
}
// NewSyncService 创建同步服务
func NewSyncService(mysqlRepo, sqliteRepo repository.SsqRepository) *SyncService {
return &SyncService{
mysqlRepo: mysqlRepo,
sqliteRepo: sqliteRepo,
}
}
// SyncResult 同步结果
type SyncResult struct {
TotalCount int `json:"total_count"` // 远程数据总数
SyncedCount int `json:"synced_count"` // 已同步数量
NewCount int `json:"new_count"` // 新增数量
UpdatedCount int `json:"updated_count"` // 更新数量
ErrorCount int `json:"error_count"` // 错误数量
LatestIssue string `json:"latest_issue"` // 最新期号
}
// Sync 执行数据同步(增量同步)
func (s *SyncService) Sync() (*SyncResult, error) {
result := &SyncResult{}
// 获取本地最新期号
localLatestIssue, err := s.sqliteRepo.GetLatestIssue()
if err != nil {
return nil, fmt.Errorf("获取本地最新期号失败: %v", err)
}
// 获取远程所有数据
remoteHistories, err := s.mysqlRepo.FindAll()
if err != nil {
return nil, fmt.Errorf("获取远程数据失败: %v", err)
}
result.TotalCount = len(remoteHistories)
if len(remoteHistories) == 0 {
return result, nil
}
// 确定最新期号
if len(remoteHistories) > 0 {
result.LatestIssue = remoteHistories[0].IssueNumber
}
// 增量同步:只同步本地没有的数据
if localLatestIssue == "" {
// 首次同步,全量同步
for _, history := range remoteHistories {
if err := s.sqliteRepo.Create(&history); err != nil {
result.ErrorCount++
continue
}
result.NewCount++
result.SyncedCount++
}
} else {
// 增量同步:同步期号大于本地最新期号的数据
for _, history := range remoteHistories {
// 如果期号小于等于本地最新期号,跳过
if history.IssueNumber <= localLatestIssue {
continue
}
// 检查本地是否已存在(基于期号)
localHistory, err := s.sqliteRepo.FindByIssue(history.IssueNumber)
if err == nil && localHistory != nil {
// 已存在,检查是否需要更新
if s.needUpdate(localHistory, &history) {
// 更新逻辑(目前使用创建,如需更新可扩展)
result.UpdatedCount++
}
continue
}
// 新数据,插入
if err := s.sqliteRepo.Create(&history); err != nil {
result.ErrorCount++
continue
}
result.NewCount++
result.SyncedCount++
}
}
return result, nil
}
// needUpdate 判断是否需要更新
func (s *SyncService) needUpdate(local, remote *models.SsqHistory) bool {
// 简单比较:如果任何字段不同,则认为需要更新
return local.RedBall1 != remote.RedBall1 ||
local.RedBall2 != remote.RedBall2 ||
local.RedBall3 != remote.RedBall3 ||
local.RedBall4 != remote.RedBall4 ||
local.RedBall5 != remote.RedBall5 ||
local.RedBall6 != remote.RedBall6 ||
local.BlueBall != remote.BlueBall
}
// GetSyncStatus 获取同步状态
func (s *SyncService) GetSyncStatus() (map[string]interface{}, error) {
// 获取本地统计
localCount, err := s.sqliteRepo.Count()
if err != nil {
return nil, err
}
localLatestIssue, err := s.sqliteRepo.GetLatestIssue()
if err != nil {
return nil, err
}
// 获取远程统计
remoteCount, err := s.mysqlRepo.Count()
if err != nil {
// 远程连接失败不影响本地状态
remoteCount = 0
}
remoteLatestIssue := ""
remoteHistories, err := s.mysqlRepo.FindAll()
if err == nil && len(remoteHistories) > 0 {
remoteLatestIssue = remoteHistories[0].IssueNumber
}
return map[string]interface{}{
"local_count": localCount,
"local_latest_issue": localLatestIssue,
"remote_count": remoteCount,
"remote_latest_issue": remoteLatestIssue,
"need_sync": remoteLatestIssue > localLatestIssue,
}, nil
}