MCPcopy Index your code
hub / github.com/jellydator/ttlcache

github.com/jellydator/ttlcache @v3.4.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v3.4.1 ↗ · + Follow
192 symbols 584 edges 18 files 118 documented · 61% 36 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

TTLCache - an in-memory cache with item expiration and generics

Go Reference Build Status Coverage Status Go Report Card

Features

  • Simple API
  • Type parameters
  • Item expiration and automatic deletion
  • Automatic expiration time extension on each Get call
  • Loader interface that may be used to load/lazily initialize missing cache items
  • Thread safety
  • Event handlers (insertion, update, and eviction)
  • Metrics

Installation

go get github.com/jellydator/ttlcache/v3

Usage

The main type of ttlcache is Cache. It represents a single in-memory data store.

To create a new instance of ttlcache.Cache, the ttlcache.New() function should be called:

func main() {
    cache := ttlcache.New[string, string]()
}

Note that by default, a new cache instance does not let any of its items to expire or be automatically deleted. However, this feature can be activated by passing a few additional options into the ttlcache.New() function and calling the cache.Start() method:

func main() {
    cache := ttlcache.New[string, string](
        ttlcache.WithTTL[string, string](30 * time.Minute),
    )

    go cache.Start() // starts automatic expired item deletion
}

Even though the cache.Start() method handles expired item deletion well, there may be times when the system that uses ttlcache needs to determine when to delete the expired items itself. For example, it may need to delete them only when the resource load is at its lowest (e.g., after midnight, when the number of users/HTTP requests drops). So, in situations like these, instead of calling cache.Start(), the system could periodically call cache.DeleteExpired():

func main() {
    cache := ttlcache.New[string, string](
        ttlcache.WithTTL[string, string](30 * time.Minute),
    )

    for {
        time.Sleep(4 * time.Hour)
        cache.DeleteExpired()
    }
}

The data stored in ttlcache.Cache can be retrieved, checked and updated with Set, Get, Delete, Has etc. methods:

func main() {
    cache := ttlcache.New[string, string](
        ttlcache.WithTTL[string, string](30 * time.Minute),
    )

    // insert data
    cache.Set("first", "value1", ttlcache.DefaultTTL)
    cache.Set("second", "value2", ttlcache.NoTTL)
    cache.Set("third", "value3", ttlcache.DefaultTTL)

    // retrieve data
    item := cache.Get("first")
    fmt.Println(item.Value(), item.ExpiresAt())

    // check key 
    ok := cache.Has("third")

    // delete data
    cache.Delete("second")
    cache.DeleteExpired()
    cache.DeleteAll()

    // retrieve data if in cache otherwise insert data
    item, retrieved := cache.GetOrSet("fourth", "value4", WithTTL[string, string](ttlcache.DefaultTTL))

    // retrieve and delete data
    item, present := cache.GetAndDelete("fourth")
}

To subscribe to insertion, update and eviction events, cache.OnInsertion(), cache.OnUpdate() and cache.OnEviction() methods should be used:

func main() {
    cache := ttlcache.New[string, string](
        ttlcache.WithTTL[string, string](30 * time.Minute),
        ttlcache.WithCapacity[string, string](300),
    )

    cache.OnInsertion(func(ctx context.Context, item *ttlcache.Item[string, string]) {
        fmt.Println(item.Value(), item.ExpiresAt())
    })
    cache.OnUpdate(func(ctx context.Context, item *ttlcache.Item[string, string]) {
        fmt.Println(item.Value(), item.ExpiresAt())
    })
    cache.OnEviction(func(ctx context.Context, reason ttlcache.EvictionReason, item *ttlcache.Item[string, string]) {
        if reason == ttlcache.EvictionReasonCapacityReached {
            fmt.Println(item.Key(), item.Value())
        }
    })

    cache.Set("first", "value1", ttlcache.DefaultTTL)
    cache.DeleteAll()
}

To load data when the cache does not have it, a custom or existing implementation of ttlcache.Loader can be used:

func main() {
    loader := ttlcache.LoaderFunc[string, string](
        func(c *ttlcache.Cache[string, string], key string) *ttlcache.Item[string, string] {
            // load from file/make an HTTP request
            item := c.Set("key from file", "value from file")
            return item
        },
    )
    cache := ttlcache.New[string, string](
        ttlcache.WithLoader[string, string](loader),
    )

    item := cache.Get("key from file")
}

To restrict the cache's capacity based on criteria beyond the number of items it can hold, the ttlcache.WithMaxCost option allows for implementing custom strategies. The following example shows how to limit memory usage for cached entries to ~5KiB.

import (
    "github.com/jellydator/ttlcache"
)

func main() {
    cache := ttlcache.New[string, string](
        ttlcache.WithMaxCost[string, string](5120, func(item ttlcache.CostItem[string, string]) uint64 {
            // Note: The below line doesn't include memory used by internal
            // structures or string metadata for the key and the value.
            return uint64(len(item.Key) + len(item.Value))
        }), 
    )

    cache.Set("first", "value1", ttlcache.DefaultTTL)
}

Examples

See the example directory for applications demonstrating how to use ttlcache.

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Function 94
Method 72
Struct 15
Interface 5
FuncType 4
TypeAlias 2

Languages

Go100%

Modules by API surface

cache_test.go36 symbols
cache.go36 symbols
options.go19 symbols
item.go15 symbols
options_test.go11 symbols
item_test.go11 symbols
expiration_queue.go11 symbols
expiration_queue_test.go10 symbols
examples/httpcache/internal/server/respcache/cache.go9 symbols
examples/dbcache/internal/order/manager.go9 symbols
examples/httpcache/internal/server/server.go6 symbols
examples/dbcache/internal/db/db.go5 symbols

For agents

$ claude mcp add ttlcache \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page