You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
1.6 KiB

package mw
import (
"context"
"fmt"
"sync"
"time"
"gitoa.ru/go-4devs/cache"
)
type key struct {
key interface{}
ctxPrefix string
}
func (k key) Value() interface{} {
return k.key
}
func (k key) String() string {
return fmt.Sprint(k.ctxPrefix, k.key)
}
// WithClearByContext clear cache if context done.
func WithClearByContext(ctxKey interface{}) cache.Configure {
operation := func(ctx context.Context, op string, item *cache.Item, next cache.Provider) error {
ctxPrefix, ok := ctx.Value(ctxKey).(string)
if !ok {
return fmt.Errorf("%w: must be unique ctx key", cache.ErrKeyNotValid)
}
k := item.Key.Key
item.Key.Key = key{
key: k,
ctxPrefix: ctxPrefix,
}
return next(ctx, op, item)
}
return cache.WithMiddleware(
func(ctx context.Context, op string, item *cache.Item, next cache.Provider) error {
if op == cache.OperationSet {
go func(ctx context.Context, item *cache.Item) {
<-ctx.Done()
_ = next(ctx, cache.OperationDelete, item)
}(ctx, item)
}
return operation(ctx, op, item, next)
})
}
// WithClearByTTL clear cache by key after ttl.
func WithClearByTTL() cache.Configure {
keys := make(map[cache.Key]*time.Timer)
mu := sync.Mutex{}
return cache.WithHandleSet(func(ctx context.Context, op string, item *cache.Item, next cache.Provider) error {
if item.TTL > 0 {
go func() {
mu.Lock()
defer mu.Unlock()
if t, ok := keys[item.Key]; ok {
t.Reset(item.TTL)
} else {
keys[item.Key] = time.AfterFunc(item.TTL, func() {
_ = next(ctx, cache.OperationDelete, item)
delete(keys, item.Key)
})
}
}()
}
return next(ctx, op, item)
})
}