act_mission.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package like
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. l "go-common/app/interface/main/activity/model/like"
  7. "go-common/library/cache/redis"
  8. xsql "go-common/library/database/sql"
  9. "go-common/library/log"
  10. "github.com/pkg/errors"
  11. )
  12. const (
  13. _likeActMissionItemSQL = "select id from like_act_mission_group where sid = ? and lid = ? and mid = ?"
  14. _addLikeActMissionSQL = "insert into like_act_mission_group (`sid`,`mid`,`lid`,`action`,`ipv6`) values(?,?,?,?,?)"
  15. _likeActMissionFriendsSQL = "select id,sid,lid,mid,action from like_act_mission_group where sid = ? and lid = ? order by id asc limit 100 "
  16. _keyMissionLikeLimitFmt = "go:m:l:limt:%d:%d"
  17. _keyMissionScoreFmt = "go:l:a:m:score:%d"
  18. _keyMissionScoreStrFmt = "go:l:a:m:score:str:%d:%d"
  19. _scoreMaxTime = 2145888000
  20. _scoreMaxNum = 1000000
  21. _maxMissionTop = 200
  22. )
  23. // missionLikeLimitKey .
  24. func missionLikeLimitKey(sid, mid int64) string {
  25. return fmt.Sprintf(_keyMissionLikeLimitFmt, sid, mid)
  26. }
  27. // likeActMissionScoreKey .
  28. func likeActMissionScoreKey(sid int64) string {
  29. return fmt.Sprintf(_keyMissionScoreFmt, sid)
  30. }
  31. // likeMissionScoreStrKey .
  32. func likeMissionScoreStrKey(sid, lid int64) string {
  33. return fmt.Sprintf(_keyMissionScoreStrFmt, sid, lid)
  34. }
  35. // scoreMaxTime .
  36. func scoreMaxTime() int64 {
  37. return _scoreMaxTime
  38. }
  39. // scoreMaxNum only for num lower 1 million.
  40. func scoreMaxNum() int64 {
  41. return _scoreMaxNum
  42. }
  43. // buildRankScore only for num lower 1 million.
  44. func buildRankScore(num int64, ctime int64) int64 {
  45. var (
  46. maxTimeStamp = scoreMaxTime()
  47. timeScore = maxTimeStamp - ctime
  48. rankScore int64
  49. )
  50. rankScore = (num & 0xFFFFF) << 32
  51. rankScore |= timeScore & 0xFFFFFFFF
  52. return rankScore
  53. }
  54. // RawActMission .
  55. func (d *Dao) RawActMission(c context.Context, sid, lid, mid int64) (res int64, err error) {
  56. act := &l.ActMissionGroup{}
  57. rows := d.db.QueryRow(c, _likeActMissionItemSQL, sid, lid, mid)
  58. if err = rows.Scan(&act.ID); err != nil {
  59. if err == xsql.ErrNoRows {
  60. err = nil
  61. } else {
  62. err = errors.Wrap(err, "RawActMission:QueryRow")
  63. return
  64. }
  65. }
  66. res = act.ID
  67. return
  68. }
  69. // MissionLikeLimit .
  70. func (d *Dao) MissionLikeLimit(c context.Context, sid, mid int64) (res int64, err error) {
  71. key := missionLikeLimitKey(sid, mid)
  72. conn := d.redis.Get(c)
  73. defer conn.Close()
  74. if res, err = redis.Int64(conn.Do("GET", key)); err != nil {
  75. if err == redis.ErrNil {
  76. err = nil
  77. } else {
  78. err = errors.Wrapf(err, "conn.Do(GET, %s)", key)
  79. }
  80. }
  81. return
  82. }
  83. // InrcMissionLikeLimit .
  84. func (d *Dao) InrcMissionLikeLimit(c context.Context, sid, mid int64, val int64) (res bool, err error) {
  85. key := missionLikeLimitKey(sid, mid)
  86. conn := d.redis.Get(c)
  87. defer conn.Close()
  88. if res, err = redis.Bool(conn.Do("INCRBY", key, val)); err != nil {
  89. log.Error("InrcMissionLikeLimit:conn.Do(INCR) %s %d", key, val)
  90. }
  91. return
  92. }
  93. // SetMissionTop .
  94. func (d *Dao) SetMissionTop(c context.Context, sid, lid int64, score int64, ctime int64) (count int64, err error) {
  95. var (
  96. conn = d.redis.Get(c)
  97. key = likeActMissionScoreKey(sid)
  98. strKey = likeMissionScoreStrKey(sid, lid)
  99. maxNum = scoreMaxNum()
  100. rankScore int64
  101. )
  102. defer conn.Close()
  103. if count, err = redis.Int64(conn.Do("INCRBY", strKey, score)); err != nil {
  104. err = errors.Wrap(err, "conn.Do(INCRBY)")
  105. return
  106. }
  107. // the score could not more than 1 million
  108. if count > maxNum {
  109. log.Warn("SetMissionTop over max score (%d) error", count)
  110. return
  111. }
  112. rankScore = buildRankScore(count, ctime)
  113. // set top list
  114. if _, err = redis.Bool(conn.Do("ZADD", key, rankScore, lid)); err != nil {
  115. err = errors.Wrapf(err, "conn.Do(ZADD) key(%s)", key)
  116. return
  117. }
  118. if _, err = conn.Do("ZREMRANGEBYRANK", key, 0, -(_maxMissionTop + 1)); err != nil {
  119. err = errors.Wrapf(err, "conn.Do(ZREMRANGEBYRANK) key(%s)", key)
  120. }
  121. return
  122. }
  123. // MissionLidScore .
  124. func (d *Dao) MissionLidScore(c context.Context, sid, lid int64) (score int64, err error) {
  125. var (
  126. conn = d.redis.Get(c)
  127. key = likeMissionScoreStrKey(sid, lid)
  128. )
  129. defer conn.Close()
  130. if score, err = redis.Int64(conn.Do("GET", key)); err != nil {
  131. if err == redis.ErrNil {
  132. err = nil
  133. } else {
  134. err = errors.Wrapf(err, "conn.Do(GET) %s", key)
  135. }
  136. }
  137. return
  138. }
  139. // MissionLidRank .
  140. func (d *Dao) MissionLidRank(c context.Context, sid, lid int64) (rank int64, err error) {
  141. var (
  142. conn = d.redis.Get(c)
  143. key = likeActMissionScoreKey(sid)
  144. )
  145. defer conn.Close()
  146. if rank, err = redis.Int64(conn.Do("ZREVRANK", key, lid)); err != nil {
  147. if err == redis.ErrNil {
  148. err = nil
  149. rank = -1
  150. } else {
  151. err = errors.Wrapf(err, "conn.Do(GET) %s", key)
  152. }
  153. }
  154. return
  155. }
  156. // MissionScoreList score list .
  157. func (d *Dao) MissionScoreList(c context.Context, sid int64, start, end int) (data []int64, err error) {
  158. var (
  159. key = likeActMissionScoreKey(sid)
  160. conn = d.redis.Get(c)
  161. )
  162. defer conn.Close()
  163. vs, err := redis.Values(conn.Do("ZREVRANGE", key, start, end, "WITHSCORES"))
  164. if err != nil {
  165. PromError("redis:获取MissionScoreList", "conn.Do(ZREVRANGE,%s,%d,%d) error(%v)", key, start, end, err)
  166. return
  167. }
  168. data = make([]int64, 0, len(vs))
  169. for len(vs) > 0 {
  170. var (
  171. lid int64
  172. score int64
  173. )
  174. if vs, err = redis.Scan(vs, &lid, &score); err != nil {
  175. PromError("redis:获取获取MissionScoreList", "redis.Scan(%v) error(%v)", vs, err)
  176. return
  177. }
  178. if lid != 0 {
  179. data = append(data, lid)
  180. }
  181. }
  182. return
  183. }
  184. // AddActMission .
  185. func (d *Dao) AddActMission(c context.Context, act *l.ActMissionGroup) (actID int64, err error) {
  186. var res sql.Result
  187. if res, err = d.db.Exec(c, _addLikeActMissionSQL, act.Sid, act.Mid, act.Lid, act.Action, act.IPv6); err != nil {
  188. err = errors.Wrapf(err, "d.db.Exec(%s)", _addLikeActMissionSQL)
  189. return
  190. }
  191. return res.LastInsertId()
  192. }
  193. // RawActMissionFriends .
  194. func (d *Dao) RawActMissionFriends(c context.Context, sid, lid int64) (res *l.ActMissionGroups, err error) {
  195. rows, err := d.db.Query(c, _likeActMissionFriendsSQL, sid, lid)
  196. if err != nil {
  197. err = errors.Wrapf(err, " d.db.Query(%s)", _likeActMissionFriendsSQL)
  198. return
  199. }
  200. list := make([]*l.ActMissionGroup, 0, 100)
  201. for rows.Next() {
  202. n := &l.ActMissionGroup{}
  203. if err = rows.Scan(&n.ID, &n.Sid, &n.Lid, &n.Mid, &n.Action); err != nil {
  204. err = errors.Wrapf(err, " d.db.rows.Scan(%s)", _likeActMissionFriendsSQL)
  205. return
  206. }
  207. list = append(list, n)
  208. }
  209. res = &l.ActMissionGroups{ActMissionGroups: list}
  210. if err = rows.Err(); err != nil {
  211. err = errors.Wrap(err, "rows.Err()")
  212. }
  213. return
  214. }