Feat: room hot list use heap

pull/24/head
zijiren233 2 years ago
parent b596d9ea03
commit 16bd51fa81

@ -8,6 +8,7 @@ import (
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
synccache "github.com/synctv-org/synctv/utils/syncCache"
"github.com/zijiren233/gencontainer/heap"
)
var roomTTL = time.Hour * 24 * 2
@ -150,3 +151,57 @@ func GetAllRoomsInCacheWithoutHidden() []*Room {
})
return rooms
}
type RoomHeapItem struct {
ID uint
RoomName string
ClientNum int64
NeedPassword bool
CreatorID uint
CreatedAt time.Time
}
type RoomHeap []*RoomHeapItem
func (h RoomHeap) Len() int {
return len(h)
}
func (h RoomHeap) Less(i, j int) bool {
return h[i].ClientNum < h[j].ClientNum
}
func (h RoomHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h *RoomHeap) Push(x *RoomHeapItem) {
*h = append(*h, x)
}
func (h *RoomHeap) Pop() *RoomHeapItem {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func GetRoomHeapInCacheWithoutHidden() RoomHeap {
rooms := make(RoomHeap, 0)
roomCache.Range(func(key uint, value *synccache.Entry[*Room]) bool {
v := value.Value()
if !v.Settings.Hidden {
heap.Push[*RoomHeapItem](&rooms, &RoomHeapItem{
ID: v.ID,
RoomName: v.Name,
ClientNum: v.ClientNum(),
NeedPassword: v.NeedPassword(),
CreatorID: v.CreatorID,
CreatedAt: v.CreatedAt,
})
}
return true
})
return rooms
}

@ -13,7 +13,6 @@ import (
"github.com/synctv-org/synctv/server/middlewares"
"github.com/synctv-org/synctv/server/model"
"github.com/synctv-org/synctv/utils"
"github.com/zijiren233/gencontainer/vec"
"gorm.io/gorm"
)
@ -75,31 +74,23 @@ func RoomHotList(ctx *gin.Context) {
return
}
r := op.GetAllRoomsInCacheWithoutHidden()
rs := vec.New[*model.RoomListResp](vec.WithCmpLess[*model.RoomListResp](func(v1, v2 *model.RoomListResp) bool {
return v1.PeopleNum < v2.PeopleNum
}), vec.WithCmpEqual[*model.RoomListResp](func(v1, v2 *model.RoomListResp) bool {
return v1.PeopleNum == v2.PeopleNum
}))
for _, v := range r {
rs.Push(&model.RoomListResp{
r := op.GetRoomHeapInCacheWithoutHidden()
rs := utils.GetPageItems(r, page, pageSize)
resp := make([]*model.RoomListResp, len(rs))
for i, v := range rs {
resp[i] = &model.RoomListResp{
RoomId: v.ID,
RoomName: v.Name,
PeopleNum: v.ClientNum(),
NeedPassword: v.NeedPassword(),
Creator: op.GetUserName(v.Room.CreatorID),
CreatedAt: v.Room.CreatedAt.UnixMilli(),
})
}
rs.SortStable()
if ctx.DefaultQuery("sort", "desc") == "desc" {
rs.Reverse()
RoomName: v.RoomName,
PeopleNum: v.ClientNum,
NeedPassword: v.NeedPassword,
Creator: op.GetUserName(v.CreatorID),
CreatedAt: v.CreatedAt.UnixMilli(),
}
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"total": rs.Len(),
"list": utils.GetPageItems(rs.Slice(), page, pageSize),
"total": len(r),
"list": rs,
}))
}

@ -35,18 +35,10 @@ func NewSyncCache[K comparable, V any](trimTime time.Duration, conf ...SyncCache
return sc
}
func (sc *SyncCache[K, V]) Releases() {
sc.ticker.Stop()
sc.cache.Clear()
}
func (sc *SyncCache[K, V]) trim() {
sc.cache.Range(func(key K, value *Entry[V]) bool {
if value.IsExpired() {
sc.cache.CompareAndDelete(key, value)
if sc.deletedCallback != nil {
sc.deletedCallback(value.value)
}
sc.CompareAndDelete(key, value)
}
return true
})
@ -61,33 +53,19 @@ func (sc *SyncCache[K, V]) Load(key K) (value *Entry[V], loaded bool) {
if ok && !e.IsExpired() {
return e, ok
}
sc.CompareAndDelete(key, e)
return
}
func (sc *SyncCache[K, V]) LoadOrStore(key K, value V, expire time.Duration) (actual *Entry[V], loaded bool) {
e, loaded := sc.cache.LoadOrStore(key, NewEntry[V](value, expire))
if e.IsExpired() {
e = NewEntry[V](value, expire)
sc.cache.Store(key, e)
return e, false
if loaded && e.IsExpired() {
sc.CompareAndDelete(key, e)
return sc.LoadOrStore(key, value, expire)
}
return e, loaded
}
func (sc *SyncCache[K, V]) AddExpiration(key K, d time.Duration) {
e, ok := sc.cache.Load(key)
if ok {
e.AddExpiration(d)
}
}
func (sc *SyncCache[K, V]) SetExpiration(key K, t time.Time) {
e, ok := sc.cache.Load(key)
if ok {
e.SetExpiration(t)
}
}
func (sc *SyncCache[K, V]) Delete(key K) {
sc.LoadAndDelete(key)
}
@ -117,6 +95,7 @@ func (sc *SyncCache[K, V]) Range(f func(key K, value *Entry[V]) bool) {
if !value.IsExpired() {
return f(key, value)
}
sc.cache.CompareAndDelete(key, value)
return true
})
}

Loading…
Cancel
Save