notice.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package notice
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "go-common/app/interface/main/app-resource/conf"
  10. locdao "go-common/app/interface/main/app-resource/dao/location"
  11. ntcdao "go-common/app/interface/main/app-resource/dao/notice"
  12. "go-common/app/interface/main/app-resource/model"
  13. "go-common/app/interface/main/app-resource/model/notice"
  14. locmdl "go-common/app/service/main/location/model"
  15. "go-common/library/ecode"
  16. "go-common/library/log"
  17. "go-common/library/net/metadata"
  18. "github.com/dgryski/go-farm"
  19. )
  20. const (
  21. _initNoticeKey = "notice_key_%d_%d"
  22. _initNoticeVer = "notice_version"
  23. )
  24. var (
  25. _emptyNotice = &notice.Notice{}
  26. )
  27. // Service notice service.
  28. type Service struct {
  29. dao *ntcdao.Dao
  30. loc *locdao.Dao
  31. // tick
  32. tick time.Duration
  33. // cache
  34. cache map[string][]*notice.Notice
  35. }
  36. // New new a notice service.
  37. func New(c *conf.Config) (s *Service) {
  38. s = &Service{
  39. dao: ntcdao.New(c),
  40. loc: locdao.New(c),
  41. // tick
  42. tick: time.Duration(c.Tick),
  43. // cache
  44. cache: map[string][]*notice.Notice{},
  45. }
  46. s.load(time.Now())
  47. go s.loadproc()
  48. return
  49. }
  50. // Notice return Notice to json
  51. func (s *Service) Notice(c context.Context, plat int8, build, typeInt int, ver string) (res *notice.Notice, version string, err error) {
  52. var (
  53. ip = metadata.String(c, metadata.RemoteIP)
  54. pids []string
  55. auths map[string]*locmdl.Auth
  56. )
  57. for _, ntc := range s.cache[fmt.Sprintf(_initNoticeKey, plat, typeInt)] {
  58. if model.InvalidBuild(build, ntc.Build, ntc.Condition) {
  59. continue
  60. }
  61. if ntc.Area != "" {
  62. pids = append(pids, ntc.Area)
  63. }
  64. }
  65. if len(pids) > 0 {
  66. auths, _ = s.loc.AuthPIDs(c, strings.Join(pids, ","), ip)
  67. }
  68. for _, ntc := range s.cache[fmt.Sprintf(_initNoticeKey, plat, typeInt)] {
  69. if model.InvalidBuild(build, ntc.Build, ntc.Condition) {
  70. continue
  71. }
  72. if auth, ok := auths[ntc.Area]; ok && auth.Play == locmdl.Forbidden {
  73. log.Warn("s.invalid area(%v) ip(%v) error(%v)", ntc.Area, ip, err)
  74. continue
  75. }
  76. res = ntc
  77. break
  78. }
  79. if res == nil {
  80. res = _emptyNotice
  81. }
  82. if version = s.hash(res); ver == version {
  83. err = ecode.NotModified
  84. res = nil
  85. }
  86. return
  87. }
  88. // load
  89. func (s *Service) load(now time.Time) {
  90. // get notice
  91. ntcs, err := s.dao.All(context.TODO(), now)
  92. if err != nil {
  93. log.Error("s.dao.GetAll() error(%v)", err)
  94. return
  95. }
  96. // copy cache
  97. tmp := map[string][]*notice.Notice{}
  98. for _, v := range ntcs {
  99. key := fmt.Sprintf(_initNoticeKey, v.Plat, v.Type)
  100. tmp[key] = append(tmp[key], v)
  101. }
  102. s.cache = tmp
  103. log.Info("notice cacheproc success")
  104. }
  105. func (s *Service) hash(v *notice.Notice) string {
  106. bs, err := json.Marshal(v)
  107. if err != nil {
  108. log.Error("json.Marshal error(%v)", err)
  109. return _initNoticeVer
  110. }
  111. return strconv.FormatUint(farm.Hash64(bs), 10)
  112. }
  113. // cacheproc load cache data
  114. func (s *Service) loadproc() {
  115. for {
  116. time.Sleep(s.tick)
  117. s.load(time.Now())
  118. }
  119. }
  120. // Close dao
  121. func (s *Service) Close() {
  122. s.dao.Close()
  123. }