.
This commit is contained in:
148
internal/service/sync_service.go
Normal file
148
internal/service/sync_service.go
Normal file
@@ -0,0 +1,148 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user