remove commentIncreaseUpdate simplify comment cache

This commit is contained in:
xing 2024-01-04 23:32:10 +08:00
parent 12b75b9d82
commit 4d9d011213
11 changed files with 122 additions and 277 deletions

View File

@ -6,9 +6,7 @@ import (
"github.com/fthvgb1/wp-go/app/pkg/dao"
"github.com/fthvgb1/wp-go/app/pkg/logs"
"github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/safety"
"time"
@ -57,26 +55,17 @@ func InitActionsCommonCache() {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
})
cachemanager.NewPaginationCache(
cachemanager.NewMemoryMapCache[string, helper.PaginationData[uint64]](nil, nil, 30*time.Second,
"PostCommentsIds", func() time.Duration {
return config.GetConfig().CacheTime.PostCommentsCacheTime
},
cache.NewIncreaseUpdate("PostCommentsIds-increaseUpdate", CommentDataIncreaseUpdate, 30*time.Second,
func() time.Duration {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
}),
),
cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
})
1000, dao.PostCommentsIds, dao.PostCommentLocal, nil, nil, 300, "PostCommentsIds")
cachemanager.NewMemoryMapCache(dao.CommentDates, nil, time.Hour, "postCommentData", func() time.Duration {
cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration {
return config.GetConfig().CacheTime.CommentsCacheTime
})
cachemanager.NewMemoryMapCache[uint64, []models.Comments](nil, CommentDataIncreaseUpdates, time.Hour, func() time.Duration {
return config.GetConfig().CacheTime.CommentsCacheTime
}, "increaseComment30s", cache.NewIncreaseUpdate("increaseComment30s", IncreaseUpdates, 30*time.Second, nil))
cachemanager.NewMemoryMapCache(dao.CommentChildren, nil, time.Minute, "commentChildren", func() time.Duration {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
})
cachemanager.NewVarMemoryCache(dao.GetMaxPostId, c.CacheTime.MaxPostIdCacheTime, "maxPostId", func() time.Duration {
return config.GetConfig().CacheTime.MaxPostIdCacheTime
@ -120,10 +109,10 @@ func Archives(ctx context.Context) []models.PostArchive {
data := a.data
l := len(data)
m := time.Now().Month()
if l > 0 && a.month != m || l < 1 {
if l < 1 || a.month != m {
r, err := a.fn(ctx)
if err != nil {
logs.Error(err, "set cache fail")
logs.Error(err, "set cache Archives fail")
return nil
}
a.month = m

View File

@ -5,13 +5,10 @@ import (
"github.com/fthvgb1/wp-go/app/pkg/dao"
"github.com/fthvgb1/wp-go/app/pkg/logs"
"github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"time"
)
@ -25,7 +22,7 @@ func RecentComments(ctx context.Context, n int) (r []models.Comments) {
return
}
func PostComments(ctx context.Context, Id uint64) ([]models.PostComments, error) {
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
ids, err := cachemanager.Get[[]uint64]("PostCommentsIds", ctx, Id, time.Second)
if err != nil {
return nil, err
@ -33,12 +30,12 @@ func PostComments(ctx context.Context, Id uint64) ([]models.PostComments, error)
return GetCommentDataByIds(ctx, ids)
}
func GetCommentById(ctx context.Context, id uint64) (models.PostComments, error) {
return cachemanager.Get[models.PostComments]("postCommentData", ctx, id, time.Second)
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
return cachemanager.Get[models.Comments]("postCommentData", ctx, id, time.Second)
}
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.PostComments, error) {
return cachemanager.GetMultiple[models.PostComments]("postCommentData", ctx, ids, time.Second)
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
return cachemanager.GetMultiple[models.Comments]("postCommentData", ctx, ids, time.Second)
}
func NewCommentCache() *cache.MapCache[string, string] {
@ -46,83 +43,17 @@ func NewCommentCache() *cache.MapCache[string, string] {
return r
}
func CommentDataIncreaseUpdates(_ context.Context, _ uint64, _ ...any) ([]models.Comments, error) {
return nil, nil
}
func IncreaseUpdates(ctx context.Context, currentData []models.Comments, postId uint64, t time.Time, _ ...any) ([]models.Comments, bool, bool, error) {
var maxId uint64
if len(currentData) > 0 {
maxId = currentData[len(currentData)-1].CommentId
} else {
maxId, err := dao.LatestCommentId(ctx, postId)
return []models.Comments{{CommentId: maxId}}, true, false, err
}
v, err := dao.IncreaseCommentData(ctx, postId, maxId, t)
func PostTopComments(ctx context.Context, _ string, a ...any) (helper.PaginationData[uint64], error) {
postId := a[0].(uint64)
page := a[1].(int)
limit := a[2].(int)
total := a[3].(int)
v, total, err := dao.PostCommentsIds(ctx, postId, page, limit, total)
if err != nil {
return nil, false, false, err
return helper.PaginationData[uint64]{}, err
}
if len(v) < 1 {
return nil, false, true, nil
}
m, err := dao.CommentDates(ctx, v)
if err != nil {
return nil, false, false, err
}
CommentData, _ := cachemanager.GetMapCache[uint64, models.PostComments]("postCommentData")
data := slice.Map(v, func(t uint64) models.Comments {
comments := m[t].Comments
if comments.CommentParent > 0 {
vv, ok := CommentData.Get(ctx, comments.CommentParent)
if ok && !slice.IsContained(vv.Children, comments.CommentId) {
vv.Children = append(vv.Children, comments.CommentId)
CommentData.Set(ctx, comments.CommentParent, vv)
}
}
CommentData.Set(ctx, comments.CommentId, models.PostComments{Comments: comments})
return comments
})
return data, true, false, nil
}
func CommentDataIncreaseUpdate(ctx context.Context, currentData helper.PaginationData[uint64], postId string, _ time.Time, _ ...any) (data helper.PaginationData[uint64], save bool, refresh bool, err error) {
refresh = true
increaseUpdateData, _ := cachemanager.GetMapCache[uint64, []models.Comments]("increaseComment30s")
v, ok := increaseUpdateData.Get(ctx, str.ToInt[uint64](postId))
if !ok {
return
}
if len(v) < 1 {
return
}
if len(currentData.Data) > 0 {
if slice.IsContained(currentData.Data, v[0].CommentId) {
return
}
}
dat := slice.FilterAndMap(v, func(t models.Comments) (uint64, bool) {
if wpconfig.GetOption("thread_comments") != "1" || "1" == wpconfig.GetOption("thread_comments_depth") {
return t.CommentId, t.CommentId > 0
}
return t.CommentId, t.CommentId > 0 && t.CommentParent == 0
})
if len(dat) > 0 {
save = true
refresh = false
var a []uint64
a = append(currentData.Data, dat...)
slice.Sorts(a, wpconfig.GetOption("comment_order"))
data.Data = a
data.TotalRaw = len(data.Data)
}
return data, save, refresh, err
}
func UpdateCommentCache(ctx context.Context, timeout time.Duration, postId uint64) (err error) {
c, _ := cachemanager.GetPaginationCache[uint64, uint64]("PostCommentsIds")
if c.IsSwitchDB(postId) {
return
}
_, err = cachemanager.Get[[]models.Comments]("increaseComment30s", ctx, postId, timeout)
return
return helper.PaginationData[uint64]{
Data: v,
TotalRaw: total,
}, nil
}

View File

@ -111,7 +111,7 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
if err != nil {
return
}
comments, err := cachemanager.GetMultiple[models.PostComments]("postCommentData", c, ids, time.Second)
comments, err := cachemanager.GetMultiple[models.Comments]("postCommentData", c, ids, time.Second)
if err != nil {
return
}
@ -140,7 +140,7 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
}
}
} else {
rs.Items = slice.Map(comments, func(t models.PostComments) rss2.Item {
rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
return rss2.Item{
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId),
@ -169,7 +169,7 @@ func commentsFeed(c context.Context, _ ...any) (r []string, err error) {
if nil != err {
return []string{}, err
}
rs.Items = slice.Map(com, func(t models.PostComments) rss2.Item {
rs.Items = slice.Map(com, func(t models.Comments) rss2.Item {
post, _ := GetPostById(c, t.CommentPostId)
desc := "评论受保护:要查看请输入密码。"
content := t.CommentContent

View File

@ -11,7 +11,6 @@ import (
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/model"
"time"
)
// RecentComments
@ -83,101 +82,6 @@ func GetCommentByIds(ctx context.Context, ids []uint64, _ ...any) (map[uint64]mo
return m, nil
}
func GetIncreaseComment(ctx context.Context, currentData []uint64, k uint64, _ time.Time, _ ...any) (data []uint64, save bool, refresh bool, err error) {
r, err := model.ChunkFind[models.Comments](ctx, 1000, model.Conditions(
model.Where(model.SqlBuilder{
{"comment_approved", "1"},
{"comment_post_ID", "=", number.IntToString(k), "int"},
//{"comment_date", ">=", t.Format(time.DateTime)},
{"comment_ID", ">", number.IntToString(currentData[len(currentData)-1])},
}),
model.Fields("comment_ID"),
model.Order(model.SqlBuilder{
{"comment_date_gmt", "asc"},
{"comment_ID", "asc"},
})),
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
err = nil
refresh = true
}
return
}
if len(r) < 1 {
refresh = true
return
}
rr := slice.Map(r, func(t models.Comments) uint64 {
return t.CommentId
})
data = append(currentData, rr...)
save = true
return
}
func CommentDates(ctx context.Context, CommentIds []uint64, _ ...any) (map[uint64]models.PostComments, error) {
if len(CommentIds) < 1 {
return nil, nil
}
m := make(map[uint64]models.PostComments)
off := 0
threadComments := wpconfig.GetOption("thread_comments")
where := model.SqlBuilder{
{"comment_approved", "1"},
}
var in [][]any
if threadComments == "1" {
where = append(where, []string{"and", "comment_ID", "in", "", "", "or", "comment_parent", "in", "", ""})
} else {
where = append(where, []string{"comment_ID", "in", ""})
}
for {
id := slice.Slice(CommentIds, off, 200)
if len(id) < 1 {
break
}
if threadComments == "1" {
in = [][]any{slice.ToAnySlice(id), slice.ToAnySlice(id)}
} else {
in = [][]any{slice.ToAnySlice(id)}
}
r, err := model.Finds[models.Comments](ctx, model.Conditions(
model.Where(where),
model.Fields("*"),
model.In(in...),
))
if err != nil {
return m, err
}
rr := slice.GroupBy(r, func(t models.Comments) (uint64, models.Comments) {
return t.CommentParent, t
})
mm := map[uint64][]uint64{}
for u, comments := range rr {
slice.SimpleSort(comments, slice.ASC, func(t models.Comments) uint64 {
return t.CommentId
})
mm[u] = slice.Map(comments, func(t models.Comments) uint64 {
return t.CommentId
})
}
for _, comments := range r {
var children []uint64
if threadComments == "1" {
children = mm[comments.CommentId]
}
v := models.PostComments{
Comments: comments,
Children: children,
}
m[comments.CommentId] = v
}
off += 200
}
return m, nil
}
func CommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
n, err := model.GetField[models.Posts](ctx, "comment_count", model.Conditions(
model.Where(model.SqlBuilder{{"ID", "=", number.IntToString(postId), "int"}})))
@ -186,18 +90,6 @@ func CommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
}
return str.ToInteger(n, 0), err
}
func PostCommentLocal(_ context.Context, data []uint64, _ uint64, page, limit int, _ ...any) ([]uint64, int, error) {
/*order := wpconfig.GetOption("comment_order")
if order == "desc" {
r := slice.ReversePagination(data, page, limit)
if len(r) < 1 {
return nil, 0, nil
}
r = slice.SortsNew(r, slice.DESC)
return r, len(data), nil
}*/
return slice.Pagination(data, page, limit), len(data), nil
}
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) {
order := wpconfig.GetOption("comment_order")
@ -226,45 +118,23 @@ func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw i
}), total, err
}
func IncreaseCommentData(ctx context.Context, postId, maxCommentId uint64, _ time.Time) ([]uint64, error) {
r, err := model.ChunkFind[models.Comments](ctx, 1000, model.Conditions(
func CommentChildren(ctx context.Context, commentIds []uint64, _ ...any) (r map[uint64][]uint64, err error) {
rr, err := model.Finds[models.Comments](ctx, model.Conditions(
model.Where(model.SqlBuilder{
{"comment_parent", "in", ""},
{"comment_approved", "1"},
{"comment_post_ID", "=", number.IntToString(postId), "int"},
{"comment_ID", ">", number.IntToString(maxCommentId), "int"},
}),
model.Fields("comment_ID"),
model.Order(model.SqlBuilder{
{"comment_date_gmt", "asc"},
{"comment_ID", "asc"},
})),
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
err = nil
return nil, nil
}
return nil, err
}
return slice.Map(r, func(t models.Comments) uint64 {
return t.CommentId
}), err
}
func LatestCommentId(ctx context.Context, postId uint64) (uint64, error) {
v, err := model.GetField[models.Comments](ctx, "comment_ID", model.Conditions(
model.Where(model.SqlBuilder{
{"comment_approved", "1"},
{"comment_post_ID", "=", number.IntToString(postId), "int"},
}),
model.Order(model.SqlBuilder{{"comment_ID", "desc"}}),
model.Limit(1),
model.In(slice.ToAnySlice(commentIds)),
model.Fields("comment_ID,comment_parent"),
))
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
err = nil
}
return 0, err
return
}
return str.ToInteger[uint64](v, 0), err
r = slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) {
return v.CommentParent, v.CommentId
})
return
}

View File

@ -117,9 +117,18 @@ func SearchPostIds(ctx context.Context, _ string, args ...any) (ids PostIds, err
}
func GetMaxPostId(ctx context.Context, _ ...any) (uint64, error) {
r, err := model.SimpleFind[models.Posts](ctx,
model.SqlBuilder{{"post_type", "post"}, {"post_status", "publish"}},
"max(ID) ID",
r, err := model.Finds[models.Posts](ctx,
model.Conditions(
model.Where(model.SqlBuilder{
{"post_type", "post"},
{"post_status", "publish"}},
),
model.Fields("ID"),
model.Order(model.SqlBuilder{
{"ID", "desc"},
}),
model.Limit(1),
),
)
var id uint64
if len(r) > 0 {

View File

@ -29,7 +29,7 @@ type Comments struct {
type CommentHtml interface {
FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string
FloorOrder(wpOrder string, i, j models.PostComments) bool
FloorOrder(wpOrder string, i, j models.Comments) bool
}
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
@ -146,7 +146,7 @@ func (c CommonCommentFormat) FormatLi(_ context.Context, m models.Comments, curr
return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent)
}
func (c CommonCommentFormat) FloorOrder(wpOrder string, i, j models.PostComments) bool {
func (c CommonCommentFormat) FloorOrder(wpOrder string, i, j models.Comments) bool {
return i.CommentId > j.CommentId
}

View File

@ -13,7 +13,8 @@ import (
)
func RenderComment(ctx context.Context, page int, render plugins.CommentHtml, ids []uint64, timeout time.Duration, isTLS bool) (string, error) {
ca, _ := cachemanager.GetMapCache[uint64, models.PostComments]("postCommentData")
ca, _ := cachemanager.GetMapCache[uint64, models.Comments]("postCommentData")
children, _ := cachemanager.GetMapCache[uint64, []uint64]("commentChildren")
h := CommentHandle{
maxDepth: str.ToInteger(wpconfig.GetOption("thread_comments_depth"), 5),
depth: 1,
@ -21,6 +22,7 @@ func RenderComment(ctx context.Context, page int, render plugins.CommentHtml, id
html: render,
order: wpconfig.GetOption("comment_order"),
ca: ca,
children: children,
threadComments: wpconfig.GetOption("thread_comments") == "1",
page: page,
}
@ -34,16 +36,21 @@ type CommentHandle struct {
html plugins.CommentHtml
order string
page int
ca *cache.MapCache[uint64, models.PostComments]
ca *cache.MapCache[uint64, models.Comments]
children *cache.MapCache[uint64, []uint64]
threadComments bool
}
func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration, comments []models.PostComments) ([]models.PostComments, error) {
rr := slice.FilterAndMap(comments, func(t models.PostComments) ([]uint64, bool) {
return t.Children, len(t.Children) > 0
func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) {
parentIds := slice.Map(comments, func(t models.Comments) uint64 {
return t.CommentId
})
children, err := c.childrenComment(ctx, parentIds, timeout)
rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) {
return t, len(t) > 0
})
if len(rr) < 1 {
slice.Sort(comments, func(i, j models.PostComments) bool {
slice.Sort(comments, func(i, j models.Comments) bool {
return c.html.FloorOrder(c.order, i, j)
})
return comments, nil
@ -57,21 +64,37 @@ func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration,
if err != nil {
return nil, err
}
comments = slice.Map(comments, func(t models.PostComments) models.PostComments {
t.Children = nil
return t
})
comments = append(comments, rrr...)
return comments, nil
}
func (c CommentHandle) childrenComment(ctx context.Context, ids []uint64, timeout time.Duration) ([][]uint64, error) {
v, err := c.children.GetCacheBatch(ctx, ids, timeout)
if err != nil {
return nil, err
}
return slice.Copy(v), nil
}
func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout time.Duration) (html string, err error) {
comments, err := c.ca.GetCacheBatch(ctx, ids, timeout)
if err != nil {
return "", err
}
if c.depth > 1 && c.depth < c.maxDepth {
comments = slice.Copy(comments)
slice.Sort(comments, func(i, j models.Comments) bool {
return c.html.FloorOrder(c.order, i, j)
})
}
fixChildren := false
if c.depth >= c.maxDepth {
comments, err = c.findComments(ctx, timeout, comments)
if err != nil {
return "", err
}
fixChildren = true
}
s := str.NewBuilder()
for i, comment := range comments {
@ -81,14 +104,22 @@ func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout
}
parent := ""
fl := false
if c.threadComments && len(comment.Children) > 0 && c.depth < c.maxDepth+1 {
var children []uint64
if !fixChildren {
children, err = c.children.GetCache(ctx, comment.CommentId, timeout)
}
if err != nil {
return "", err
}
if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 {
parent = "parent"
fl = true
}
s.WriteString(c.html.FormatLi(ctx, comment.Comments, c.depth, c.maxDepth, c.page, c.isTls, c.threadComments, eo, parent))
s.WriteString(c.html.FormatLi(ctx, comment, c.depth, c.maxDepth, c.page, c.isTls, c.threadComments, eo, parent))
if fl {
c.depth++
ss, err := c.formatComments(ctx, comment.Children, timeout)
ss, err := c.formatComments(ctx, children, timeout)
if err != nil {
return "", err
}

View File

@ -11,6 +11,7 @@ import (
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
"github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/plugin/pagination"
@ -88,20 +89,21 @@ func (d *DetailHandle) PasswordProject() {
}
}
func (d *DetailHandle) Comment() {
err := cache.UpdateCommentCache(d.C, time.Second, d.Post.Id)
d.ginH["totalCommentNum"] = 0
d.ginH["totalCommentPage"] = 1
d.ginH["commentPageNav"] = ""
d.ginH["commentOrder"] = wpconfig.GetOption("comment_order")
logs.IfError(err, "increase update comments err")
d.Page = str.ToInteger(d.C.Param("page"), 1)
d.ginH["currentPage"] = d.Page
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
ids, totalCommentNum, err := cachemanager.Pagination[uint64]("PostCommentsIds", d.C, time.Second, d.Post.Id, d.Page, d.Limit, "desc")
key := fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
data, err := cachemanager.Get[helper.PaginationData[uint64]]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, 0)
if err != nil {
d.SetErr(err)
return
}
ids := data.Data
totalCommentNum := data.TotalRaw
d.TotalRaw = totalCommentNum
num, err := cachemanager.Get[int]("commentNumber", d.C, d.Post.Id, time.Second)
if err != nil {

View File

@ -22,7 +22,7 @@ func NewPipe(name string, order float64, fn HandlePipeFn[*Handle]) Pipe {
// HandlePipe 方便把功能写在其它包里
func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) {
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f HandleFn[T]) HandleFn[T] {
return func(t T) {
next(f, t)
}

View File

@ -1,6 +1,26 @@
package helper
import "context"
type Pagination[T any] interface {
SetData(ctx context.Context, data []T)
GetData(ctx context.Context) []T
TotalRaws(ctx context.Context) int
}
type PaginationData[T any] struct {
Data []T
TotalRaw int
}
func (p *PaginationData[T]) SetData(ctx context.Context, data []T) {
p.Data = data
}
func (p *PaginationData[T]) GetData(ctx context.Context) []T {
return p.Data
}
func (p *PaginationData[T]) TotalRaws(ctx context.Context) int {
return p.TotalRaw
}

View File

@ -76,13 +76,6 @@ func Copy[T any](a []T, l ...int) []T {
copy(dst, a)
return dst
}
func Copies[T any](a ...[]T) []T {
var r []T
for _, ts := range a {
r = append(r, ts...)
}
return r
}
func Unshift[T any](a *[]T, e ...T) {
*a = append(e, *a...)