118 lines
2.1 KiB
Go
118 lines
2.1 KiB
Go
package cache
|
|
|
|
import (
|
|
"context"
|
|
"github.com/hashicorp/golang-lru/v2/expirable"
|
|
_ "github.com/hashicorp/golang-lru/v2/expirable"
|
|
"time"
|
|
"uauth/internal/interfaces"
|
|
)
|
|
|
|
var _ interfaces.Cacher = (*_lru)(nil)
|
|
|
|
type _lru struct {
|
|
client *expirable.LRU[string, *_lru_value]
|
|
}
|
|
|
|
type _lru_value struct {
|
|
duration time.Duration
|
|
last time.Time
|
|
bs []byte
|
|
}
|
|
|
|
func (l *_lru) Get(ctx context.Context, key string) ([]byte, error) {
|
|
v, ok := l.client.Get(key)
|
|
if !ok {
|
|
return nil, ErrorKeyNotFound
|
|
}
|
|
|
|
if v.duration == 0 {
|
|
return v.bs, nil
|
|
}
|
|
|
|
if time.Now().Sub(v.last) > v.duration {
|
|
l.client.Remove(key)
|
|
return nil, ErrorKeyNotFound
|
|
}
|
|
|
|
return v.bs, nil
|
|
}
|
|
|
|
func (l *_lru) GetScan(ctx context.Context, key string) interfaces.Scanner {
|
|
return newScanner(l.Get(ctx, key))
|
|
}
|
|
|
|
func (l *_lru) GetEx(ctx context.Context, key string, duration time.Duration) ([]byte, error) {
|
|
v, ok := l.client.Get(key)
|
|
if !ok {
|
|
return nil, ErrorKeyNotFound
|
|
}
|
|
|
|
if v.duration == 0 {
|
|
return v.bs, nil
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
if now.Sub(v.last) > v.duration {
|
|
l.client.Remove(key)
|
|
return nil, ErrorKeyNotFound
|
|
}
|
|
|
|
l.client.Add(key, &_lru_value{
|
|
duration: duration,
|
|
last: now,
|
|
bs: v.bs,
|
|
})
|
|
|
|
return v.bs, nil
|
|
}
|
|
|
|
func (l *_lru) GetExScan(ctx context.Context, key string, duration time.Duration) interfaces.Scanner {
|
|
return newScanner(l.GetEx(ctx, key, duration))
|
|
}
|
|
|
|
func (l *_lru) Set(ctx context.Context, key string, value any) error {
|
|
bs, err := handleValue(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
l.client.Add(key, &_lru_value{
|
|
duration: 0,
|
|
last: time.Now(),
|
|
bs: bs,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (l *_lru) SetEx(ctx context.Context, key string, value any, duration time.Duration) error {
|
|
bs, err := handleValue(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
l.client.Add(key, &_lru_value{
|
|
duration: duration,
|
|
last: time.Now(),
|
|
bs: bs,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (l *_lru) Del(ctx context.Context, keys ...string) error {
|
|
for _, key := range keys {
|
|
l.client.Remove(key)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func newLRUCache() (interfaces.Cacher, error) {
|
|
client := expirable.NewLRU[string, *_lru_value](1024*1024, nil, 0)
|
|
|
|
return &_lru{client: client}, nil
|
|
}
|