Browse Source

Merge remote-tracking branch 'origin/master'

master
liruiqiang 6 days ago
parent
commit
bdd2e32851
  1. 20
      api/vote_record/v1/vote_record.go
  2. 1
      api/vote_record/vote_record.go
  3. 2
      hack/config.yaml
  4. 11
      internal/consts/consts.go
  5. 12
      internal/controller/vote_record/vote_record_v1_get_export_file.go
  6. 2
      internal/dao/internal/article.go
  7. 8
      internal/dao/internal/user.go
  8. 4
      internal/dao/internal/vote_poll.go
  9. 10
      internal/dao/internal/vote_record.go
  10. 21
      internal/logic/vote_record/add_record.go
  11. 87
      internal/logic/vote_record/get_export_file.go
  12. 30
      internal/logic/vote_record/get_vote.go
  13. 36
      internal/logic/vote_record/get_vote_detail.go
  14. 2
      internal/model/do/article.go
  15. 7
      internal/model/do/user.go
  16. 2
      internal/model/do/vote_poll.go
  17. 8
      internal/model/do/vote_record.go
  18. 2
      internal/model/entity/article.go
  19. 15
      internal/model/entity/user.go
  20. 2
      internal/model/entity/vote_poll.go
  21. 14
      internal/model/entity/vote_record.go
  22. 1
      internal/service/vote_record.go
  23. 13
      internal/utils/cachettl.go
  24. 45
      internal/utils/delete_keys.go
  25. 2
      main.go
  26. 12
      manifest/config/config.yaml

20
api/vote_record/v1/vote_record.go

@ -5,9 +5,16 @@ import (
"github.com/gogf/gf/v2/os/gtime"
)
type GetVoteDetailListRes struct {
VoteList []*GetVoteDetailRes `json:"voteList"`
TotalCount int `json:"totalCount"`
type GetExportFileReq struct {
g.Meta `path:"/getExportVoteDetail" method:"get" tags:"获取投票名单列表"`
VoteId int `p:"voteId" v:"required" dc:"投票活动ID"`
Username string `p:"username" dc:"<用户名>"`
Account string `p:"account" dc:"<精网号>"`
Area string `p:"area" dc:"地区"`
OptionContent string `p:"optionContent" dc:"<选项>"`
}
type GetExportFileRes struct {
VoteList []*GetVoteDetailRes `json:"voteList"`
}
type GetVoteDetailReq struct {
g.Meta `path:"/getAllVoteDetail" method:"get" tags:"获取投票名单列表"`
@ -16,6 +23,7 @@ type GetVoteDetailReq struct {
Size int `p:"size" dc:"每页数量" default:"50"`
Username string `p:"username" dc:"<用户名>"`
Account string `p:"account" dc:"<精网号>"`
Area string `p:"area" dc:"地区"`
OptionContent string `p:"optionContent" dc:"<选项>"`
}
@ -24,9 +32,14 @@ type GetVoteDetailRes struct {
Account string `json:"account" dc:"精网号"`
//VoteTitle string `json:"voteTitle" dc:"投票标题"`
//ArticleTitle string `json:"articleTitle" dc:"文章/视频标题"`
Area string `json:"area" dc:"地区"`
OptionContents string `json:"optionContents" dc:"选项名称"`
CreateTime *gtime.Time `json:"createTime" dc:"投票时间"`
}
type GetVoteDetailListRes struct {
VoteList []*GetVoteDetailRes `json:"voteList"`
TotalCount int `json:"totalCount"`
}
type GetVoteReq struct {
g.Meta `path:"/getVote" method:"get" tags:"<获取文章及投票活动>"`
ArticleId int `p:"articleId" v:"required" dc:"<文章>ID"`
@ -61,6 +74,7 @@ type GetIndexRes struct {
type AddRecordReq struct {
g.Meta `path:"/addRecord" method:"post" dc:"<UNK>"`
ArticleId int ` v:"required" json:"articleId" dc:"<<UNK>ID>"`
UserId int `v:"required" json:"userId" dc:"<用户>ID"`
VoteId int `v:"required" json:"voteId" dc:"<投票活动>ID"`
OptionId []int `v:"required" json:"optionId" dc:"<投票选项>ID"`

1
api/vote_record/vote_record.go

@ -11,6 +11,7 @@ import (
)
type IVoteRecordV1 interface {
GetExportFile(ctx context.Context, req *v1.GetExportFileReq) (res *v1.GetExportFileRes, err error)
GetVoteDetail(ctx context.Context, req *v1.GetVoteDetailReq) (res *v1.GetVoteDetailListRes, err error)
GetVote(ctx context.Context, req *v1.GetVoteReq) (res *v1.GetVoteRes, err error)
GetIndex(ctx context.Context, req *v1.GetIndexReq) (res *v1.GetIndexRes, err error)

2
hack/config.yaml

@ -4,7 +4,7 @@
gfcli:
gen:
dao:
- link: "mysql:root:root@tcp(127.0.0.1:3306)/link_test"
- link: "mysql:root:123456@tcp(127.0.0.1:3306)/link_test"
descriptionTag: true
docker:

11
internal/consts/consts.go

@ -1 +1,12 @@
package consts
const (
BASE_TTL = 600
RANDOM_RANGE = 60
)
const (
VOTE_DETAIL = "voteDetail" //投票名单查询
ARTICLE = "article" //文章查询
EXPORT_FILE = "exportFile" //导出数据查询
)

12
internal/controller/vote_record/vote_record_v1_get_export_file.go

@ -0,0 +1,12 @@
package vote_record
import (
"context"
"practice_ArticleVote_Go/internal/service"
"practice_ArticleVote_Go/api/vote_record/v1"
)
func (c *ControllerV1) GetExportFile(ctx context.Context, req *v1.GetExportFileReq) (res *v1.GetExportFileRes, err error) {
return service.NewVoteRecordService().ExportVoteDetail(ctx, req)
}

2
internal/dao/internal/article.go

@ -22,7 +22,7 @@ type ArticleDao struct {
// ArticleColumns defines and stores column names for the table article.
type ArticleColumns struct {
Id string //
UserId string // 用户ID
UserId string //
ArticleTitle string // 文章/视频标题
ArticleContent string // 文章/视频内容
VoteStatus string // 是否发起投票:1发起,0不发起

8
internal/dao/internal/user.go

@ -22,9 +22,10 @@ type UserDao struct {
// UserColumns defines and stores column names for the table user.
type UserColumns struct {
Id string //
Account string // 精网号
Password string // 用户密码
Username string // 用户名
Account string //
Password string //
Username string //
Area string //
Status string //
CreateTime string //
UpdateTime string //
@ -36,6 +37,7 @@ var userColumns = UserColumns{
Account: "account",
Password: "password",
Username: "username",
Area: "area",
Status: "status",
CreateTime: "create_time",
UpdateTime: "update_time",

4
internal/dao/internal/vote_poll.go

@ -27,8 +27,8 @@ type VotePollColumns struct {
MultiOption string // 是否开启多选:1多选,0不多选
DeadlineTime string // 截止时间
CreateTime string //
UpdateTime string //
Status string // 投票活动状态:1:进行中,0已结束
UpdateTime string //
}
// votePollColumns holds the columns for the table vote_poll.
@ -39,8 +39,8 @@ var votePollColumns = VotePollColumns{
MultiOption: "multi_option",
DeadlineTime: "deadline_time",
CreateTime: "create_time",
UpdateTime: "update_time",
Status: "status",
UpdateTime: "update_time",
}
// NewVotePollDao creates and returns a new DAO object for table data access.

10
internal/dao/internal/vote_record.go

@ -22,11 +22,11 @@ type VoteRecordDao struct {
// VoteRecordColumns defines and stores column names for the table vote_record.
type VoteRecordColumns struct {
Id string //
UserId string // 用户ID
VoteId string // 投票活动ID
OptionId string // 投票选项ID
VoteIndex string // 已投票次数
UserId string //
VoteId string //
OptionId string //
CreateTime string //
VoteIndex string //
UpdateTime string //
}
@ -36,8 +36,8 @@ var voteRecordColumns = VoteRecordColumns{
UserId: "user_id",
VoteId: "vote_id",
OptionId: "option_id",
VoteIndex: "vote_index",
CreateTime: "create_time",
VoteIndex: "vote_index",
UpdateTime: "update_time",
}

21
internal/logic/vote_record/add_record.go

@ -2,10 +2,14 @@ package vote_record
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
v1 "practice_ArticleVote_Go/api/vote_record/v1"
"practice_ArticleVote_Go/internal/consts"
"practice_ArticleVote_Go/internal/dao"
"practice_ArticleVote_Go/internal/model/do"
"practice_ArticleVote_Go/internal/utils"
)
func (l *VoteRecordLogic) AddRecord(ctx context.Context, req *v1.AddRecordReq) (res *v1.AddRecordRes, err error) {
@ -22,19 +26,16 @@ func (l *VoteRecordLogic) AddRecord(ctx context.Context, req *v1.AddRecordReq) (
})
}
_, err = dao.VoteRecord.Ctx(ctx).Data(records).Insert()
//_, err = dao.VoteRecord.
// Ctx(ctx).
// Data(do.VoteRecord{
// UserId: req.UserId,
// VoteId: req.VoteId,
// OptionId: req.OptionId,
// VoteIndex: req.VoteIndex,
// CreateTime: gtime.Now(),
// UpdateTime: gtime.Now(),
// }).Insert()
if err != nil {
return nil, err
}
voteDetailPattern := fmt.Sprintf(consts.VOTE_DETAIL+":%d:*", req.VoteId)
_, err = utils.DeleteKeys(ctx, voteDetailPattern)
exportFilePattern := fmt.Sprintf(consts.EXPORT_FILE+":%d:*", req.VoteId)
_, err = utils.DeleteKeys(ctx, exportFilePattern)
articleAndVote := fmt.Sprintf(consts.ARTICLE+":%d", req.ArticleId)
redis := g.Redis()
_, err = redis.Del(ctx, articleAndVote)
res = &v1.AddRecordRes{}
return res, nil
}

87
internal/logic/vote_record/get_export_file.go

@ -0,0 +1,87 @@
package vote_record
import (
"context"
"encoding/json"
"fmt"
"github.com/gogf/gf/v2/frame/g"
v1 "practice_ArticleVote_Go/api/vote_record/v1"
"practice_ArticleVote_Go/internal/consts"
"practice_ArticleVote_Go/internal/utils"
)
func (l *VoteRecordLogic) ExportVoteDetail(ctx context.Context, req *v1.GetExportFileReq) (res *v1.GetExportFileRes, err error) {
redis := g.Redis()
cacheKey := fmt.Sprintf(
consts.EXPORT_FILE+":%d:%s:%s:%s:%s",
req.VoteId, req.Username, req.Account, req.Area, req.OptionContent,
)
data, _ := redis.Get(ctx, cacheKey)
fmt.Println("data", data)
if data != nil {
var cached v1.GetExportFileRes
err = json.Unmarshal([]byte(data.String()), &cached)
if err == nil {
return &cached, nil
}
}
query := `
SELECT
u.username,
u.account,
u.area,
uv.option_contents,
uv.create_time
FROM (
SELECT
vr.user_id,
vr.vote_index,
DATE(vr.create_time) AS vote_date,
MAX(vr.create_time) AS create_time,
GROUP_CONCAT(o.option_content ORDER BY o.id SEPARATOR ',') AS option_contents
FROM vote_record vr
JOIN vote_option o
ON vr.option_id = o.id
WHERE vr.vote_id = ?
GROUP BY vr.user_id, vr.vote_index, vote_date
) AS uv
JOIN user u ON u.id = uv.user_id
WHERE 1=1
`
conditions := []interface{}{req.VoteId}
if req.OptionContent != "" {
query += " AND uv.option_contents LIKE ?"
conditions = append(conditions, "%"+req.OptionContent+"%")
}
if req.Username != "" {
query += " AND u.username LIKE ?"
conditions = append(conditions, "%"+req.Username+"%")
}
if req.Account != "" {
query += " AND u.account LIKE ?"
conditions = append(conditions, "%"+req.Account+"%")
}
if req.Area != "" {
query += " AND u.area LIKE ?"
conditions = append(conditions, "%"+req.Area+"%")
}
query += " ORDER BY uv.create_time DESC "
var voteList []*v1.GetVoteDetailRes
err = g.DB().Ctx(ctx).
Raw(query, conditions...).
Scan(&voteList)
if err != nil {
return nil, err
}
res = &v1.GetExportFileRes{
VoteList: voteList,
}
buf, err := json.Marshal(res)
if err == nil {
ttl := utils.GetCacheTTL()
_ = redis.SetEX(ctx, cacheKey, string(buf), int64(ttl))
}
return res, err
}

30
internal/logic/vote_record/get_vote.go

@ -2,15 +2,34 @@ package vote_record
import (
"context"
"encoding/json"
"fmt"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
v1 "practice_ArticleVote_Go/api/vote_record/v1"
"practice_ArticleVote_Go/internal/consts"
"practice_ArticleVote_Go/internal/dao"
"practice_ArticleVote_Go/internal/utils"
)
func (l *VoteRecordLogic) GetVote(ctx context.Context, req *v1.GetVoteReq) (res *v1.GetVoteRes, err error) {
redis := g.Redis()
cacheKey := fmt.Sprintf(
consts.ARTICLE+":%d",
req.ArticleId,
)
fmt.Println(cacheKey)
data, _ := redis.Get(ctx, cacheKey)
fmt.Println("data", data)
if data != nil {
var cached v1.GetVoteRes
err = json.Unmarshal([]byte(data.String()), &cached)
if err == nil {
return &cached, nil
}
}
articleRow, err := dao.Article.Ctx(ctx).
Fields(
dao.Article.Columns().ArticleTitle,
@ -58,10 +77,10 @@ func (l *VoteRecordLogic) GetVote(ctx context.Context, req *v1.GetVoteReq) (res
res.DeadlineTime = votePoll[dao.VotePoll.Columns().DeadlineTime].GTime()
res.ParticipationNumber = votePoll["totalCount"].Int()
res.VotePollStatus = votePoll[dao.VotePoll.Columns().Status].Int()
if res.DeadlineTime.Before(gtime.Now()) && res.VotePollStatus != 0 {
res.VotePollStatus = 0
if res.DeadlineTime.Before(gtime.Now()) && res.VotePollStatus != 2 {
res.VotePollStatus = 2
_, err = dao.VotePoll.Ctx(ctx).Data(g.Map{
dao.VotePoll.Columns().Status: 0,
dao.VotePoll.Columns().Status: 2,
}).WherePri(res.VoteId).Update()
if err != nil {
return nil, err
@ -87,5 +106,10 @@ func (l *VoteRecordLogic) GetVote(ctx context.Context, req *v1.GetVoteReq) (res
OrderAsc(dao.VoteOption.Columns().OptionIndex).
Scan(&res.OptionList)
}
buf, err := json.Marshal(res)
if err == nil {
ttl := utils.GetCacheTTL()
_ = redis.SetEX(ctx, cacheKey, string(buf), int64(ttl))
}
return res, nil
}

36
internal/logic/vote_record/get_vote_detail.go

@ -2,9 +2,12 @@ package vote_record
import (
"context"
"encoding/json"
"fmt"
"github.com/gogf/gf/v2/frame/g"
v1 "practice_ArticleVote_Go/api/vote_record/v1"
"practice_ArticleVote_Go/internal/consts"
"practice_ArticleVote_Go/internal/utils"
)
func (l *VoteRecordLogic) GetVoteDetail(ctx context.Context, req *v1.GetVoteDetailReq) (res *v1.GetVoteDetailListRes, err error) {
@ -42,10 +45,27 @@ func (l *VoteRecordLogic) GetVoteDetail(ctx context.Context, req *v1.GetVoteDeta
// return nil, err
//}
//return res, nil
redis := g.Redis()
cacheKey := fmt.Sprintf(
consts.VOTE_DETAIL+":%d:%d:%d:%s:%s:%s:%s",
req.VoteId, req.Page, req.Size,
req.Username, req.Account, req.Area, req.OptionContent,
)
fmt.Println(cacheKey)
data, _ := redis.Get(ctx, cacheKey)
fmt.Println("data", data)
if data != nil {
var cached v1.GetVoteDetailListRes
err = json.Unmarshal([]byte(data.String()), &cached)
if err == nil {
return &cached, nil
}
}
query := `
SELECT
u.username,
u.account,
u.area,
uv.option_contents,
uv.create_time
FROM (
@ -61,13 +81,10 @@ func (l *VoteRecordLogic) GetVoteDetail(ctx context.Context, req *v1.GetVoteDeta
WHERE vr.vote_id = ?
GROUP BY vr.user_id, vr.vote_index, vote_date
) AS uv
JOIN ` + "`user`" + ` u
ON u.id = uv.user_id
WHERE 1=1
JOIN user u ON u.id = uv.user_id
WHERE 1=1
`
conditions := []interface{}{req.VoteId}
if req.OptionContent != "" {
query += " AND uv.option_contents LIKE ?"
conditions = append(conditions, "%"+req.OptionContent+"%")
@ -80,6 +97,10 @@ func (l *VoteRecordLogic) GetVoteDetail(ctx context.Context, req *v1.GetVoteDeta
query += " AND u.account LIKE ?"
conditions = append(conditions, "%"+req.Account+"%")
}
if req.Area != "" {
query += " AND u.area LIKE ?"
conditions = append(conditions, "%"+req.Area+"%")
}
countQuery := "SELECT COUNT(*) AS cnt FROM ( " + query + " ) AS subquery"
var cntResult struct{ Cnt int }
err = g.DB().Ctx(ctx).Raw(countQuery, conditions...).Scan(&cntResult)
@ -98,5 +119,10 @@ func (l *VoteRecordLogic) GetVoteDetail(ctx context.Context, req *v1.GetVoteDeta
return nil, err
}
res.VoteList = voteList
buf, merr := json.Marshal(res)
if merr == nil {
ttl := utils.GetCacheTTL()
_ = redis.SetEX(ctx, cacheKey, string(buf), int64(ttl))
}
return res, nil
}

2
internal/model/do/article.go

@ -13,7 +13,7 @@ import (
type Article struct {
g.Meta `orm:"table:article, do:true"`
Id interface{} //
UserId interface{} // 用户ID
UserId interface{} //
ArticleTitle interface{} // 文章/视频标题
ArticleContent interface{} // 文章/视频内容
VoteStatus interface{} // 是否发起投票:1发起,0不发起

7
internal/model/do/user.go

@ -13,9 +13,10 @@ import (
type User struct {
g.Meta `orm:"table:user, do:true"`
Id interface{} //
Account interface{} // 精网号
Password interface{} // 用户密码
Username interface{} // 用户名
Account interface{} //
Password interface{} //
Username interface{} //
Area interface{} //
Status interface{} //
CreateTime *gtime.Time //
UpdateTime *gtime.Time //

2
internal/model/do/vote_poll.go

@ -18,6 +18,6 @@ type VotePoll struct {
MultiOption interface{} // 是否开启多选:1多选,0不多选
DeadlineTime *gtime.Time // 截止时间
CreateTime *gtime.Time //
UpdateTime *gtime.Time //
Status interface{} // 投票活动状态:1:进行中,0已结束
UpdateTime *gtime.Time //
}

8
internal/model/do/vote_record.go

@ -13,10 +13,10 @@ import (
type VoteRecord struct {
g.Meta `orm:"table:vote_record, do:true"`
Id interface{} //
UserId interface{} // 用户ID
VoteId interface{} // 投票活动ID
OptionId interface{} // 投票选项ID
VoteIndex interface{} // 已投票次数
UserId interface{} //
VoteId interface{} //
OptionId interface{} //
CreateTime *gtime.Time //
VoteIndex interface{} //
UpdateTime *gtime.Time //
}

2
internal/model/entity/article.go

@ -11,7 +11,7 @@ import (
// Article is the golang structure for table article.
type Article struct {
Id int64 `json:"id" orm:"id" description:""` //
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
UserId int64 `json:"userId" orm:"user_id" description:""` //
ArticleTitle string `json:"articleTitle" orm:"article_title" description:"文章/视频标题"` // 文章/视频标题
ArticleContent string `json:"articleContent" orm:"article_content" description:"文章/视频内容"` // 文章/视频内容
VoteStatus int `json:"voteStatus" orm:"vote_status" description:"是否发起投票:1发起,0不发起"` // 是否发起投票:1发起,0不发起

15
internal/model/entity/user.go

@ -10,11 +10,12 @@ import (
// User is the golang structure for table user.
type User struct {
Id int64 `json:"id" orm:"id" description:""` //
Account string `json:"account" orm:"account" description:"精网号"` // 精网号
Password string `json:"password" orm:"password" description:"用户密码"` // 用户密码
Username string `json:"username" orm:"username" description:"用户名"` // 用户名
Status uint `json:"status" orm:"status" description:""` //
CreateTime *gtime.Time `json:"createTime" orm:"create_time" description:""` //
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
Id int64 `json:"id" orm:"id" description:""` //
Account string `json:"account" orm:"account" description:""` //
Password string `json:"password" orm:"password" description:""` //
Username string `json:"username" orm:"username" description:""` //
Area string `json:"area" orm:"area" description:""` //
Status uint `json:"status" orm:"status" description:""` //
CreateTime *gtime.Time `json:"createTime" orm:"create_time" description:""` //
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
}

2
internal/model/entity/vote_poll.go

@ -16,6 +16,6 @@ type VotePoll struct {
MultiOption int `json:"multiOption" orm:"multi_option" description:"是否开启多选:1多选,0不多选"` // 是否开启多选:1多选,0不多选
DeadlineTime *gtime.Time `json:"deadlineTime" orm:"deadline_time" description:"截止时间"` // 截止时间
CreateTime *gtime.Time `json:"createTime" orm:"create_time" description:""` //
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
Status int `json:"status" orm:"status" description:"投票活动状态:1:进行中,0已结束"` // 投票活动状态:1:进行中,0已结束
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
}

14
internal/model/entity/vote_record.go

@ -10,11 +10,11 @@ import (
// VoteRecord is the golang structure for table vote_record.
type VoteRecord struct {
Id int64 `json:"id" orm:"id" description:""` //
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
VoteId int64 `json:"voteId" orm:"vote_id" description:"投票活动ID"` // 投票活动ID
OptionId int64 `json:"optionId" orm:"option_id" description:"投票选项ID"` // 投票选项ID
VoteIndex int `json:"voteIndex" orm:"vote_index" description:"已投票次数"` // 已投票次数
CreateTime *gtime.Time `json:"createTime" orm:"create_time" description:""` //
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
Id int64 `json:"id" orm:"id" description:""` //
UserId int64 `json:"userId" orm:"user_id" description:""` //
VoteId int64 `json:"voteId" orm:"vote_id" description:""` //
OptionId int64 `json:"optionId" orm:"option_id" description:""` //
CreateTime *gtime.Time `json:"createTime" orm:"create_time" description:""` //
VoteIndex int `json:"voteIndex" orm:"vote_index" description:""` //
UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" description:""` //
}

1
internal/service/vote_record.go

@ -7,6 +7,7 @@ import (
)
type IVoteRecord interface {
ExportVoteDetail(ctx context.Context, req *v1.GetExportFileReq) (res *v1.GetExportFileRes, err error)
GetIndex(ctx context.Context, req *v1.GetIndexReq) (res *v1.GetIndexRes, err error)
AddRecord(ctx context.Context, req *v1.AddRecordReq) (res *v1.AddRecordRes, err error)
GetVote(ctx context.Context, req *v1.GetVoteReq) (res *v1.GetVoteRes, err error)

13
internal/utils/cachettl.go

@ -0,0 +1,13 @@
package utils
import (
"math/rand"
"practice_ArticleVote_Go/internal/consts"
"time"
)
func GetCacheTTL() time.Duration {
baseTTL := consts.BASE_TTL
randomNumber := rand.Intn(consts.RANDOM_RANGE)
return time.Duration(baseTTL+randomNumber) * time.Second
}

45
internal/utils/delete_keys.go

@ -0,0 +1,45 @@
package utils
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
func DeleteKeys(ctx context.Context, pattern string) (int, error) {
redis := g.Redis()
var (
cursor uint64
totalKeys int
batchSize = 100
)
g.Log().Debugf(ctx, "开始删除匹配模式 %q 的缓存键", pattern)
for {
result, err := redis.Do(ctx, "SCAN", cursor, "MATCH", pattern, "COUNT", batchSize)
if err != nil {
return totalKeys, fmt.Errorf("SCAN 失败: %v", err)
}
arr := result.Array()
fmt.Println("arr:", arr)
cursor = gconv.Uint64(arr[0])
rawKeys := gconv.Strings(arr[1])
var keys []string
for _, k := range rawKeys {
keys = append(keys, k)
}
fmt.Println("keys:", keys)
if len(keys) > 0 {
deleted, err := redis.Del(ctx, keys...)
if err != nil {
g.Log().Warningf(ctx, "缓存删除异常: %v", err)
}
totalKeys += int(deleted)
g.Log().Debugf(ctx, "本次删除 %d/%d 个键", deleted, len(keys))
}
if cursor == 0 {
break
}
}
return totalKeys, nil
}

2
main.go

@ -9,6 +9,8 @@ import (
"github.com/gogf/gf/v2/os/gctx"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
"practice_ArticleVote_Go/internal/cmd"
)

12
manifest/config/config.yaml

@ -14,4 +14,14 @@ database:
default:
link: "mysql:root:root@tcp(127.0.0.1:3306)/link_test?loc=Local&parseTime=true"
createdAt: "create_time"
updatedAt: "update_time"
updatedAt: "update_time"
redis:
default: # 默认实例,用于常规操作
address: "127.0.0.1:6379"
db: 0
password: ""
cache: # 缓存专用实例
address: "127.0.0.1:6379"
db: 1
password: ""
Loading…
Cancel
Save