service.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package sidebar
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "time"
  7. "go-common/app/interface/main/app-resource/conf"
  8. bplusdao "go-common/app/interface/main/app-resource/dao/bplus"
  9. resdao "go-common/app/interface/main/app-resource/dao/resource"
  10. whitedao "go-common/app/interface/main/app-resource/dao/white"
  11. "go-common/app/interface/main/app-resource/model"
  12. "go-common/app/interface/main/app-resource/model/sidebar"
  13. resource "go-common/app/service/main/resource/model"
  14. "go-common/library/log"
  15. "go-common/library/sync/errgroup"
  16. )
  17. const (
  18. _initSidebarKey = "sidebar_%d_%d_%s"
  19. _defaultLanguageHans = "hans"
  20. _defaultLanguageHant = "hant"
  21. )
  22. type Service struct {
  23. c *conf.Config
  24. //dao
  25. res *resdao.Dao
  26. bdao *bplusdao.Dao
  27. wdao *whitedao.Dao
  28. // sidebar
  29. tick time.Duration
  30. sidebarCache map[string][]*sidebar.SideBar
  31. limitsCahce map[int64][]*resource.SideBarLimit
  32. //limit ids
  33. limitIDs map[int64]struct{}
  34. }
  35. func New(c *conf.Config) (s *Service) {
  36. s = &Service{
  37. c: c,
  38. res: resdao.New(c),
  39. bdao: bplusdao.New(c),
  40. wdao: whitedao.New(c),
  41. tick: time.Duration(c.Tick),
  42. sidebarCache: map[string][]*sidebar.SideBar{},
  43. limitsCahce: map[int64][]*resource.SideBarLimit{},
  44. //limit ids
  45. limitIDs: map[int64]struct{}{},
  46. }
  47. s.loadSidebar()
  48. s.loadLimit(c.SideBarLimit)
  49. go s.tickproc()
  50. return s
  51. }
  52. // SideBar
  53. func (s *Service) SideBar(c context.Context, plat int8, build, module int, mid int64, language string) (ss []*sidebar.SideBar) {
  54. if key := fmt.Sprintf(_initSidebarKey, plat, module, language); len(s.sidebarCache[fmt.Sprintf(key)]) == 0 || language == "" {
  55. if model.IsOverseas(plat) {
  56. key = fmt.Sprintf(_initSidebarKey, plat, module, _defaultLanguageHant)
  57. if len(s.sidebarCache[fmt.Sprintf(key)]) > 0 {
  58. language = _defaultLanguageHant
  59. } else {
  60. language = _defaultLanguageHans
  61. }
  62. } else {
  63. language = _defaultLanguageHans
  64. }
  65. }
  66. var (
  67. key = fmt.Sprintf(_initSidebarKey, plat, module, language)
  68. verify = map[int64]bool{}
  69. mutex sync.Mutex
  70. )
  71. if sidebars, ok := s.sidebarCache[key]; ok {
  72. g, _ := errgroup.WithContext(c)
  73. for _, v := range sidebars {
  74. var (
  75. vid = v.ID
  76. vurl = v.WhiteURL
  77. )
  78. if vurl != "" && mid > 0 {
  79. g.Go(func() (err error) {
  80. var ok bool
  81. if ok, err = s.wdao.WhiteVerify(context.TODO(), mid, vurl); err != nil {
  82. log.Error("s.wdao.WhiteVerify uri(%s) error(%v)", vurl, err)
  83. ok = false
  84. err = nil
  85. }
  86. mutex.Lock()
  87. verify[vid] = ok
  88. mutex.Unlock()
  89. return
  90. })
  91. } else if vurl != "" && mid == 0 {
  92. verify[vid] = false
  93. }
  94. }
  95. g.Wait()
  96. LOOP:
  97. for _, v := range sidebars {
  98. for _, l := range s.limitsCahce[v.ID] {
  99. if model.InvalidBuild(build, l.Build, l.Condition) {
  100. continue LOOP
  101. }
  102. }
  103. if verifybool, ok := verify[v.ID]; ok && !verifybool {
  104. continue LOOP
  105. }
  106. ss = append(ss, v)
  107. }
  108. }
  109. return
  110. }
  111. // tickproc tick load cache.
  112. func (s *Service) tickproc() {
  113. for {
  114. time.Sleep(s.tick)
  115. s.loadSidebar()
  116. }
  117. }
  118. func (s *Service) loadSidebar() {
  119. sideBars, err := s.res.ResSideBar(context.TODO())
  120. if err != nil || sideBars == nil {
  121. log.Error("s.sideDao.SideBar error(%v) or nil", err)
  122. return
  123. }
  124. var (
  125. tmp = map[int64]struct{}{}
  126. ss = map[string][]*sidebar.SideBar{}
  127. )
  128. for _, v := range sideBars.SideBar {
  129. if _, ok := tmp[v.ID]; ok {
  130. continue
  131. }
  132. tmp[v.ID] = struct{}{}
  133. t := &sidebar.SideBar{}
  134. t.Change(v)
  135. key := fmt.Sprintf(_initSidebarKey, t.Plat, t.Module, t.Language)
  136. ss[key] = append(ss[key], t)
  137. }
  138. s.sidebarCache = ss
  139. s.limitsCahce = sideBars.Limit
  140. log.Info("loadSidebar cache success")
  141. }
  142. func (s *Service) loadLimit(limit []int64) {
  143. tmp := map[int64]struct{}{}
  144. for _, l := range limit {
  145. tmp[l] = struct{}{}
  146. }
  147. s.limitIDs = tmp
  148. }