versioned
API
versioned
packageAPI reference for the versioned
package.
Imports
(9)
S
struct
Cache
Cache wraps a cache.Cache of VersionedValue to keep multiple versions per key.
It exposes the cache.Cache interface for merge.Value while maintaining
up to limit historical versions per key.
v1/cache/versioned/versioned.go:19-33
type Cache struct
Fields
| Name | Type | Description |
|---|---|---|
| base | cache.Cache[merge.VersionedValue[T]] | |
| limit | int | |
| mu | sync.Mutex | |
| order | *list.List | |
| entries | map[string]*list.Element | |
| maxEntries | int | |
| hits | atomic.Uint64 | |
| misses | atomic.Uint64 | |
| evictions | atomic.Uint64 | |
| hitCounter | prometheus.Counter | |
| missCounter | prometheus.Counter | |
| evictionCounter | prometheus.Counter |
T
type
Option
Option configures the versioned cache.
v1/cache/versioned/versioned.go:36-36
type Option func(*Cache[T])
F
function
WithMaxEntries
WithMaxEntries sets a global LRU limit on the number of keys stored.
Parameters
n
int
Returns
Option[T]
v1/cache/versioned/versioned.go:39-41
func WithMaxEntries[T any](n int) Option[T]
{
return func(c *Cache[T]) { c.maxEntries = n }
}
F
function
WithMetrics
WithMetrics enables Prometheus metrics collection using the provided registerer.
Parameters
Returns
Option[T]
v1/cache/versioned/versioned.go:44-60
func WithMetrics[T any](reg prometheus.Registerer) Option[T]
{
return func(c *Cache[T]) {
c.hitCounter = prometheus.NewCounter(prometheus.CounterOpts{
Name: "warp_versioned_cache_hits_total",
Help: "Total number of versioned cache hits",
})
c.missCounter = prometheus.NewCounter(prometheus.CounterOpts{
Name: "warp_versioned_cache_misses_total",
Help: "Total number of versioned cache misses",
})
c.evictionCounter = prometheus.NewCounter(prometheus.CounterOpts{
Name: "warp_versioned_cache_evictions_total",
Help: "Total number of versioned cache evictions",
})
reg.MustRegister(c.hitCounter, c.missCounter, c.evictionCounter)
}
}
F
function
New
New creates a new versioned cache with the provided base cache and history limit.
Parameters
Returns
*Cache[T]
v1/cache/versioned/versioned.go:63-74
func New[T any](base cache.Cache[merge.VersionedValue[T]], limit int, opts ...Option[T]) *Cache[T]
{
c := &Cache[T]{
base: base,
limit: limit,
order: list.New(),
entries: make(map[string]*list.Element),
}
for _, opt := range opts {
opt(c)
}
return c
}
S
struct
Metrics
Metrics exposes cache statistics.
v1/cache/versioned/versioned.go:191-195
type Metrics struct
Fields
| Name | Type | Description |
|---|---|---|
| Hits | uint64 | |
| Misses | uint64 | |
| Evictions | uint64 |
F
function
TestCacheSetGetHistory
Parameters
t
v1/cache/versioned/versioned_test.go:12-39
func TestCacheSetGetHistory(t *testing.T)
{
base := cache.NewInMemory[merge.VersionedValue[int]]()
c := New(base, 3)
ctx := context.Background()
v1 := merge.Value[int]{Data: 1, Timestamp: time.Now().Add(-3 * time.Minute)}
v2 := merge.Value[int]{Data: 2, Timestamp: time.Now().Add(-2 * time.Minute)}
v3 := merge.Value[int]{Data: 3, Timestamp: time.Now().Add(-1 * time.Minute)}
if err := c.Set(ctx, "k", v1, time.Minute); err != nil {
t.Fatalf("set v1: %v", err)
}
if err := c.Set(ctx, "k", v2, time.Minute); err != nil {
t.Fatalf("set v2: %v", err)
}
if err := c.Set(ctx, "k", v3, time.Minute); err != nil {
t.Fatalf("set v3: %v", err)
}
got, ok, err := c.Get(ctx, "k")
if err != nil || !ok || got.Data != 3 {
t.Fatalf("expected latest=3 got %v ok %v err %v", got.Data, ok, err)
}
at, ok, err := c.GetAt(ctx, "k", v2.Timestamp.Add(time.Millisecond))
if err != nil || !ok || at.Data != 2 {
t.Fatalf("expected value at v2, got %v ok %v err %v", at.Data, ok, err)
}
}
F
function
TestCacheHistoryLimit
Parameters
t
v1/cache/versioned/versioned_test.go:41-58
func TestCacheHistoryLimit(t *testing.T)
{
base := cache.NewInMemory[merge.VersionedValue[int]]()
c := New(base, 2)
ctx := context.Background()
now := time.Now()
v1 := merge.Value[int]{Data: 1, Timestamp: now.Add(-3 * time.Minute)}
v2 := merge.Value[int]{Data: 2, Timestamp: now.Add(-2 * time.Minute)}
v3 := merge.Value[int]{Data: 3, Timestamp: now.Add(-1 * time.Minute)}
_ = c.Set(ctx, "k", v1, time.Minute)
_ = c.Set(ctx, "k", v2, time.Minute)
_ = c.Set(ctx, "k", v3, time.Minute)
// v1 should be evicted due to limit 2
if _, ok, _ := c.GetAt(ctx, "k", v1.Timestamp); ok {
t.Fatal("expected oldest version evicted")
}
}
F
function
TestCacheInvalidate
Parameters
t
v1/cache/versioned/versioned_test.go:60-74
func TestCacheInvalidate(t *testing.T)
{
base := cache.NewInMemory[merge.VersionedValue[int]]()
c := New(base, 1)
ctx := context.Background()
mv := merge.Value[int]{Data: 1, Timestamp: time.Now()}
if err := c.Set(ctx, "k", mv, time.Minute); err != nil {
t.Fatalf("set: %v", err)
}
if err := c.Invalidate(ctx, "k"); err != nil {
t.Fatalf("invalidate: %v", err)
}
if _, ok, _ := c.Get(ctx, "k"); ok {
t.Fatal("expected key removed after invalidate")
}
}
F
function
TestCacheGlobalEviction
Parameters
t
v1/cache/versioned/versioned_test.go:76-94
func TestCacheGlobalEviction(t *testing.T)
{
base := cache.NewInMemory[merge.VersionedValue[int]]()
c := New(base, 1, WithMaxEntries[int](1))
ctx := context.Background()
mv := merge.Value[int]{Data: 1, Timestamp: time.Now()}
if err := c.Set(ctx, "k1", mv, time.Minute); err != nil {
t.Fatalf("set k1: %v", err)
}
if err := c.Set(ctx, "k2", mv, time.Minute); err != nil {
t.Fatalf("set k2: %v", err)
}
if _, ok, _ := c.Get(ctx, "k1"); ok {
t.Fatal("expected k1 evicted due to max entries")
}
m := c.Metrics()
if m.Evictions != 1 {
t.Fatalf("expected 1 eviction got %d", m.Evictions)
}
}
F
function
TestCacheMetricsCounters
Parameters
t
v1/cache/versioned/versioned_test.go:96-120
func TestCacheMetricsCounters(t *testing.T)
{
base := cache.NewInMemory[merge.VersionedValue[int]]()
c := New(base, 1)
ctx := context.Background()
now := time.Now()
if err := c.Set(ctx, "present", merge.Value[int]{Data: 1, Timestamp: now}, time.Minute); err != nil {
t.Fatalf("set present: %v", err)
}
if _, ok, err := c.Get(ctx, "present"); err != nil || !ok {
t.Fatalf("expected cache hit, got ok=%v err=%v", ok, err)
}
if _, ok, err := c.Get(ctx, "missing"); err != nil || ok {
t.Fatalf("expected cache miss, got ok=%v err=%v", ok, err)
}
metrics := c.Metrics()
if metrics.Hits != 1 {
t.Fatalf("expected 1 hit, got %d", metrics.Hits)
}
if metrics.Misses != 1 {
t.Fatalf("expected 1 miss, got %d", metrics.Misses)
}
}