mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-10-27 11:35:04 +08:00
this fix a panic that can be replicated using the video thumbnail plugin, opening up a page with a lot of videos. Under the hood, the server would call ffmpeg that would make a bunch of HTTP range requests that would call the cache concurrently, hence causing the panic
109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/mitchellh/hashstructure"
|
|
"github.com/patrickmn/go-cache"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type AppCache struct {
|
|
Cache *cache.Cache
|
|
sync.Mutex
|
|
}
|
|
|
|
func (a *AppCache) Get(key interface{}) interface{} {
|
|
hash, err := hashstructure.Hash(key, nil)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
a.Lock()
|
|
defer a.Unlock()
|
|
value, found := a.Cache.Get(fmt.Sprintf("%d", hash))
|
|
if found == false {
|
|
return nil
|
|
}
|
|
return value
|
|
}
|
|
|
|
func (a *AppCache) Set(key map[string]string, value interface{}) {
|
|
hash, err := hashstructure.Hash(key, nil)
|
|
if err != nil {
|
|
return
|
|
}
|
|
a.Cache.Set(fmt.Sprint(hash), value, cache.DefaultExpiration)
|
|
}
|
|
|
|
func (a *AppCache) SetKey(key string, value interface{}) {
|
|
a.Cache.Set(key, value, cache.DefaultExpiration)
|
|
}
|
|
|
|
func (a *AppCache) Del(key map[string]string) {
|
|
hash, _ := hashstructure.Hash(key, nil)
|
|
a.Cache.Delete(fmt.Sprint(hash))
|
|
}
|
|
|
|
func (a *AppCache) OnEvict(fn func(string, interface{})) {
|
|
a.Cache.OnEvicted(fn)
|
|
}
|
|
|
|
func NewAppCache(arg ...time.Duration) AppCache {
|
|
var retention time.Duration = 5
|
|
var cleanup time.Duration = 10
|
|
if len(arg) > 0 {
|
|
retention = arg[0]
|
|
if len(arg) > 1 {
|
|
cleanup = arg[1]
|
|
}
|
|
}
|
|
c := AppCache{}
|
|
c.Cache = cache.New(retention*time.Minute, cleanup*time.Minute)
|
|
return c
|
|
}
|
|
|
|
func NewQuickCache(arg ...time.Duration) AppCache {
|
|
var retention time.Duration = 5
|
|
var cleanup time.Duration = 10
|
|
if len(arg) > 0 {
|
|
retention = arg[0]
|
|
if len(arg) > 1 {
|
|
cleanup = arg[1]
|
|
}
|
|
}
|
|
c := AppCache{}
|
|
c.Cache = cache.New(retention*time.Second, cleanup*time.Second)
|
|
return c
|
|
}
|
|
|
|
// ============================================================================
|
|
|
|
type KeyValueStore struct {
|
|
cache map[string]interface{}
|
|
sync.RWMutex
|
|
}
|
|
|
|
func NewKeyValueStore() KeyValueStore {
|
|
return KeyValueStore{cache: make(map[string]interface{})}
|
|
}
|
|
|
|
func (this *KeyValueStore) Get(key string) interface{} {
|
|
var val interface{}
|
|
this.RLock()
|
|
val = this.cache[key]
|
|
this.RUnlock()
|
|
return val
|
|
}
|
|
|
|
func (this *KeyValueStore) Set(key string, value interface{}) {
|
|
this.Lock()
|
|
this.cache[key] = value
|
|
this.Unlock()
|
|
}
|
|
|
|
func (this *KeyValueStore) Clear() {
|
|
this.Lock()
|
|
this.cache = make(map[string]interface{})
|
|
this.Unlock()
|
|
}
|