userset.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package core
  2. import (
  3. "time"
  4. )
  5. const (
  6. updateIntervalSec = 10
  7. cacheDurationSec = 120
  8. )
  9. type UserSet interface {
  10. AddUser(user User) error
  11. GetUser(timeHash []byte) (*ID, int64, bool)
  12. }
  13. type TimedUserSet struct {
  14. validUserIds []ID
  15. userHashes map[string]indexTimePair
  16. }
  17. type indexTimePair struct {
  18. index int
  19. timeSec int64
  20. }
  21. type hashEntry struct {
  22. hash string
  23. timeSec int64
  24. }
  25. func NewTimedUserSet() UserSet {
  26. vuSet := new(TimedUserSet)
  27. vuSet.validUserIds = make([]ID, 0, 16)
  28. vuSet.userHashes = make(map[string]indexTimePair)
  29. go vuSet.updateUserHash(time.Tick(updateIntervalSec * time.Second))
  30. return vuSet
  31. }
  32. func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
  33. now := time.Now().UTC()
  34. lastSec := now.Unix() - cacheDurationSec
  35. hash2Remove := make(chan hashEntry, cacheDurationSec*3*len(us.validUserIds))
  36. lastSec2Remove := now.Unix()
  37. for {
  38. now := <-tick
  39. nowSec := now.UTC().Unix()
  40. remove2Sec := nowSec - cacheDurationSec
  41. if remove2Sec > lastSec2Remove {
  42. for lastSec2Remove+1 < remove2Sec {
  43. entry := <-hash2Remove
  44. lastSec2Remove = entry.timeSec
  45. delete(us.userHashes, entry.hash)
  46. }
  47. }
  48. for lastSec < nowSec + cacheDurationSec {
  49. for idx, id := range us.validUserIds {
  50. idHash := id.TimeHash(lastSec)
  51. hash2Remove <- hashEntry{string(idHash), lastSec}
  52. us.userHashes[string(idHash)] = indexTimePair{idx, lastSec}
  53. }
  54. lastSec ++
  55. }
  56. }
  57. }
  58. func (us *TimedUserSet) AddUser(user User) error {
  59. id := user.Id
  60. us.validUserIds = append(us.validUserIds, id)
  61. return nil
  62. }
  63. func (us TimedUserSet) GetUser(userHash []byte) (*ID, int64, bool) {
  64. pair, found := us.userHashes[string(userHash)]
  65. if found {
  66. return &us.validUserIds[pair.index], pair.timeSec, true
  67. }
  68. return nil, 0, false
  69. }