exp.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package dao
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "go-common/app/service/live/userexp/model"
  7. "go-common/library/log"
  8. "go-common/library/xstr"
  9. )
  10. const (
  11. _shard = 10
  12. _insExp = "INSERT IGNORE INTO user_exp_%d (uid,uexp,rexp) VALUES(?,?,?)"
  13. _selExp = "SELECT uid,uexp,rexp FROM user_exp_%d where uid=?"
  14. _inSelExp = "SELECT uid,uexp,rexp FROM user_exp_%d where uid IN (%s)"
  15. _addUexp = "INSERT INTO user_exp_%d(uid,uexp,rexp) VALUES(?,?,0) ON DUPLICATE KEY UPDATE uexp=uexp+%d"
  16. _addRexp = "INSERT INTO user_exp_%d(uid,uexp,rexp) VALUES(?,0,?) ON DUPLICATE KEY UPDATE rexp=rexp+%d"
  17. )
  18. // InitExp 初始化用户经验,用于首次查询
  19. func (d *Dao) InitExp(c context.Context, uid int64, uexp int64, rexp int64) (row int64, err error) {
  20. res, err := d.expDb.Exec(c, fmt.Sprintf(_insExp, uid%_shard), uid, uexp, rexp)
  21. if err != nil {
  22. log.Error("[dao.exp|InitExp] d.exp.Exec err: %v", err)
  23. return
  24. }
  25. return res.RowsAffected()
  26. }
  27. // Exp 查询一条记录
  28. func (d *Dao) Exp(c context.Context, uid int64) (exp *model.Exp, err error) {
  29. row := d.expDb.QueryRow(c, fmt.Sprintf(_selExp, uid%_shard), uid)
  30. exp = &model.Exp{}
  31. if err = row.Scan(&exp.Uid, &exp.Uexp, &exp.Rexp); err == sql.ErrNoRows {
  32. // 查询结果为空时,初始化数据
  33. _, err = d.InitExp(c, uid, 0, 0)
  34. }
  35. if err != nil {
  36. log.Error("[dao.exp|Exp] row.Scan err: %v", err)
  37. return
  38. }
  39. return
  40. }
  41. // MultiExp 批量查询
  42. func (d *Dao) MultiExp(c context.Context, uids []int64) (exps []*model.Exp, err error) {
  43. var (
  44. suffix int64
  45. uidGroup [_shard][]int64
  46. um = make(map[int64]struct{}, len(uids))
  47. )
  48. for _, uid := range uids {
  49. suffix = uid % _shard
  50. uidGroup[suffix] = append(uidGroup[suffix], uid)
  51. um[uid] = struct{}{}
  52. }
  53. for index, uids := range uidGroup {
  54. if 0 == len(uids) {
  55. continue
  56. }
  57. rows, err1 := d.expDb.Query(c, fmt.Sprintf(_inSelExp, index, xstr.JoinInts(uids)))
  58. if err1 != nil {
  59. err = err1
  60. log.Error("[dao.exp|MultiExp] d.exp.Query err: %v", err)
  61. return
  62. }
  63. for rows.Next() {
  64. ele := &model.Exp{}
  65. if err = rows.Scan(&ele.Uid, &ele.Uexp, &ele.Rexp); err != nil {
  66. log.Error("[dao.exp|MultiExp] rows.Scan err: %v", err)
  67. return
  68. }
  69. exps = append(exps, ele)
  70. delete(um, ele.Uid)
  71. }
  72. }
  73. // 初始化不存在的数据,补齐数据
  74. for uid := range um {
  75. d.InitExp(c, uid, 0, 0)
  76. ele := &model.Exp{Uid: uid, Uexp: 0, Rexp: 0}
  77. exps = append(exps, ele)
  78. }
  79. return
  80. }
  81. // AddUexp 添加用户经验
  82. func (d *Dao) AddUexp(c context.Context, uid int64, uexp int64) (affect int64, err error) {
  83. upSQL := fmt.Sprintf(_addUexp, uid%_shard, uexp)
  84. res, err := d.expDb.Exec(c, upSQL, uid, uexp)
  85. if err != nil {
  86. log.Error("db.Exec(%s) error(%v)", upSQL, err)
  87. return
  88. }
  89. return res.RowsAffected()
  90. }
  91. // AddRexp 添加主播经验
  92. func (d *Dao) AddRexp(c context.Context, uid int64, rexp int64) (affect int64, err error) {
  93. upSQL := fmt.Sprintf(_addRexp, uid%_shard, rexp)
  94. res, err := d.expDb.Exec(c, upSQL, uid, rexp)
  95. if err != nil {
  96. log.Error("db.Exec(%s) error(%v)", upSQL, err)
  97. return
  98. }
  99. return res.RowsAffected()
  100. }