deferred_service.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package service
  2. import (
  3. "context"
  4. "log"
  5. "sync"
  6. "time"
  7. )
  8. // DeferredService provides deferred batch update functionality
  9. type DeferredService struct {
  10. accountRepo AccountRepository
  11. timingWheel *TimingWheelService
  12. interval time.Duration
  13. lastUsedUpdates sync.Map
  14. }
  15. // NewDeferredService creates a new DeferredService instance
  16. func NewDeferredService(accountRepo AccountRepository, timingWheel *TimingWheelService, interval time.Duration) *DeferredService {
  17. return &DeferredService{
  18. accountRepo: accountRepo,
  19. timingWheel: timingWheel,
  20. interval: interval,
  21. }
  22. }
  23. // Start starts the deferred service
  24. func (s *DeferredService) Start() {
  25. s.timingWheel.ScheduleRecurring("deferred:last_used", s.interval, s.flushLastUsed)
  26. log.Printf("[DeferredService] Started (interval: %v)", s.interval)
  27. }
  28. // Stop stops the deferred service
  29. func (s *DeferredService) Stop() {
  30. s.timingWheel.Cancel("deferred:last_used")
  31. s.flushLastUsed()
  32. log.Printf("[DeferredService] Service stopped")
  33. }
  34. func (s *DeferredService) ScheduleLastUsedUpdate(accountID int64) {
  35. s.lastUsedUpdates.Store(accountID, time.Now())
  36. }
  37. func (s *DeferredService) flushLastUsed() {
  38. updates := make(map[int64]time.Time)
  39. s.lastUsedUpdates.Range(func(key, value any) bool {
  40. id, ok := key.(int64)
  41. if !ok {
  42. return true
  43. }
  44. ts, ok := value.(time.Time)
  45. if !ok {
  46. return true
  47. }
  48. updates[id] = ts
  49. s.lastUsedUpdates.Delete(key)
  50. return true
  51. })
  52. if len(updates) == 0 {
  53. return
  54. }
  55. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  56. defer cancel()
  57. if err := s.accountRepo.BatchUpdateLastUsed(ctx, updates); err != nil {
  58. log.Printf("[DeferredService] BatchUpdateLastUsed failed (%d accounts): %v", len(updates), err)
  59. for id, ts := range updates {
  60. s.lastUsedUpdates.Store(id, ts)
  61. }
  62. } else {
  63. log.Printf("[DeferredService] BatchUpdateLastUsed flushed %d accounts", len(updates))
  64. }
  65. }