- 前端: 所有界面显示、i18n 文本、组件中的品牌名称 - 后端: 服务层、设置默认值、邮件模板、安装向导 - 数据库: 迁移脚本注释 - 保持功能完全一致,仅更改品牌名称 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// DeferredService provides deferred batch update functionality
|
|
type DeferredService struct {
|
|
accountRepo AccountRepository
|
|
timingWheel *TimingWheelService
|
|
interval time.Duration
|
|
|
|
lastUsedUpdates sync.Map
|
|
}
|
|
|
|
// NewDeferredService creates a new DeferredService instance
|
|
func NewDeferredService(accountRepo AccountRepository, timingWheel *TimingWheelService, interval time.Duration) *DeferredService {
|
|
return &DeferredService{
|
|
accountRepo: accountRepo,
|
|
timingWheel: timingWheel,
|
|
interval: interval,
|
|
}
|
|
}
|
|
|
|
// Start starts the deferred service
|
|
func (s *DeferredService) Start() {
|
|
s.timingWheel.ScheduleRecurring("deferred:last_used", s.interval, s.flushLastUsed)
|
|
log.Printf("[DeferredService] Started (interval: %v)", s.interval)
|
|
}
|
|
|
|
// Stop stops the deferred service
|
|
func (s *DeferredService) Stop() {
|
|
s.timingWheel.Cancel("deferred:last_used")
|
|
s.flushLastUsed()
|
|
log.Printf("[DeferredService] Service stopped")
|
|
}
|
|
|
|
func (s *DeferredService) ScheduleLastUsedUpdate(accountID int64) {
|
|
s.lastUsedUpdates.Store(accountID, time.Now())
|
|
}
|
|
|
|
func (s *DeferredService) flushLastUsed() {
|
|
updates := make(map[int64]time.Time)
|
|
s.lastUsedUpdates.Range(func(key, value any) bool {
|
|
id, ok := key.(int64)
|
|
if !ok {
|
|
return true
|
|
}
|
|
ts, ok := value.(time.Time)
|
|
if !ok {
|
|
return true
|
|
}
|
|
updates[id] = ts
|
|
s.lastUsedUpdates.Delete(key)
|
|
return true
|
|
})
|
|
|
|
if len(updates) == 0 {
|
|
return
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
if err := s.accountRepo.BatchUpdateLastUsed(ctx, updates); err != nil {
|
|
log.Printf("[DeferredService] BatchUpdateLastUsed failed (%d accounts): %v", len(updates), err)
|
|
for id, ts := range updates {
|
|
s.lastUsedUpdates.Store(id, ts)
|
|
}
|
|
} else {
|
|
log.Printf("[DeferredService] BatchUpdateLastUsed flushed %d accounts", len(updates))
|
|
}
|
|
}
|