mirror of
https://github.com/samuelncui/yatm.git
synced 2026-11-08 04:18:03 +00:00
Unify file queries and Scan execution, retain indexed Identical results, improve Job and Preview workflows, and verify release packaging.
82 lines
1.5 KiB
Go
82 lines
1.5 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
)
|
|
|
|
func Cache[K comparable, V any](f func(in K) V) func(in K) V {
|
|
cache := new(sync.Map)
|
|
return func(in K) V {
|
|
cached, has := cache.Load(in)
|
|
if has {
|
|
return cached.(V)
|
|
}
|
|
|
|
out := f(in)
|
|
cache.Store(in, out)
|
|
return out
|
|
}
|
|
}
|
|
|
|
func ThreadUnsafeCache[K comparable, V any](f func(in K) V) func(in K) V {
|
|
cache := make(map[K]V, 32)
|
|
return func(in K) V {
|
|
cached, has := cache[in]
|
|
if has {
|
|
return cached
|
|
}
|
|
|
|
out := f(in)
|
|
cache[in] = out
|
|
return out
|
|
}
|
|
}
|
|
|
|
type CacheOnce[K comparable, V any] struct {
|
|
cached sync.Map
|
|
getter func(context.Context, K) (V, error)
|
|
}
|
|
|
|
type cacheOnceItem[V any] struct {
|
|
once sync.Once
|
|
value V
|
|
err error
|
|
}
|
|
|
|
func NewCacheOnce[K comparable, V any](getter func(context.Context, K) (V, error)) *CacheOnce[K, V] {
|
|
return &CacheOnce[K, V]{getter: getter}
|
|
}
|
|
|
|
func (c *CacheOnce[K, V]) Get(ctx context.Context, req K) (V, error) {
|
|
if v, have := c.cached.Load(req); have {
|
|
item, ok := v.(*cacheOnceItem[V])
|
|
if ok {
|
|
val, err := c.get(ctx, item, req)
|
|
if err == nil {
|
|
return val, nil
|
|
}
|
|
c.Remove(req)
|
|
}
|
|
}
|
|
|
|
v, _ := c.cached.LoadOrStore(req, &cacheOnceItem[V]{})
|
|
return c.get(ctx, v.(*cacheOnceItem[V]), req)
|
|
}
|
|
|
|
func (c *CacheOnce[K, V]) Remove(req K) {
|
|
c.cached.Delete(req)
|
|
}
|
|
|
|
func (c *CacheOnce[K, V]) get(ctx context.Context, item *cacheOnceItem[V], key K) (V, error) {
|
|
item.once.Do(func() {
|
|
v, e := c.getter(ctx, key)
|
|
if e != nil {
|
|
item.err = e
|
|
return
|
|
}
|
|
item.value = v
|
|
})
|
|
return item.value, item.err
|
|
}
|