Files
ccache/secondarycache.go
Karl Seguin 55899506d5 Add setable buffer to handle sets in order to allow a hard max size limit
Previously, items were pushed onto the frequency linked list via the promotable
buffer. As a general rule, you want your protobable buffer to be quite large,
since you don't want to block Gets. But because Set uses the same buffer, the
cache could grow to MaxSize + cap(promotables).

Sets are now "promoted" via a new "setables" buffer. These are handled exactly
the same way as before, but having it be a separate buffer means they can have
different capacity. Thus, using the new `SetableBuffer(int)` configuration
method can help set a hard limit on the maximum size.
2023-03-08 12:44:20 +08:00

73 lines
1.8 KiB
Go

package ccache
import "time"
type SecondaryCache[T any] struct {
bucket *bucket[T]
pCache *LayeredCache[T]
}
// Get the secondary key.
// The semantics are the same as for LayeredCache.Get
func (s *SecondaryCache[T]) Get(secondary string) *Item[T] {
return s.bucket.get(secondary)
}
// Set the secondary key to a value.
// The semantics are the same as for LayeredCache.Set
func (s *SecondaryCache[T]) Set(secondary string, value T, duration time.Duration) *Item[T] {
item, existing := s.bucket.set(secondary, value, duration, false)
if existing != nil {
s.pCache.deletables <- existing
}
s.pCache.promotables <- item
return item
}
// Fetch or set a secondary key.
// The semantics are the same as for LayeredCache.Fetch
func (s *SecondaryCache[T]) Fetch(secondary string, duration time.Duration, fetch func() (T, error)) (*Item[T], error) {
item := s.Get(secondary)
if item != nil {
return item, nil
}
value, err := fetch()
if err != nil {
return nil, err
}
return s.Set(secondary, value, duration), nil
}
// Delete a secondary key.
// The semantics are the same as for LayeredCache.Delete
func (s *SecondaryCache[T]) Delete(secondary string) bool {
item := s.bucket.delete(secondary)
if item != nil {
s.pCache.deletables <- item
return true
}
return false
}
// Replace a secondary key.
// The semantics are the same as for LayeredCache.Replace
func (s *SecondaryCache[T]) Replace(secondary string, value T) bool {
item := s.Get(secondary)
if item == nil {
return false
}
s.Set(secondary, value, item.TTL())
return true
}
// Track a secondary key.
// The semantics are the same as for LayeredCache.TrackingGet
func (c *SecondaryCache[T]) TrackingGet(secondary string) TrackedItem[T] {
item := c.Get(secondary)
if item == nil {
return nil
}
item.track()
return item
}