🎨 class RedisClient in single file

This commit is contained in:
Havoc412 2024-11-18 18:35:10 +08:00
parent 6f97245961
commit 18ef3f2bce
3 changed files with 96 additions and 29 deletions

View File

@ -11,9 +11,7 @@ import (
"catface/app/service/animals/curd"
"catface/app/service/upload_file"
"catface/app/utils/query_handler"
"catface/app/utils/redis_factory"
"catface/app/utils/response"
"encoding/json"
"os"
"path/filepath"
"strconv"
@ -39,23 +37,17 @@ func (a *Animals) List(context *gin.Context) {
mode := context.GetString(consts.ValidatorPrefix + "mode")
// TAG prefer MODE 查询模式。
var key int64
var redis_selctedCatsId model_redis.SelectedAnimal4Prefer
var animalsWithLike []model.AnimalWithLikeList
if mode == consts.AnimalPreferMode {
key = int64(context.GetFloat64(consts.ValidatorPrefix + "key"))
redis_selctedCatsId.Key = key
key := int64(context.GetFloat64(consts.ValidatorPrefix + "key"))
redisClient := redis_factory.GetOneRedisClient()
defer redisClient.ReleaseOneRedisClient()
if key != 0 {
if res, err := redisClient.String(redisClient.Execute("get", key)); err == nil {
json.Unmarshal([]byte(res), &redis_selctedCatsId)
} else {
_ = err
if ok, err := redis_selctedCatsId.GetDataByKey(key); !ok {
_ = err // TODO
}
} else {
key = variable.SnowFlake.GetId()
redis_selctedCatsId.GenerateKey()
}
if redis_selctedCatsId.Length() == skip {
@ -65,10 +57,8 @@ func (a *Animals) List(context *gin.Context) {
}
// TODO 刷新 Redis 有效期
if value, err := json.Marshal(redis_selctedCatsId); err == nil {
if _, err := redisClient.String(redisClient.Execute("set", key, string(value))); err != nil {
// TODO
}
if ok, err := redis_selctedCatsId.SetDataByKey(); !ok {
_ = err // TODO
}
}
}
@ -85,7 +75,7 @@ func (a *Animals) List(context *gin.Context) {
if animalsWithLike != nil {
response.Success(context, consts.CurdStatusOkMsg, gin.H{
"animals": animalsWithLike,
"key": key,
"key": redis_selctedCatsId.GetKey(),
})
} else {
response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], errcode.ErrMsgForUser[errcode.AnimalNoFind])
@ -106,7 +96,7 @@ func getPreferCats(userId, num int, attrs string, redis *model_redis.SelectedAni
// STAGE #2 获取近期新增的毛茸茸;只在第一次操作 && 数量不够时 启用。
var idsNew []int64
if !redis.PassNew() && len(ids) < num {
if redis.NotPassNew() { // UPDATE && len(ids) < num 调整为第一次访问时一定会次优先返回 NewCats 的推荐。
// 获取近期新增的毛茸茸
newCats, _ := model.CreateAnimalFactory("").NewCatsId(3, 0) // INFO 硬编码获取最新的 3 个。

View File

@ -180,15 +180,47 @@ func (e *Encounter) ShowByIDs(ids []int64, attrs ...string) (temp []Encounter) {
* @return {*}
*/
func (e *Encounter) EncounteredCatsId(user_id, num, skip int, notInIds []int64) ([]int64, error) {
sql := `SELECT DISTINCT eal.animal_id
FROM encounter_animal_links eal
JOIN encounters e
ON e.id = eal.encounter_id AND e.user_id = ?
WHERE e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
ORDER BY e.updated_at DESC
LIMIT ? OFFSET ?`
var sqlBuilder strings.Builder
rows, err := e.Raw(sql, user_id, num, skip).Rows()
sqlBuilder.WriteString(`
SELECT DISTINCT eal.animal_id
FROM encounter_animal_links eal
JOIN encounters e
ON e.id = eal.encounter_id
WHERE e.user_id = ?
AND e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
`)
if len(notInIds) > 0 {
sqlBuilder.WriteString(`
AND eal.animal_id NOT IN (?)
`)
}
sqlBuilder.WriteString(`
ORDER BY e.updated_at DESC
LIMIT ? OFFSET ?
`)
// sql := `SELECT DISTINCT eal.animal_id
// FROM encounter_animal_links eal
// JOIN encounters e
// ON e.id = eal.encounter_id AND e.user_id = ?
// WHERE e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
// ORDER BY e.updated_at DESC
// LIMIT ? OFFSET ?`
// Exe SQL
sql := sqlBuilder.String()
var rowsRaw *gorm.DB
if len(notInIds) > 0 {
rowsRaw = e.Raw(sql, user_id, notInIds, num, skip)
} else {
rowsRaw = e.Raw(sql, user_id, num, skip)
}
rows, err := rowsRaw.Rows()
if err != nil {
log.Println("查询失败:", err)
return nil, err

View File

@ -1,15 +1,23 @@
package model_redis
import (
"catface/app/global/variable"
"catface/app/utils/redis_factory"
"encoding/json"
)
// INFO 辅助 animal - list - prefer 模式下的查询特化。
type SelectedAnimal4Prefer struct {
Key int64 `json:"-"` // redis 的 key 值
EncounteredCatsId []int64 `json:"encountered_cats_id"` // #1 对应第一阶段:近期路遇关联
NewCatsId []int64 `json:"new_cats_id"` // #2 对应第二阶段:近期新增
key int64 `json:"-"` // redis 的 key 值
notPassNewCat bool `json:"-"`
}
func (s *SelectedAnimal4Prefer) PassNew() bool {
return s.Key != 0
func (s *SelectedAnimal4Prefer) NotPassNew() bool {
return s.notPassNewCat
}
func (s *SelectedAnimal4Prefer) Length() int {
@ -29,3 +37,40 @@ func (s *SelectedAnimal4Prefer) AppendEncIds(ids []int64) {
s.EncounteredCatsId = append(s.EncounteredCatsId, int64(id))
}
}
// BASE CURD
func (s *SelectedAnimal4Prefer) GenerateKey() int64 { // TODO 之后迁移到 model_redis 的基类去。
s.key = variable.SnowFlake.GetId()
s.notPassNewCat = true
return s.key
}
func (s *SelectedAnimal4Prefer) GetKey() int64 { // TODO 同上
return s.key
}
func (s *SelectedAnimal4Prefer) GetDataByKey(key int64) (bool, error) {
s.key = key
redisClient := redis_factory.GetOneRedisClient()
defer redisClient.ReleaseOneRedisClient()
if res, err := redisClient.String(redisClient.Execute("get", key)); err == nil {
json.Unmarshal([]byte(res), s)
return true, nil
} else {
return false, err
}
}
func (s *SelectedAnimal4Prefer) SetDataByKey() (bool, error) {
redisClient := redis_factory.GetOneRedisClient()
defer redisClient.ReleaseOneRedisClient()
data, _ := json.Marshal(s)
if _, err := redisClient.Execute("set", s.key, data); err == nil {
return true, nil
} else {
return false, err
}
}