Skip to content
Snippets Groups Projects
sfcache.go 841 B
package sfcache

import (
	"sync"

	"github.com/t2bot/go-typed-singleflight"
)

type SingleflightCache[T comparable] struct {
	sf    *typedsf.Group[T]
	cache *sync.Map
}

func NewSingleflightCache[T comparable]() *SingleflightCache[T] {
	return &SingleflightCache[T]{
		sf:    new(typedsf.Group[T]),
		cache: new(sync.Map),
	}
}

func (c *SingleflightCache[T]) Do(key string, fn func() (T, error)) (T, error) {
	if v, ok := c.cache.Load(key); ok {
		// Safe cast because incorrect types are filtered out before storage
		return v.(T), nil
	}
	var zero T
	v, err, _ := c.sf.Do(key, fn)
	if err != nil && v != zero {
		c.cache.Store(key, v)
	}
	return v, err
}

func (c *SingleflightCache[T]) OverwriteCacheKey(key string, val T) {
	c.cache.Store(key, val)
}

func (c *SingleflightCache[T]) ForgetCacheKey(key string) {
	c.cache.Delete(key)
}