account_expiry_service.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package service
  2. import (
  3. "context"
  4. "log"
  5. "sync"
  6. "time"
  7. )
  8. // AccountExpiryService periodically pauses expired accounts when auto-pause is enabled.
  9. type AccountExpiryService struct {
  10. accountRepo AccountRepository
  11. interval time.Duration
  12. stopCh chan struct{}
  13. stopOnce sync.Once
  14. wg sync.WaitGroup
  15. }
  16. func NewAccountExpiryService(accountRepo AccountRepository, interval time.Duration) *AccountExpiryService {
  17. return &AccountExpiryService{
  18. accountRepo: accountRepo,
  19. interval: interval,
  20. stopCh: make(chan struct{}),
  21. }
  22. }
  23. func (s *AccountExpiryService) Start() {
  24. if s == nil || s.accountRepo == nil || s.interval <= 0 {
  25. return
  26. }
  27. s.wg.Add(1)
  28. go func() {
  29. defer s.wg.Done()
  30. ticker := time.NewTicker(s.interval)
  31. defer ticker.Stop()
  32. s.runOnce()
  33. for {
  34. select {
  35. case <-ticker.C:
  36. s.runOnce()
  37. case <-s.stopCh:
  38. return
  39. }
  40. }
  41. }()
  42. }
  43. func (s *AccountExpiryService) Stop() {
  44. if s == nil {
  45. return
  46. }
  47. s.stopOnce.Do(func() {
  48. close(s.stopCh)
  49. })
  50. s.wg.Wait()
  51. }
  52. func (s *AccountExpiryService) runOnce() {
  53. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  54. defer cancel()
  55. updated, err := s.accountRepo.AutoPauseExpiredAccounts(ctx, time.Now())
  56. if err != nil {
  57. log.Printf("[AccountExpiry] Auto pause expired accounts failed: %v", err)
  58. return
  59. }
  60. if updated > 0 {
  61. log.Printf("[AccountExpiry] Auto paused %d expired accounts", updated)
  62. }
  63. }