Skip to content

goVerta/cache

Repository files navigation

cache – In-memory cache with TTL

Deterministic. Minimal. Fast. A tiny, thread-safe in-memory key-value cache with per-key TTL and a background janitor. Think of it as a small Redis-flavored TTL cache for Go: set bytes, get bytes, optional capacity, predictable eviction.

Note: This is the only public repository we are publishing; historically we had no public repositories. We are open to contributions and feedback. But we don't public.

Install

go get github.com/goverta/cache

Usage

package main

import (
    "time"
    "github.com/goverta/cache"
)

func main() {
    c := cache.New(cache.Options{JanitorInterval: 500 * time.Millisecond, MaxEntries: 0})
    defer c.Close()
    c.Set("token", []byte("abc123"), 2*time.Second)
    v, ok := c.Get("token")
    _, _ = v, ok
}

Features

  • Thread-safe operations with sync.RWMutex
  • Per-key TTL with wall-clock semantics
  • Background janitor that evicts expired keys on a ticker
  • Optional capacity via FIFO eviction (MaxEntries), simple and predictable
  • No external dependencies, pure stdlib
  • Copy-on-write and copy-on-read to avoid aliasing

API Surface

type Options struct {
    JanitorInterval time.Duration
    MaxEntries      int
}

func New(opts Options) *cache.Cache
func (*Cache) Set(key string, value []byte, ttl time.Duration) bool
func (*Cache) Get(key string) ([]byte, bool)
func (*Cache) Delete(key string) bool
func (*Cache) Len() int
func (*Cache) Keys() []string
func (*Cache) PurgeExpired()
func (*Cache) Close()

Semantics

  • Set overwrites existing values and returns true
  • TTL=0 means no expiry
  • Get only returns non-expired values
  • Keys/Len exclude expired entries
  • Expired entries are removed by janitor or PurgeExpired()
  • If MaxEntries>0, oldest insertions are evicted first (simple FIFO). Overwrites append a new position in the queue; eviction always removes the oldest still-present key.

Design Notes (small Redis vibes)

  • Storage: map[string]item{value []byte, expiry time.Time}
  • Capacity: append-only FIFO with lazy duplicates; compacted when queue grows > 2× live keys
  • Expiry policy: lazy on read, proactive via janitor, explicit via PurgeExpired
  • Time source: time.Now()
  • Determinism: no randomized eviction; straightforward FIFO and TTL

Patterns

// Capacity-bounded cache
c := cache.New(cache.Options{JanitorInterval: 100 * time.Millisecond, MaxEntries: 1024})
defer c.Close()

// Session token with TTL
c.Set("sess:123", []byte("..."), 15*time.Minute)

// Periodic purge if janitor disabled
c.PurgeExpired()

Performance Notes

  • Reads use RLock and copy result to avoid aliasing
  • Writes Lock once, FIFO eviction is O(1) amortized with lazy compaction
  • For read-heavy workloads, increase GOMAXPROCS and keep MaxEntries unbounded or sufficiently high
  • Benchmarks included; run with -bench flags

Notes

  • Thread-safe via sync.RWMutex
  • Per-key TTL using wall clock
  • Optional capacity via FIFO eviction
  • No external dependencies

Benchmarks

go test -bench . -benchmem

Included:

  • Set/Get no TTL
  • Set/Get with short TTL
  • Parallel Get on prewarmed keys

Roadmap

  • LRU option
  • Metrics hooks
  • Sharding for higher parallelism

Run the example

go test -run Example

About

Tiny in-memory cache for Go. TTL keys. Thread-safe. Zero deps.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages