Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
package configser
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const rankLimit = 48
|
||||
|
||||
// NormalizeRankPage 榜单分页:页码从 1 起,pageSize 不是 rankLimit 时强制改为 rankLimit。
|
||||
func NormalizeRankPage(pageNum, pageSize int64) (int64, int64) {
|
||||
if pageNum <= 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
if pageSize != int64(rankLimit) {
|
||||
pageSize = int64(rankLimit)
|
||||
}
|
||||
return pageNum, pageSize
|
||||
}
|
||||
|
||||
type periodRankCache[T any] struct {
|
||||
Lock sync.RWMutex
|
||||
Total []T
|
||||
Week []T
|
||||
Month []T
|
||||
Year []T
|
||||
}
|
||||
|
||||
func (c *periodRankCache[T]) hasAny() bool {
|
||||
c.Lock.RLock()
|
||||
defer c.Lock.RUnlock()
|
||||
return len(c.Total) > 0 || len(c.Week) > 0 || len(c.Month) > 0 || len(c.Year) > 0
|
||||
}
|
||||
|
||||
func (c *periodRankCache[T]) pick(p RankPeriod) []T {
|
||||
switch p {
|
||||
case RankPeriodWeek:
|
||||
return c.Week
|
||||
case RankPeriodMonth:
|
||||
return c.Month
|
||||
case RankPeriodYear:
|
||||
return c.Year
|
||||
default:
|
||||
return c.Total
|
||||
}
|
||||
}
|
||||
|
||||
func (c *periodRankCache[T]) replace(total, week, month, year []T) {
|
||||
c.Lock.Lock()
|
||||
c.Total, c.Week, c.Month, c.Year = total, week, month, year
|
||||
c.Lock.Unlock()
|
||||
}
|
||||
|
||||
func (c *periodRankCache[T]) get(p RankPeriod, limit int, refreshIfEmpty func()) []T {
|
||||
c.Lock.RLock()
|
||||
list := c.pick(p)
|
||||
empty := len(list) == 0
|
||||
c.Lock.RUnlock()
|
||||
if empty {
|
||||
refreshIfEmpty()
|
||||
c.Lock.RLock()
|
||||
list = c.pick(p)
|
||||
c.Lock.RUnlock()
|
||||
}
|
||||
return sliceLimit(list, limit)
|
||||
}
|
||||
|
||||
func sliceLimit[T any](s []T, limit int) []T {
|
||||
if limit <= 0 || limit >= len(s) {
|
||||
return s
|
||||
}
|
||||
return s[:limit]
|
||||
}
|
||||
|
||||
// SliceRankPage 对榜单缓存做分页切片
|
||||
func SliceRankPage[T any](all []T, pageNum, pageSize int64) []T {
|
||||
if pageNum <= 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
return []T{}
|
||||
}
|
||||
start := (pageNum - 1) * pageSize
|
||||
if start >= int64(len(all)) {
|
||||
return []T{}
|
||||
}
|
||||
end := start + pageSize
|
||||
if end > int64(len(all)) {
|
||||
end = int64(len(all))
|
||||
}
|
||||
return append([]T{}, all[start:end]...)
|
||||
}
|
||||
|
||||
func contentLikeRankPipeline(statusField string, statusVal interface{}, realLikes, fakeLikes, updatedAt, idField string, limit int64) []bson.M {
|
||||
return []bson.M{
|
||||
{"$match": bson.M{statusField: statusVal}},
|
||||
{"$addFields": bson.M{"rankScore": bson.M{"$add": []interface{}{
|
||||
bson.M{"$ifNull": []interface{}{"$" + realLikes, 0}},
|
||||
bson.M{"$ifNull": []interface{}{"$" + fakeLikes, 0}},
|
||||
}}}},
|
||||
{"$match": bson.M{"rankScore": bson.M{"$gt": 0}}},
|
||||
{"$sort": bson.D{
|
||||
{Key: "rankScore", Value: -1},
|
||||
{Key: updatedAt, Value: -1},
|
||||
{Key: idField, Value: -1},
|
||||
}},
|
||||
{"$limit": limit},
|
||||
}
|
||||
}
|
||||
|
||||
func contentWatchRankOpts(watchField, updatedAt, idField string, limit int64) *options.FindOptions {
|
||||
return options.Find().
|
||||
SetSort(bson.D{
|
||||
{Key: watchField, Value: -1},
|
||||
{Key: updatedAt, Value: -1},
|
||||
{Key: idField, Value: -1},
|
||||
}).
|
||||
SetLimit(limit)
|
||||
}
|
||||
|
||||
func contentRankFillPipeline(idField, statusField string, statusVal interface{}, excludeIds []int64, needFill int64) []bson.M {
|
||||
return []bson.M{
|
||||
{"$match": bson.M{
|
||||
idField: bson.M{"$nin": excludeIds},
|
||||
statusField: statusVal,
|
||||
}},
|
||||
{"$sample": bson.M{"size": needFill}},
|
||||
}
|
||||
}
|
||||
|
||||
func periodWatchNum(p RankPeriod, week, month, year, total int64) int64 {
|
||||
switch p {
|
||||
case RankPeriodWeek:
|
||||
return week
|
||||
case RankPeriodMonth:
|
||||
return month
|
||||
case RankPeriodYear:
|
||||
return year
|
||||
default:
|
||||
return total
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user