wp-go/cache/vars.go

110 lines
2.1 KiB
Go
Raw Normal View History

2022-09-19 09:39:00 +00:00
package cache
import (
2022-09-20 04:00:09 +00:00
"context"
2022-09-20 08:11:20 +00:00
"errors"
"fmt"
"github.com/fthvgb1/wp-go/safety"
2022-09-19 09:39:00 +00:00
"sync"
"time"
)
2023-01-20 10:10:13 +00:00
type VarCache[T any] struct {
2023-11-02 14:40:13 +00:00
AnyCache[T]
setCacheFunc func(context.Context, ...any) (T, error)
mutex sync.Mutex
2022-10-14 09:15:43 +00:00
}
2023-11-02 14:40:13 +00:00
func (t *VarCache[T]) GetCache(ctx context.Context, timeout time.Duration, params ...any) (T, error) {
data, ok := t.Get(ctx)
if ok {
return data, nil
}
var err error
call := func() {
t.mutex.Lock()
defer t.mutex.Unlock()
dat, ok := t.Get(ctx)
if ok {
data = dat
return
}
r, er := t.setCacheFunc(ctx, params...)
if er != nil {
err = er
return
}
t.Set(ctx, r)
data = r
}
if timeout > 0 {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
done := make(chan struct{}, 1)
go func() {
call()
done <- struct{}{}
close(done)
}()
select {
case <-ctx.Done():
err = errors.New(fmt.Sprintf("get cache %s", ctx.Err().Error()))
case <-done:
}
} else {
call()
}
return data, err
2022-09-19 09:39:00 +00:00
}
2023-11-02 14:40:13 +00:00
type VarMemoryCache[T any] struct {
v *safety.Var[vars[T]]
expireTime func() time.Duration
2022-10-07 12:37:42 +00:00
}
2023-11-02 14:40:13 +00:00
func (c *VarMemoryCache[T]) ClearExpired(ctx context.Context) {
c.Flush(ctx)
2022-09-19 09:39:00 +00:00
}
2023-11-02 14:40:13 +00:00
func NewVarMemoryCache[T any](expireTime func() time.Duration) *VarMemoryCache[T] {
return &VarMemoryCache[T]{v: safety.NewVar(vars[T]{}), expireTime: expireTime}
2023-01-20 10:10:13 +00:00
}
2023-11-02 14:40:13 +00:00
func (c *VarMemoryCache[T]) Get(_ context.Context) (T, bool) {
2023-01-20 10:43:11 +00:00
v := c.v.Load()
2023-11-02 14:40:13 +00:00
return v.data, c.expireTime() >= time.Now().Sub(v.setTime)
2022-09-19 14:02:34 +00:00
}
2023-11-02 14:40:13 +00:00
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)
}
2022-09-20 04:00:09 +00:00
2023-11-02 14:40:13 +00:00
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
}
2022-09-20 08:11:20 +00:00
2023-11-02 14:40:13 +00:00
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{},
2022-09-19 09:39:00 +00:00
}
2023-11-02 14:40:13 +00:00
}
func (c *VarMemoryCache[T]) Flush(_ context.Context) {
c.v.Flush()
2022-09-19 09:39:00 +00:00
}