mirror of https://github.com/synctv-org/synctv
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
59 lines
1.2 KiB
Go
59 lines
1.2 KiB
Go
package refreshcache
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type RefreshCache[T any] struct {
|
|
lock sync.Mutex
|
|
last int64
|
|
maxAge int64
|
|
refreshFunc func() (T, error)
|
|
data atomic.Pointer[T]
|
|
}
|
|
|
|
func NewRefreshCache[T any](refreshFunc func() (T, error), maxAge time.Duration) *RefreshCache[T] {
|
|
if refreshFunc == nil {
|
|
panic("refreshFunc cannot be nil")
|
|
}
|
|
if maxAge <= 0 {
|
|
panic("maxAge must be positive")
|
|
}
|
|
return &RefreshCache[T]{
|
|
refreshFunc: refreshFunc,
|
|
maxAge: int64(maxAge),
|
|
}
|
|
}
|
|
|
|
func (r *RefreshCache[T]) Get() (data T, err error) {
|
|
if time.Now().UnixNano()-atomic.LoadInt64(&r.last) < r.maxAge {
|
|
return *r.data.Load(), nil
|
|
}
|
|
r.lock.Lock()
|
|
defer r.lock.Unlock()
|
|
if time.Now().UnixNano()-r.last < r.maxAge {
|
|
return *r.data.Load(), nil
|
|
}
|
|
defer func() {
|
|
if err == nil {
|
|
r.data.Store(&data)
|
|
atomic.StoreInt64(&r.last, time.Now().UnixNano())
|
|
}
|
|
}()
|
|
return r.refreshFunc()
|
|
}
|
|
|
|
func (r *RefreshCache[T]) Refresh() (data T, err error) {
|
|
r.lock.Lock()
|
|
defer r.lock.Unlock()
|
|
defer func() {
|
|
if err == nil {
|
|
r.data.Store(&data)
|
|
atomic.StoreInt64(&r.last, time.Now().UnixNano())
|
|
}
|
|
}()
|
|
return r.refreshFunc()
|
|
}
|