手动同步改为异步任务并前端轮询状态

This commit is contained in:
2026-07-04 12:10:33 +08:00
parent ab14eb9c30
commit 46013a2b2f
4 changed files with 98 additions and 23 deletions
+51 -9
View File
@@ -52,10 +52,31 @@ func (s *StockSyncService) SyncHistory(ctx context.Context, triggerBy string, mo
})
}
func (s *StockSyncService) runSyncJob(ctx context.Context, triggerBy string, fn func() (int, error)) (int, error) {
s.mu.Lock()
defer s.mu.Unlock()
// StartSync 异步启动一次盘后同步,返回已创建的 job。
func (s *StockSyncService) StartSync(ctx context.Context, triggerBy string) (*models.StockSyncJob, error) {
job, err := s.createJob(ctx, triggerBy)
if err != nil {
return nil, err
}
go s.runSyncJobByID(context.Background(), job.ID, func(ctx context.Context) (int, error) {
return s.doSync(ctx)
})
return job, nil
}
// StartSyncHistory 异步启动近 N 个月历史同步,返回已创建的 job。
func (s *StockSyncService) StartSyncHistory(ctx context.Context, triggerBy string, months int) (*models.StockSyncJob, error) {
job, err := s.createJob(ctx, triggerBy)
if err != nil {
return nil, err
}
go s.runSyncJobByID(context.Background(), job.ID, func(ctx context.Context) (int, error) {
return s.doSyncHistory(ctx, months)
})
return job, nil
}
func (s *StockSyncService) createJob(ctx context.Context, triggerBy string) (*models.StockSyncJob, error) {
job := models.StockSyncJob{
JobDate: today(),
Status: "running",
@@ -63,25 +84,46 @@ func (s *StockSyncService) runSyncJob(ctx context.Context, triggerBy string, fn
TriggerBy: triggerBy,
}
if err := s.db.WithContext(ctx).Create(&job).Error; err != nil {
return 0, fmt.Errorf("create sync job: %w", err)
return nil, fmt.Errorf("create sync job: %w", err)
}
return &job, nil
}
func (s *StockSyncService) runSyncJob(ctx context.Context, triggerBy string, fn func() (int, error)) (int, error) {
job, err := s.createJob(ctx, triggerBy)
if err != nil {
return 0, err
}
recordsCount, err := fn()
s.finishJob(ctx, job.ID, recordsCount, err)
return recordsCount, err
}
func (s *StockSyncService) runSyncJobByID(ctx context.Context, jobID string, fn func(context.Context) (int, error)) {
s.mu.Lock()
defer s.mu.Unlock()
recordsCount, err := fn(ctx)
s.finishJob(ctx, jobID, recordsCount, err)
}
func (s *StockSyncService) finishJob(ctx context.Context, jobID string, recordsCount int, jobErr error) {
now := time.Now().UTC()
updates := map[string]any{
"records_count": recordsCount,
"finished_at": &now,
}
if err != nil {
if jobErr != nil {
updates["status"] = "failed"
updates["error_message"] = err.Error()
updates["error_message"] = jobErr.Error()
log.Printf("[stock sync] job %s failed: %v", jobID, jobErr)
} else {
updates["status"] = "success"
log.Printf("[stock sync] job %s success, records=%d", jobID, recordsCount)
}
if err := s.db.WithContext(ctx).Model(&models.StockSyncJob{}).Where("id = ?", jobID).Updates(updates).Error; err != nil {
log.Printf("[stock sync] update job %s failed: %v", jobID, err)
}
s.db.WithContext(ctx).Model(&job).Updates(updates)
return recordsCount, err
}
func (s *StockSyncService) doSync(ctx context.Context) (int, error) {