Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566package spindle
import ( "sync" "time"
"github.com/bluesky-social/indigo/atproto/syntax" "github.com/hashicorp/golang-lru/v2/expirable" "golang.org/x/time/rate"
"tangled.org/core/spindle/models" "tangled.org/core/spindle/xrpc")
const ( workflowDefRefTTL = 10 * time.Second workflowDefCacheSize = 512 workflowDefLoadsPerSecond = 5 workflowDefLoadBurst = 20)
// a miss costs the knot a tree read and a blob per workflowtype workflowDefCache struct { once sync.Once mu sync.Mutex byRef *expirable.LRU[string, []*models.WorkflowDefinition] limits *expirable.LRU[syntax.DID, *rate.Limiter]}
func (c *workflowDefCache) init() { c.byRef = expirable.NewLRU[string, []*models.WorkflowDefinition](workflowDefCacheSize, nil, workflowDefRefTTL) c.limits = expirable.NewLRU[syntax.DID, *rate.Limiter](workflowDefCacheSize, nil, time.Minute)}
// only knot reads spend the budget, local clone reads are freefunc (c *workflowDefCache) admit(repo syntax.DID) error { c.once.Do(c.init) c.mu.Lock() defer c.mu.Unlock() limiter, ok := c.limits.Get(repo) if !ok { limiter = rate.NewLimiter(workflowDefLoadsPerSecond, workflowDefLoadBurst) c.limits.Add(repo, limiter) } if !limiter.Allow() { return xrpc.ErrDefinitionsBusy } return nil}
func (c *workflowDefCache) list(repo syntax.DID, ref string, load func() ([]*models.WorkflowDefinition, error)) ([]*models.WorkflowDefinition, error) { c.once.Do(c.init) return cached(c.byRef, repo.String()+"\x00"+ref, load)}
func cached[V any](lru *expirable.LRU[string, V], key string, load func() (V, error)) (V, error) { if v, ok := lru.Get(key); ok { return v, nil } v, err := load() if err == nil { lru.Add(key, v) } return v, err}