You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
6.3 KiB
233 lines
6.3 KiB
package like |
|
|
|
import ( |
|
"context" |
|
"database/sql" |
|
"fmt" |
|
|
|
l "go-common/app/interface/main/activity/model/like" |
|
"go-common/library/cache/redis" |
|
xsql "go-common/library/database/sql" |
|
"go-common/library/log" |
|
|
|
"github.com/pkg/errors" |
|
) |
|
|
|
const ( |
|
_likeActMissionItemSQL = "select id from like_act_mission_group where sid = ? and lid = ? and mid = ?" |
|
_addLikeActMissionSQL = "insert into like_act_mission_group (`sid`,`mid`,`lid`,`action`,`ipv6`) values(?,?,?,?,?)" |
|
_likeActMissionFriendsSQL = "select id,sid,lid,mid,action from like_act_mission_group where sid = ? and lid = ? order by id asc limit 100 " |
|
_keyMissionLikeLimitFmt = "go:m:l:limt:%d:%d" |
|
_keyMissionScoreFmt = "go:l:a:m:score:%d" |
|
_keyMissionScoreStrFmt = "go:l:a:m:score:str:%d:%d" |
|
_scoreMaxTime = 2145888000 |
|
_scoreMaxNum = 1000000 |
|
_maxMissionTop = 200 |
|
) |
|
|
|
// missionLikeLimitKey . |
|
func missionLikeLimitKey(sid, mid int64) string { |
|
return fmt.Sprintf(_keyMissionLikeLimitFmt, sid, mid) |
|
} |
|
|
|
// likeActMissionScoreKey . |
|
func likeActMissionScoreKey(sid int64) string { |
|
return fmt.Sprintf(_keyMissionScoreFmt, sid) |
|
} |
|
|
|
// likeMissionScoreStrKey . |
|
func likeMissionScoreStrKey(sid, lid int64) string { |
|
return fmt.Sprintf(_keyMissionScoreStrFmt, sid, lid) |
|
} |
|
|
|
// scoreMaxTime . |
|
func scoreMaxTime() int64 { |
|
return _scoreMaxTime |
|
} |
|
|
|
// scoreMaxNum only for num lower 1 million. |
|
func scoreMaxNum() int64 { |
|
return _scoreMaxNum |
|
} |
|
|
|
// buildRankScore only for num lower 1 million. |
|
func buildRankScore(num int64, ctime int64) int64 { |
|
var ( |
|
maxTimeStamp = scoreMaxTime() |
|
timeScore = maxTimeStamp - ctime |
|
rankScore int64 |
|
) |
|
rankScore = (num & 0xFFFFF) << 32 |
|
rankScore |= timeScore & 0xFFFFFFFF |
|
return rankScore |
|
} |
|
|
|
// RawActMission . |
|
func (d *Dao) RawActMission(c context.Context, sid, lid, mid int64) (res int64, err error) { |
|
act := &l.ActMissionGroup{} |
|
rows := d.db.QueryRow(c, _likeActMissionItemSQL, sid, lid, mid) |
|
if err = rows.Scan(&act.ID); err != nil { |
|
if err == xsql.ErrNoRows { |
|
err = nil |
|
} else { |
|
err = errors.Wrap(err, "RawActMission:QueryRow") |
|
return |
|
} |
|
} |
|
res = act.ID |
|
return |
|
} |
|
|
|
// MissionLikeLimit . |
|
func (d *Dao) MissionLikeLimit(c context.Context, sid, mid int64) (res int64, err error) { |
|
key := missionLikeLimitKey(sid, mid) |
|
conn := d.redis.Get(c) |
|
defer conn.Close() |
|
if res, err = redis.Int64(conn.Do("GET", key)); err != nil { |
|
if err == redis.ErrNil { |
|
err = nil |
|
} else { |
|
err = errors.Wrapf(err, "conn.Do(GET, %s)", key) |
|
} |
|
} |
|
return |
|
} |
|
|
|
// InrcMissionLikeLimit . |
|
func (d *Dao) InrcMissionLikeLimit(c context.Context, sid, mid int64, val int64) (res bool, err error) { |
|
key := missionLikeLimitKey(sid, mid) |
|
conn := d.redis.Get(c) |
|
defer conn.Close() |
|
if res, err = redis.Bool(conn.Do("INCRBY", key, val)); err != nil { |
|
log.Error("InrcMissionLikeLimit:conn.Do(INCR) %s %d", key, val) |
|
} |
|
return |
|
} |
|
|
|
// SetMissionTop . |
|
func (d *Dao) SetMissionTop(c context.Context, sid, lid int64, score int64, ctime int64) (count int64, err error) { |
|
var ( |
|
conn = d.redis.Get(c) |
|
key = likeActMissionScoreKey(sid) |
|
strKey = likeMissionScoreStrKey(sid, lid) |
|
maxNum = scoreMaxNum() |
|
rankScore int64 |
|
) |
|
defer conn.Close() |
|
if count, err = redis.Int64(conn.Do("INCRBY", strKey, score)); err != nil { |
|
err = errors.Wrap(err, "conn.Do(INCRBY)") |
|
return |
|
} |
|
// the score could not more than 1 million |
|
if count > maxNum { |
|
log.Warn("SetMissionTop over max score (%d) error", count) |
|
return |
|
} |
|
rankScore = buildRankScore(count, ctime) |
|
// set top list |
|
if _, err = redis.Bool(conn.Do("ZADD", key, rankScore, lid)); err != nil { |
|
err = errors.Wrapf(err, "conn.Do(ZADD) key(%s)", key) |
|
return |
|
} |
|
if _, err = conn.Do("ZREMRANGEBYRANK", key, 0, -(_maxMissionTop + 1)); err != nil { |
|
err = errors.Wrapf(err, "conn.Do(ZREMRANGEBYRANK) key(%s)", key) |
|
} |
|
return |
|
} |
|
|
|
// MissionLidScore . |
|
func (d *Dao) MissionLidScore(c context.Context, sid, lid int64) (score int64, err error) { |
|
var ( |
|
conn = d.redis.Get(c) |
|
key = likeMissionScoreStrKey(sid, lid) |
|
) |
|
defer conn.Close() |
|
if score, err = redis.Int64(conn.Do("GET", key)); err != nil { |
|
if err == redis.ErrNil { |
|
err = nil |
|
} else { |
|
err = errors.Wrapf(err, "conn.Do(GET) %s", key) |
|
} |
|
} |
|
return |
|
} |
|
|
|
// MissionLidRank . |
|
func (d *Dao) MissionLidRank(c context.Context, sid, lid int64) (rank int64, err error) { |
|
var ( |
|
conn = d.redis.Get(c) |
|
key = likeActMissionScoreKey(sid) |
|
) |
|
defer conn.Close() |
|
if rank, err = redis.Int64(conn.Do("ZREVRANK", key, lid)); err != nil { |
|
if err == redis.ErrNil { |
|
err = nil |
|
rank = -1 |
|
} else { |
|
err = errors.Wrapf(err, "conn.Do(GET) %s", key) |
|
} |
|
} |
|
return |
|
} |
|
|
|
// MissionScoreList score list . |
|
func (d *Dao) MissionScoreList(c context.Context, sid int64, start, end int) (data []int64, err error) { |
|
var ( |
|
key = likeActMissionScoreKey(sid) |
|
conn = d.redis.Get(c) |
|
) |
|
defer conn.Close() |
|
vs, err := redis.Values(conn.Do("ZREVRANGE", key, start, end, "WITHSCORES")) |
|
if err != nil { |
|
PromError("redis:获取MissionScoreList", "conn.Do(ZREVRANGE,%s,%d,%d) error(%v)", key, start, end, err) |
|
return |
|
} |
|
data = make([]int64, 0, len(vs)) |
|
for len(vs) > 0 { |
|
var ( |
|
lid int64 |
|
score int64 |
|
) |
|
if vs, err = redis.Scan(vs, &lid, &score); err != nil { |
|
PromError("redis:获取获取MissionScoreList", "redis.Scan(%v) error(%v)", vs, err) |
|
return |
|
} |
|
if lid != 0 { |
|
data = append(data, lid) |
|
} |
|
} |
|
return |
|
} |
|
|
|
// AddActMission . |
|
func (d *Dao) AddActMission(c context.Context, act *l.ActMissionGroup) (actID int64, err error) { |
|
var res sql.Result |
|
if res, err = d.db.Exec(c, _addLikeActMissionSQL, act.Sid, act.Mid, act.Lid, act.Action, act.IPv6); err != nil { |
|
err = errors.Wrapf(err, "d.db.Exec(%s)", _addLikeActMissionSQL) |
|
return |
|
} |
|
return res.LastInsertId() |
|
} |
|
|
|
// RawActMissionFriends . |
|
func (d *Dao) RawActMissionFriends(c context.Context, sid, lid int64) (res *l.ActMissionGroups, err error) { |
|
rows, err := d.db.Query(c, _likeActMissionFriendsSQL, sid, lid) |
|
if err != nil { |
|
err = errors.Wrapf(err, " d.db.Query(%s)", _likeActMissionFriendsSQL) |
|
return |
|
} |
|
list := make([]*l.ActMissionGroup, 0, 100) |
|
for rows.Next() { |
|
n := &l.ActMissionGroup{} |
|
if err = rows.Scan(&n.ID, &n.Sid, &n.Lid, &n.Mid, &n.Action); err != nil { |
|
err = errors.Wrapf(err, " d.db.rows.Scan(%s)", _likeActMissionFriendsSQL) |
|
return |
|
} |
|
list = append(list, n) |
|
} |
|
res = &l.ActMissionGroups{ActMissionGroups: list} |
|
if err = rows.Err(); err != nil { |
|
err = errors.Wrap(err, "rows.Err()") |
|
} |
|
return |
|
}
|
|
|