optimize cachemanger improve var cache
This commit is contained in:
parent
d1fb560578
commit
041d06104b
@ -25,19 +25,20 @@ func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Feed(c *gin.Context) {
|
func Feed(c *gin.Context) {
|
||||||
if !isCacheExpired(c, cache.FeedCache().GetLastSetTime()) {
|
feed := cache.FeedCache()
|
||||||
|
if !isCacheExpired(c, feed.GetLastSetTime(c)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := cache.FeedCache().GetCache(c, time.Second, c)
|
r, err := feed.GetCache(c, time.Second, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(r[0], c, cache.FeedCache().GetLastSetTime())
|
setFeed(r[0], c, feed.GetLastSetTime(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFeed(s string, c *gin.Context, t time.Time) {
|
func setFeed(s string, c *gin.Context, t time.Time) {
|
||||||
@ -51,31 +52,33 @@ func setFeed(s string, c *gin.Context, t time.Time) {
|
|||||||
|
|
||||||
func PostFeed(c *gin.Context) {
|
func PostFeed(c *gin.Context) {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
if !isCacheExpired(c, cache.PostFeedCache().GetLastSetTime(c, id)) {
|
postFeed := cache.PostFeedCache()
|
||||||
|
if !isCacheExpired(c, postFeed.GetLastSetTime(c, id)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s, err := cache.PostFeedCache().GetCache(c, id, time.Second, c, id)
|
s, err := postFeed.GetCache(c, id, time.Second, c, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(s, c, cache.PostFeedCache().GetLastSetTime(c, id))
|
setFeed(s, c, postFeed.GetLastSetTime(c, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommentsFeed(c *gin.Context) {
|
func CommentsFeed(c *gin.Context) {
|
||||||
if !isCacheExpired(c, cache.CommentsFeedCache().GetLastSetTime()) {
|
feed := cache.CommentsFeedCache()
|
||||||
|
if !isCacheExpired(c, feed.GetLastSetTime(c)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := cache.CommentsFeedCache().GetCache(c, time.Second, c)
|
r, err := feed.GetCache(c, time.Second, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(r[0], c, cache.CommentsFeedCache().GetLastSetTime())
|
setFeed(r[0], c, feed.GetLastSetTime(c))
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,13 @@ var getSingleFn = safety.NewMap[string, func(context.Context, any, time.Duration
|
|||||||
var getBatchFn = safety.NewMap[string, func(context.Context, any, time.Duration, ...any) (any, error)]()
|
var getBatchFn = safety.NewMap[string, func(context.Context, any, time.Duration, ...any) (any, error)]()
|
||||||
var anyFlush = safety.NewMap[string, func()]()
|
var anyFlush = safety.NewMap[string, func()]()
|
||||||
|
|
||||||
|
var getVar = safety.NewMap[string, func(context.Context, time.Duration, ...any) (any, error)]()
|
||||||
|
|
||||||
var expiredTime = safety.NewMap[string, expire]()
|
var expiredTime = safety.NewMap[string, expire]()
|
||||||
|
|
||||||
|
var varCache = safety.NewMap[string, any]()
|
||||||
|
var mapCache = safety.NewMap[string, any]()
|
||||||
|
|
||||||
type expire struct {
|
type expire struct {
|
||||||
fn func() time.Duration
|
fn func() time.Duration
|
||||||
p *safety.Var[time.Duration]
|
p *safety.Var[time.Duration]
|
||||||
@ -62,7 +67,10 @@ func FlushAnyVal(name ...string) {
|
|||||||
|
|
||||||
func pushFlushMap[K comparable, V any](m *cache.MapCache[K, V], args ...any) {
|
func pushFlushMap[K comparable, V any](m *cache.MapCache[K, V], args ...any) {
|
||||||
name, _ := parseArgs(args...)
|
name, _ := parseArgs(args...)
|
||||||
if name != "" {
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mapCache.Store(name, m)
|
||||||
anyFlush.Store(name, func() {
|
anyFlush.Store(name, func() {
|
||||||
m.Flush(ctx)
|
m.Flush(ctx)
|
||||||
})
|
})
|
||||||
@ -87,10 +95,10 @@ func pushFlushMap[K comparable, V any](m *cache.MapCache[K, V], args ...any) {
|
|||||||
return m.GetCacheBatch(ct, kk, t, a...)
|
return m.GetCacheBatch(ct, kk, t, a...)
|
||||||
})
|
})
|
||||||
FlushPush()
|
FlushPush()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get[T, K any](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
func Get[T, K any](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
||||||
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
v, ok := getSingleFn.Load(name)
|
v, ok := getSingleFn.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||||
@ -104,6 +112,7 @@ func Get[T, K any](name string, ct context.Context, key K, timeout time.Duration
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func GetMultiple[T, K any](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
func GetMultiple[T, K any](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
||||||
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
v, ok := getBatchFn.Load(name)
|
v, ok := getBatchFn.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||||
@ -140,20 +149,33 @@ func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapB
|
|||||||
pushFlushMap(m, args...)
|
pushFlushMap(m, args...)
|
||||||
FlushPush(m)
|
FlushPush(m)
|
||||||
ClearPush(m)
|
ClearPush(m)
|
||||||
|
name, f := parseArgs(args...)
|
||||||
|
if f != nil && name != "" {
|
||||||
|
SetExpireTime(any(data).(cache.SetTime), name, 0, f)
|
||||||
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
func NewMemoryMapCache[K comparable, V any](batchFn cache.MapBatchFn[K, V],
|
func NewMemoryMapCache[K comparable, V any](batchFn cache.MapBatchFn[K, V],
|
||||||
fn cache.MapSingleFn[K, V], expireTime time.Duration, args ...any) *cache.MapCache[K, V] {
|
fn cache.MapSingleFn[K, V], expireTime time.Duration, args ...any) *cache.MapCache[K, V] {
|
||||||
name, f := parseArgs(args...)
|
|
||||||
|
c := NewMapCache[K, V](cache.NewMemoryMapCache[K, V](func() time.Duration {
|
||||||
|
return expireTime
|
||||||
|
}), batchFn, fn, args...)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetExpireTime(c cache.SetTime, name string, expireTime time.Duration, expireTimeFn func() time.Duration) {
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
var t, tt func() time.Duration
|
var t, tt func() time.Duration
|
||||||
t = f
|
t = expireTimeFn
|
||||||
if t == nil {
|
if t == nil {
|
||||||
t = func() time.Duration {
|
t = func() time.Duration {
|
||||||
return expireTime
|
return expireTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tt = t
|
tt = t
|
||||||
if name != "" {
|
|
||||||
expireTime = t()
|
expireTime = t()
|
||||||
p := safety.NewVar(expireTime)
|
p := safety.NewVar(expireTime)
|
||||||
e := expire{
|
e := expire{
|
||||||
@ -170,12 +192,10 @@ func NewMemoryMapCache[K comparable, V any](batchFn cache.MapBatchFn[K, V],
|
|||||||
t = func() time.Duration {
|
t = func() time.Duration {
|
||||||
return e.p.Load()
|
return e.p.Load()
|
||||||
}
|
}
|
||||||
}
|
c.SetExpiredTime(t)
|
||||||
|
|
||||||
return NewMapCache[K, V](cache.NewMemoryMapCache[K, V](t), batchFn, fn, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetExpireTime(t time.Duration, name ...string) {
|
func ChangeExpireTime(t time.Duration, name ...string) {
|
||||||
for _, s := range name {
|
for _, s := range name {
|
||||||
v, ok := expiredTime.Load(s)
|
v, ok := expiredTime.Load(s)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -200,3 +220,66 @@ func ClearExpired() {
|
|||||||
c.ClearExpired(ctx)
|
c.ClearExpired(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] {
|
||||||
|
v := cache.NewVarCache(c, fn)
|
||||||
|
FlushPush(v)
|
||||||
|
name, _ := parseArgs(a...)
|
||||||
|
if name != "" {
|
||||||
|
varCache.Store(name, v)
|
||||||
|
getVar.Store(name, func(c context.Context, duration time.Duration, a ...any) (any, error) {
|
||||||
|
return v.GetCache(c, duration, a...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
cc, ok := any(c).(clearExpired)
|
||||||
|
if ok {
|
||||||
|
ClearPush(cc)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVarVal[T any](name string, ctx context.Context, duration time.Duration, a ...any) (r T, err error) {
|
||||||
|
ctx = context.WithValue(ctx, "getCache", name)
|
||||||
|
fn, ok := getVar.Load(name)
|
||||||
|
if !ok {
|
||||||
|
err = errors.New(str.Join("cache ", name, " is not exist"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v, err := fn(ctx, duration, a...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vv, ok := v.(T)
|
||||||
|
if !ok {
|
||||||
|
err = errors.New(str.Join("cache ", name, " value wanted can't match got"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = vv
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVarMemoryCache[T any](fn func(context.Context, ...any) (T, error), expired time.Duration, a ...any) *cache.VarCache[T] {
|
||||||
|
c := cache.NewVarMemoryCache[T](nil)
|
||||||
|
name, e := parseArgs(a...)
|
||||||
|
SetExpireTime(c, name, expired, e)
|
||||||
|
v := NewVarCache[T](c, fn, a...)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVarCache[T any](name string) (*cache.VarCache[T], bool) {
|
||||||
|
v, ok := varCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
vv, ok := v.(*cache.VarCache[T])
|
||||||
|
return vv, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMapCache[K comparable, V any](name string) (*cache.MapCache[K, V], bool) {
|
||||||
|
v, ok := mapCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
vv, ok := v.(*cache.MapCache[K, V])
|
||||||
|
return vv, ok
|
||||||
|
}
|
@ -61,7 +61,7 @@ func TestSetExpireTime(t *testing.T) {
|
|||||||
fmt.Println(c.Get(ctx, "xx"))
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
fmt.Println(c.Get(ctx, "xx"))
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
SetExpireTime(3*time.Second, "xx")
|
ChangeExpireTime(3*time.Second, "xx")
|
||||||
c.Set(ctx, "xx", "yyy")
|
c.Set(ctx, "xx", "yyy")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
fmt.Println(c.Get(ctx, "xx"))
|
fmt.Println(c.Get(ctx, "xx"))
|
20
app/pkg/cache/cache.go
vendored
20
app/pkg/cache/cache.go
vendored
@ -69,15 +69,21 @@ func InitActionsCommonCache() {
|
|||||||
return config.GetConfig().CacheTime.CategoryCacheTime
|
return config.GetConfig().CacheTime.CategoryCacheTime
|
||||||
})
|
})
|
||||||
|
|
||||||
recentPostsCaches = cache.NewVarCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime)
|
recentPostsCaches = cachemanager.NewVarMemoryCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime, "recentPosts", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.RecentPostCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
recentCommentsCaches = cache.NewVarCache(dao.RecentComments, c.CacheTime.RecentCommentsCacheTime)
|
recentCommentsCaches = cachemanager.NewVarMemoryCache(dao.RecentComments, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.RecentCommentsCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postCommentCaches = cachemanager.NewMemoryMapCache(nil, dao.PostComments, c.CacheTime.PostCommentsCacheTime, "postCommentIds", func() time.Duration {
|
postCommentCaches = cachemanager.NewMemoryMapCache(nil, dao.PostComments, c.CacheTime.PostCommentsCacheTime, "postCommentIds", func() time.Duration {
|
||||||
return config.GetConfig().CacheTime.PostCommentsCacheTime
|
return config.GetConfig().CacheTime.PostCommentsCacheTime
|
||||||
})
|
})
|
||||||
|
|
||||||
maxPostIdCache = cache.NewVarCache(dao.GetMaxPostId, c.CacheTime.MaxPostIdCacheTime)
|
maxPostIdCache = cachemanager.NewVarMemoryCache(dao.GetMaxPostId, c.CacheTime.MaxPostIdCacheTime, "maxPostId", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.MaxPostIdCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
cachemanager.NewMemoryMapCache(nil, dao.GetUserById, c.CacheTime.UserInfoCacheTime, "userData", func() time.Duration {
|
cachemanager.NewMemoryMapCache(nil, dao.GetUserById, c.CacheTime.UserInfoCacheTime, "userData", func() time.Duration {
|
||||||
return config.GetConfig().CacheTime.UserInfoCacheTime
|
return config.GetConfig().CacheTime.UserInfoCacheTime
|
||||||
@ -91,13 +97,15 @@ func InitActionsCommonCache() {
|
|||||||
return config.GetConfig().CacheTime.CommentsCacheTime
|
return config.GetConfig().CacheTime.CommentsCacheTime
|
||||||
})
|
})
|
||||||
|
|
||||||
allUsernameCache = cache.NewVarCache(dao.AllUsername, c.CacheTime.UserInfoCacheTime)
|
allUsernameCache = cachemanager.NewVarMemoryCache(dao.AllUsername, c.CacheTime.UserInfoCacheTime, "allUsername", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.UserInfoCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
feedCache = cache.NewVarCache(feed, time.Hour)
|
feedCache = cachemanager.NewVarMemoryCache(feed, time.Hour, "feed")
|
||||||
|
|
||||||
postFeedCache = cachemanager.NewMemoryMapCache(nil, postFeed, time.Hour, "postFeed")
|
postFeedCache = cachemanager.NewMemoryMapCache(nil, postFeed, time.Hour, "postFeed")
|
||||||
|
|
||||||
commentsFeedCache = cache.NewVarCache(commentsFeed, time.Hour)
|
commentsFeedCache = cachemanager.NewVarMemoryCache(commentsFeed, time.Hour, "commentsFeed")
|
||||||
|
|
||||||
newCommentCache = cachemanager.NewMemoryMapCache[string, string](nil, nil, 15*time.Minute, "NewComment")
|
newCommentCache = cachemanager.NewMemoryMapCache[string, string](nil, nil, 15*time.Minute, "NewComment")
|
||||||
|
|
||||||
|
7
app/pkg/cache/feed.go
vendored
7
app/pkg/cache/feed.go
vendored
@ -13,7 +13,6 @@ import (
|
|||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/plugin/digest"
|
"github.com/fthvgb1/wp-go/plugin/digest"
|
||||||
"github.com/fthvgb1/wp-go/rss2"
|
"github.com/fthvgb1/wp-go/rss2"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -46,8 +45,7 @@ func PostFeedCache() *cache.MapCache[string, string] {
|
|||||||
return postFeedCache
|
return postFeedCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func feed(arg ...any) (xml []string, err error) {
|
func feed(c context.Context, _ ...any) (xml []string, err error) {
|
||||||
c := arg[0].(*gin.Context)
|
|
||||||
r := RecentPosts(c, 10)
|
r := RecentPosts(c, 10)
|
||||||
ids := slice.Map(r, func(t models.Posts) uint64 {
|
ids := slice.Map(r, func(t models.Posts) uint64 {
|
||||||
return t.Id
|
return t.Id
|
||||||
@ -150,8 +148,7 @@ func postFeed(c context.Context, id string, arg ...any) (x string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func commentsFeed(args ...any) (r []string, err error) {
|
func commentsFeed(c context.Context, _ ...any) (r []string, err error) {
|
||||||
c := args[0].(*gin.Context)
|
|
||||||
commens := RecentComments(c, 10)
|
commens := RecentComments(c, 10)
|
||||||
rs := templateRss
|
rs := templateRss
|
||||||
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.GetOption("blogname"))
|
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.GetOption("blogname"))
|
||||||
|
@ -10,8 +10,7 @@ import (
|
|||||||
|
|
||||||
// RecentComments
|
// RecentComments
|
||||||
// param context.Context
|
// param context.Context
|
||||||
func RecentComments(a ...any) (r []models.Comments, err error) {
|
func RecentComments(ctx context.Context, a ...any) (r []models.Comments, err error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
n := a[1].(int)
|
n := a[1].(int)
|
||||||
return model.Finds[models.Comments](ctx, model.Conditions(
|
return model.Finds[models.Comments](ctx, model.Conditions(
|
||||||
model.Where(model.SqlBuilder{
|
model.Where(model.SqlBuilder{
|
||||||
|
@ -116,8 +116,7 @@ func SearchPostIds(ctx context.Context, _ string, args ...any) (ids PostIds, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaxPostId(a ...any) (uint64, error) {
|
func GetMaxPostId(ctx context.Context, a ...any) (uint64, error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
r, err := model.SimpleFind[models.Posts](ctx,
|
r, err := model.SimpleFind[models.Posts](ctx,
|
||||||
model.SqlBuilder{{"post_type", "post"}, {"post_status", "publish"}},
|
model.SqlBuilder{{"post_type", "post"}, {"post_status", "publish"}},
|
||||||
"max(ID) ID",
|
"max(ID) ID",
|
||||||
@ -129,8 +128,7 @@ func GetMaxPostId(a ...any) (uint64, error) {
|
|||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecentPosts(a ...any) (r []models.Posts, err error) {
|
func RecentPosts(ctx context.Context, a ...any) (r []models.Posts, err error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
num := a[1].(int)
|
num := a[1].(int)
|
||||||
r, err = model.Finds[models.Posts](ctx, model.Conditions(
|
r, err = model.Finds[models.Posts](ctx, model.Conditions(
|
||||||
model.Where(model.SqlBuilder{
|
model.Where(model.SqlBuilder{
|
||||||
|
@ -12,8 +12,7 @@ func GetUserById(ctx context.Context, uid uint64, _ ...any) (r models.Users, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func AllUsername(a ...any) (map[string]struct{}, error) {
|
func AllUsername(ctx context.Context, _ ...any) (map[string]struct{}, error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{
|
r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{
|
||||||
{"user_status", "=", "0", "int"},
|
{"user_status", "=", "0", "int"},
|
||||||
}, "user_login")
|
}, "user_login")
|
||||||
|
@ -118,7 +118,7 @@ func InitHandle(fn func(*Handle), h *Handle) {
|
|||||||
h.C.Set("inited", true)
|
h.C.Set("inited", true)
|
||||||
inited = true
|
inited = true
|
||||||
return *h
|
return *h
|
||||||
}, float64(-100))
|
})
|
||||||
h.ginH = maps.Copy(hh.ginH)
|
h.ginH = maps.Copy(hh.ginH)
|
||||||
h.ginH["calPostClass"] = postClass(h)
|
h.ginH["calPostClass"] = postClass(h)
|
||||||
h.ginH["calBodyClass"] = bodyClass(h)
|
h.ginH["calBodyClass"] = bodyClass(h)
|
||||||
|
11
cache/cache.go
vendored
11
cache/cache.go
vendored
@ -19,3 +19,14 @@ type Expend[K comparable, V any] interface {
|
|||||||
Gets(ctx context.Context, k []K) (map[K]V, error)
|
Gets(ctx context.Context, k []K) (map[K]V, error)
|
||||||
Sets(ctx context.Context, m map[K]V)
|
Sets(ctx context.Context, m map[K]V)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SetTime interface {
|
||||||
|
SetExpiredTime(func() time.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnyCache[T any] interface {
|
||||||
|
Get(ctx context.Context) (T, bool)
|
||||||
|
Set(ctx context.Context, v T)
|
||||||
|
Flush(ctx context.Context)
|
||||||
|
GetLastSetTime(ctx context.Context) time.Time
|
||||||
|
}
|
||||||
|
4
cache/memorymapcache.go
vendored
4
cache/memorymapcache.go
vendored
@ -24,6 +24,10 @@ type mapVal[T any] struct {
|
|||||||
data T
|
data T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MemoryMapCache[K, V]) SetExpiredTime(f func() time.Duration) {
|
||||||
|
m.expireTime = f
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MemoryMapCache[K, V]) GetExpireTime(_ context.Context) time.Duration {
|
func (m *MemoryMapCache[K, V]) GetExpireTime(_ context.Context) time.Duration {
|
||||||
return m.expireTime()
|
return m.expireTime()
|
||||||
}
|
}
|
||||||
|
120
cache/vars.go
vendored
120
cache/vars.go
vendored
@ -10,70 +10,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type VarCache[T any] struct {
|
type VarCache[T any] struct {
|
||||||
v *safety.Var[vars[T]]
|
AnyCache[T]
|
||||||
|
setCacheFunc func(context.Context, ...any) (T, error)
|
||||||
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type vars[T any] struct {
|
func (t *VarCache[T]) GetCache(ctx context.Context, timeout time.Duration, params ...any) (T, error) {
|
||||||
data T
|
data, ok := t.Get(ctx)
|
||||||
mutex *sync.Mutex
|
if ok {
|
||||||
setCacheFunc func(...any) (T, error)
|
return data, nil
|
||||||
expireTime time.Duration
|
|
||||||
setTime time.Time
|
|
||||||
incr int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *VarCache[T]) GetLastSetTime() time.Time {
|
|
||||||
return c.v.Load().setTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewVarCache[T any](fun func(...any) (T, error), duration time.Duration) *VarCache[T] {
|
|
||||||
return &VarCache[T]{
|
|
||||||
v: safety.NewVar(vars[T]{
|
|
||||||
mutex: &sync.Mutex{},
|
|
||||||
setCacheFunc: fun,
|
|
||||||
expireTime: duration,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (c *VarCache[T]) IsExpired() bool {
|
|
||||||
v := c.v.Load()
|
|
||||||
return time.Duration(v.setTime.UnixNano())+v.expireTime < time.Duration(time.Now().UnixNano())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *VarCache[T]) Flush() {
|
|
||||||
v := c.v.Load()
|
|
||||||
mu := v.mutex
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
var vv T
|
|
||||||
v.data = vv
|
|
||||||
c.v.Store(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *VarCache[T]) GetCache(ctx context.Context, timeout time.Duration, params ...any) (T, error) {
|
|
||||||
v := c.v.Load()
|
|
||||||
data := v.data
|
|
||||||
var err error
|
var err error
|
||||||
if v.expireTime <= 0 || ((time.Duration(v.setTime.UnixNano()) + v.expireTime) < time.Duration(time.Now().UnixNano())) {
|
|
||||||
t := v.incr
|
|
||||||
call := func() {
|
call := func() {
|
||||||
v.mutex.Lock()
|
t.mutex.Lock()
|
||||||
defer v.mutex.Unlock()
|
defer t.mutex.Unlock()
|
||||||
vv := c.v.Load()
|
dat, ok := t.Get(ctx)
|
||||||
if vv.incr > t {
|
if ok {
|
||||||
|
data = dat
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, er := vv.setCacheFunc(params...)
|
r, er := t.setCacheFunc(ctx, params...)
|
||||||
if err != nil {
|
if er != nil {
|
||||||
err = er
|
err = er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vv.setTime = time.Now()
|
t.Set(ctx, r)
|
||||||
vv.data = r
|
|
||||||
data = r
|
data = r
|
||||||
vv.incr++
|
|
||||||
c.v.Store(vv)
|
|
||||||
}
|
}
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
@ -93,7 +55,55 @@ func (c *VarCache[T]) GetCache(ctx context.Context, timeout time.Duration, param
|
|||||||
} else {
|
} else {
|
||||||
call()
|
call()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VarMemoryCache[T any] struct {
|
||||||
|
v *safety.Var[vars[T]]
|
||||||
|
expireTime func() time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) ClearExpired(ctx context.Context) {
|
||||||
|
c.Flush(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVarMemoryCache[T any](expireTime func() time.Duration) *VarMemoryCache[T] {
|
||||||
|
return &VarMemoryCache[T]{v: safety.NewVar(vars[T]{}), expireTime: expireTime}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) Get(_ context.Context) (T, bool) {
|
||||||
|
v := c.v.Load()
|
||||||
|
return v.data, c.expireTime() >= time.Now().Sub(v.setTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) Set(_ context.Context, v T) {
|
||||||
|
vv := c.v.Load()
|
||||||
|
vv.data = v
|
||||||
|
vv.setTime = time.Now()
|
||||||
|
vv.incr++
|
||||||
|
c.v.Store(vv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) SetExpiredTime(f func() time.Duration) {
|
||||||
|
c.expireTime = f
|
||||||
|
}
|
||||||
|
|
||||||
|
type vars[T any] struct {
|
||||||
|
data T
|
||||||
|
setTime time.Time
|
||||||
|
incr int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) GetLastSetTime(_ context.Context) time.Time {
|
||||||
|
return c.v.Load().setTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVarCache[T any](cache AnyCache[T], fn func(context.Context, ...any) (T, error)) *VarCache[T] {
|
||||||
|
return &VarCache[T]{
|
||||||
|
AnyCache: cache, setCacheFunc: fn, mutex: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VarMemoryCache[T]) Flush(_ context.Context) {
|
||||||
|
c.v.Flush()
|
||||||
|
}
|
||||||
|
41
cache/vars_test.go
vendored
41
cache/vars_test.go
vendored
@ -7,9 +7,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cc = *NewVarCache(func(a ...any) (int, error) {
|
var cc = *NewVarCache[int](NewVarMemoryCache[int](func() time.Duration {
|
||||||
|
return time.Minute
|
||||||
|
}), func(ctx context.Context, a ...any) (int, error) {
|
||||||
return 1, nil
|
return 1, nil
|
||||||
}, time.Minute)
|
})
|
||||||
|
|
||||||
func TestVarCache_Flush(t *testing.T) {
|
func TestVarCache_Flush(t *testing.T) {
|
||||||
type testCase[T any] struct {
|
type testCase[T any] struct {
|
||||||
@ -26,41 +28,8 @@ func TestVarCache_Flush(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
fmt.Println(tt.c.GetCache(c, time.Second))
|
fmt.Println(tt.c.GetCache(c, time.Second))
|
||||||
tt.c.Flush()
|
tt.c.Flush(ctx)
|
||||||
fmt.Println(tt.c.GetCache(c, time.Second))
|
fmt.Println(tt.c.GetCache(c, time.Second))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVarCache_IsExpired(t *testing.T) {
|
|
||||||
type testCase[T any] struct {
|
|
||||||
name string
|
|
||||||
c VarCache[T]
|
|
||||||
want bool
|
|
||||||
}
|
|
||||||
tests := []testCase[int]{
|
|
||||||
{
|
|
||||||
name: "expired",
|
|
||||||
c: cc,
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "not expired",
|
|
||||||
c: func() VarCache[int] {
|
|
||||||
v := *NewVarCache(func(a ...any) (int, error) {
|
|
||||||
return 1, nil
|
|
||||||
}, time.Minute)
|
|
||||||
_, _ = v.GetCache(context.Background(), time.Second)
|
|
||||||
return v
|
|
||||||
}(),
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := tt.c.IsExpired(); got != tt.want {
|
|
||||||
t.Errorf("IsExpired() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user