Feat: slice sort stable

pull/44/head
zijiren233 2 years ago
parent a54996aca5
commit 57a1c88eae

@ -5,9 +5,10 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"time" "slices"
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/maruel/natural"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/synctv-org/synctv/cmd/flags" "github.com/synctv-org/synctv/cmd/flags"
"github.com/synctv-org/synctv/internal/conf" "github.com/synctv-org/synctv/internal/conf"
@ -18,7 +19,6 @@ import (
"github.com/synctv-org/synctv/internal/settings" "github.com/synctv-org/synctv/internal/settings"
"github.com/synctv-org/synctv/utils" "github.com/synctv-org/synctv/utils"
"github.com/zijiren233/gencontainer/refreshcache" "github.com/zijiren233/gencontainer/refreshcache"
"github.com/zijiren233/gencontainer/vec"
) )
var ProviderGroupSettings = make(map[model.SettingGroup]*ProviderGroupSetting) var ProviderGroupSettings = make(map[model.SettingGroup]*ProviderGroupSetting)
@ -34,17 +34,23 @@ type ProviderGroupSetting struct {
var ( var (
Oauth2EnabledCache = refreshcache.NewRefreshCache[[]provider.OAuth2Provider](func(context.Context, ...any) ([]provider.OAuth2Provider, error) { Oauth2EnabledCache = refreshcache.NewRefreshCache[[]provider.OAuth2Provider](func(context.Context, ...any) ([]provider.OAuth2Provider, error) {
a := vec.New[provider.OAuth2Provider](vec.WithCmpEqual[provider.OAuth2Provider](func(v1, v2 provider.OAuth2Provider) bool { ps := providers.EnabledProvider()
return v1 == v2 r := make([]provider.OAuth2Provider, 0, ps.Len())
}), vec.WithCmpLess[provider.OAuth2Provider](func(v1, v2 provider.OAuth2Provider) bool {
return v1 < v2
}))
providers.EnabledProvider().Range(func(key provider.OAuth2Provider, value provider.ProviderInterface) bool { providers.EnabledProvider().Range(func(key provider.OAuth2Provider, value provider.ProviderInterface) bool {
a.Push(key) r = append(r, key)
return true return true
}) })
return a.SortStable().Slice(), nil slices.SortStableFunc(r, func(a, b provider.OAuth2Provider) int {
}, time.Hour) if a == b {
return 0
} else if natural.Less(string(a), string(b)) {
return -1
} else {
return 1
}
})
return r, nil
}, 0)
) )
func InitProvider(ctx context.Context) (err error) { func InitProvider(ctx context.Context) (err error) {

@ -9,11 +9,14 @@ import (
"github.com/synctv-org/synctv/internal/model" "github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/settings" "github.com/synctv-org/synctv/internal/settings"
"github.com/zijiren233/gencontainer/synccache" "github.com/zijiren233/gencontainer/synccache"
"github.com/zijiren233/gencontainer/vec"
) )
var roomCache *synccache.SyncCache[string, *Room] var roomCache *synccache.SyncCache[string, *Room]
func RangeRoomCache(f func(key string, value *synccache.Entry[*Room]) bool) {
roomCache.Range(f)
}
func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConfig) (*Room, error) { func CreateRoom(name, password string, maxCount int64, conf ...db.CreateRoomConfig) (*Room, error) {
r, err := db.CreateRoom(name, password, maxCount, conf...) r, err := db.CreateRoom(name, password, maxCount, conf...)
if err != nil { if err != nil {
@ -146,40 +149,6 @@ func GetAllRoomsInCacheWithoutHidden() []*Room {
return rooms return rooms
} }
type RoomInfo struct {
RoomId string `json:"roomId"`
RoomName string `json:"roomName"`
PeopleNum int64 `json:"peopleNum"`
NeedPassword bool `json:"needPassword"`
CreatorID string `json:"creatorId"`
Creator string `json:"creator"`
CreatedAt int64 `json:"createdAt"`
Status model.RoomStatus `json:"status"`
}
func GetRoomHeapInCacheWithoutHidden() []*RoomInfo {
rooms := vec.New[*RoomInfo](vec.WithCmpLess[*RoomInfo](func(v1, v2 *RoomInfo) bool {
return v1.PeopleNum > v2.PeopleNum
}), vec.WithCmpEqual[*RoomInfo](func(v1, v2 *RoomInfo) bool {
return v1.RoomId == v2.RoomId
}))
roomCache.Range(func(key string, value *synccache.Entry[*Room]) bool {
v := value.Value()
if !v.Settings.Hidden {
rooms.Push(&RoomInfo{
RoomId: v.ID,
RoomName: v.Name,
PeopleNum: v.PeopleNum(),
NeedPassword: v.NeedPassword(),
Creator: GetUserName(v.CreatorID),
CreatedAt: v.CreatedAt.UnixMilli(),
})
}
return true
})
return rooms.SortStable().Slice()
}
func SetRoomStatus(roomID string, status model.RoomStatus) error { func SetRoomStatus(roomID string, status model.RoomStatus) error {
err := db.SetRoomStatus(roomID, status) err := db.SetRoomStatus(roomID, status)
if err != nil { if err != nil {

@ -5,9 +5,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"slices"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/maruel/natural"
"github.com/synctv-org/synctv/internal/db" "github.com/synctv-org/synctv/internal/db"
dbModel "github.com/synctv-org/synctv/internal/model" dbModel "github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/op" "github.com/synctv-org/synctv/internal/op"
@ -16,6 +18,7 @@ import (
"github.com/synctv-org/synctv/server/model" "github.com/synctv-org/synctv/server/model"
"github.com/synctv-org/synctv/utils" "github.com/synctv-org/synctv/utils"
"github.com/zijiren233/gencontainer/refreshcache" "github.com/zijiren233/gencontainer/refreshcache"
"github.com/zijiren233/gencontainer/synccache"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -63,8 +66,41 @@ func CreateRoom(ctx *gin.Context) {
})) }))
} }
var roomHotCache = refreshcache.NewRefreshCache[[]*op.RoomInfo](func(context.Context, ...any) ([]*op.RoomInfo, error) { var roomHotCache = refreshcache.NewRefreshCache[[]*model.RoomListResp](func(context.Context, ...any) ([]*model.RoomListResp, error) {
return op.GetRoomHeapInCacheWithoutHidden(), nil rooms := make([]*model.RoomListResp, 0)
op.RangeRoomCache(func(key string, value *synccache.Entry[*op.Room]) bool {
v := value.Value()
if !v.Settings.Hidden {
rooms = append(rooms, &model.RoomListResp{
RoomId: v.ID,
RoomName: v.Name,
PeopleNum: v.PeopleNum(),
NeedPassword: v.NeedPassword(),
Creator: op.GetUserName(v.CreatorID),
CreatedAt: v.CreatedAt.UnixMilli(),
})
}
return true
})
slices.SortStableFunc(rooms, func(a, b *model.RoomListResp) int {
if a.PeopleNum == b.PeopleNum {
if a.RoomName == b.RoomName {
return 0
}
if natural.Less(a.RoomName, b.RoomName) {
return -1
} else {
return 1
}
} else if a.PeopleNum > b.PeopleNum {
return -1
} else {
return 1
}
})
return rooms, nil
}, time.Second*3) }, time.Second*3)
func RoomHotList(ctx *gin.Context) { func RoomHotList(ctx *gin.Context) {
@ -74,12 +110,15 @@ func RoomHotList(ctx *gin.Context) {
return return
} }
r, _ := roomHotCache.Get(ctx) r, err := roomHotCache.Get(ctx)
rs := utils.GetPageItems(r, page, pageSize) if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{ ctx.JSON(http.StatusOK, model.NewApiDataResp(gin.H{
"total": len(r), "total": len(r),
"list": rs, "list": utils.GetPageItems(r, page, pageSize),
})) }))
} }

@ -6,9 +6,9 @@ import (
"regexp" "regexp"
json "github.com/json-iterator/go" json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/op"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/synctv-org/synctv/internal/model"
dbModel "github.com/synctv-org/synctv/internal/model" dbModel "github.com/synctv-org/synctv/internal/model"
) )
@ -68,7 +68,16 @@ func (c *CreateRoomReq) Validate() error {
return nil return nil
} }
type RoomListResp = op.RoomInfo type RoomListResp struct {
RoomId string `json:"roomId"`
RoomName string `json:"roomName"`
PeopleNum int64 `json:"peopleNum"`
NeedPassword bool `json:"needPassword"`
CreatorID string `json:"creatorId"`
Creator string `json:"creator"`
CreatedAt int64 `json:"createdAt"`
Status model.RoomStatus `json:"status"`
}
type LoginRoomReq struct { type LoginRoomReq struct {
RoomId string `json:"roomId"` RoomId string `json:"roomId"`

Loading…
Cancel
Save