1## TTLCache - an in-memory cache with item expiration and generics
2
3[](https://pkg.go.dev/github.com/jellydator/ttlcache/v3)
4[](https://github.com/jellydator/ttlcache/actions/workflows/go.yml)
5[](https://coveralls.io/github/jellydator/ttlcache?branch=master)
6[](https://goreportcard.com/report/github.com/jellydator/ttlcache/v3)
7
8## Features
9- Simple API
10- Type parameters
11- Item expiration and automatic deletion
12- Automatic expiration time extension on each `Get` call
13- `Loader` interface that may be used to load/lazily initialize missing cache
14items
15- Event handlers (insertion and eviction)
16- Metrics
17
18## Installation
19```
20go get github.com/jellydator/ttlcache/v3
21```
22
23## Usage
24The main type of `ttlcache` is `Cache`. It represents a single
25in-memory data store.
26
27To create a new instance of `ttlcache.Cache`, the `ttlcache.New()` function
28should be called:
29```go
30func main() {
31 cache := ttlcache.New[string, string]()
32}
33```
34
35Note that by default, a new cache instance does not let any of its
36items to expire or be automatically deleted. However, this feature
37can be activated by passing a few additional options into the
38`ttlcache.New()` function and calling the `cache.Start()` method:
39```go
40func main() {
41 cache := ttlcache.New[string, string](
42 ttlcache.WithTTL[string, string](30 * time.Minute),
43 )
44
45 go cache.Start() // starts automatic expired item deletion
46}
47```
48
49Even though the `cache.Start()` method handles expired item deletion well,
50there may be times when the system that uses `ttlcache` needs to determine
51when to delete the expired items itself. For example, it may need to
52delete them only when the resource load is at its lowest (e.g., after
53midnight, when the number of users/HTTP requests drops). So, in situations
54like these, instead of calling `cache.Start()`, the system could
55periodically call `cache.DeleteExpired()`:
56```go
57func main() {
58 cache := ttlcache.New[string, string](
59 ttlcache.WithTTL[string, string](30 * time.Minute),
60 )
61
62 for {
63 time.Sleep(4 * time.Hour)
64 cache.DeleteExpired()
65 }
66}
67```
68
69The data stored in `ttlcache.Cache` can be retrieved, checked and updated with
70`Set`, `Get`, `Delete`, `Has` etc. methods:
71```go
72func main() {
73 cache := ttlcache.New[string, string](
74 ttlcache.WithTTL[string, string](30 * time.Minute),
75 )
76
77 // insert data
78 cache.Set("first", "value1", ttlcache.DefaultTTL)
79 cache.Set("second", "value2", ttlcache.NoTTL)
80 cache.Set("third", "value3", ttlcache.DefaultTTL)
81
82 // retrieve data
83 item := cache.Get("first")
84 fmt.Println(item.Value(), item.ExpiresAt())
85
86 // check key
87 ok := cache.Has("third")
88
89 // delete data
90 cache.Delete("second")
91 cache.DeleteExpired()
92 cache.DeleteAll()
93
94 // retrieve data if in cache otherwise insert data
95 item, retrieved := cache.GetOrSet("fourth", "value4", WithTTL[string, string](ttlcache.DefaultTTL))
96
97 // retrieve and delete data
98 item, present := cache.GetAndDelete("fourth")
99}
100```
101
102To subscribe to insertion and eviction events, `cache.OnInsertion()` and
103`cache.OnEviction()` methods should be used:
104```go
105func main() {
106 cache := ttlcache.New[string, string](
107 ttlcache.WithTTL[string, string](30 * time.Minute),
108 ttlcache.WithCapacity[string, string](300),
109 )
110
111 cache.OnInsertion(func(ctx context.Context, item *ttlcache.Item[string, string]) {
112 fmt.Println(item.Value(), item.ExpiresAt())
113 })
114 cache.OnEviction(func(ctx context.Context, reason ttlcache.EvictionReason, item *ttlcache.Item[string, string]) {
115 if reason == ttlcache.EvictionReasonCapacityReached {
116 fmt.Println(item.Key(), item.Value())
117 }
118 })
119
120 cache.Set("first", "value1", ttlcache.DefaultTTL)
121 cache.DeleteAll()
122}
123```
124
125To load data when the cache does not have it, a custom or
126existing implementation of `ttlcache.Loader` can be used:
127```go
128func main() {
129 loader := ttlcache.LoaderFunc[string, string](
130 func(c *ttlcache.Cache[string, string], key string) *ttlcache.Item[string, string] {
131 // load from file/make an HTTP request
132 item := c.Set("key from file", "value from file")
133 return item
134 },
135 )
136 cache := ttlcache.New[string, string](
137 ttlcache.WithLoader[string, string](loader),
138 )
139
140 item := cache.Get("key from file")
141}
142```
View as plain text