Codebase list golang-github-renekroon-ttlcache / upstream/2.5.0+ds
New upstream version 2.5.0+ds Sascha Steinbiss 2 years ago
4 changed file(s) with 126 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
0 # 2.4.0 (May 2021)
1
2 ## API changes:
3
4 * #42 : Add option to get list of keys
5 * #40: Allow 'Touch' on items without other operation
6
7 // Touch resets the TTL of the key when it exists, returns ErrNotFound if the key is not present.
8 func (cache *Cache) Touch(key string) error
9
10 // GetKeys returns all keys of items in the cache. Returns nil when the cache has been closed.
11 func (cache *Cache) GetKeys() []string
12
013 # 2.3.0 (February 2021)
114
215 ## API changes:
2222
2323 ## Usage
2424
25 You can copy it as a full standalone demo program.
25 You can copy it as a full standalone demo program. The first snippet is basic usage, where the second exploits more options in the cache.
2626
27 Basic:
28 ```go
29 package main
30
31 import (
32 "fmt"
33 "time"
34
35 "github.com/ReneKroon/ttlcache/v2"
36 )
37
38 var notFound = ttlcache.ErrNotFound
39
40 func main() {
41 var cache ttlcache.SimpleCache = ttlcache.NewCache()
42
43 cache.SetTTL(time.Duration(10 * time.Second))
44 cache.Set("MyKey", "MyValue")
45 cache.Set("MyNumber", 1000)
46
47 if val, err := cache.Get("MyKey"); err != notFound {
48 fmt.Printf("Got it: %s\n", val)
49 }
50
51 cache.Remove("MyNumber")
52 cache.Purge()
53 cache.Close()
54 }
55 ```
56
57 Advanced:
2758 ```go
2859 package main
2960
1616
1717 // LoaderFunction can be supplied to retrieve an item where a cache miss occurs. Supply an item specific ttl or Duration.Zero
1818 type LoaderFunction func(key string) (data interface{}, ttl time.Duration, err error)
19
20 // SimpleCache interface enables a quick-start. Interface for basic usage.
21 type SimpleCache interface {
22 Get(key string) (interface{}, error)
23 Set(key string, data interface{}) error
24 SetTTL(ttl time.Duration) error
25 SetWithTTL(key string, data interface{}, ttl time.Duration) error
26 Remove(key string) error
27 Close() error
28 Purge() error
29 }
1930
2031 // Cache is a synchronized map of items that can auto-expire once stale
2132 type Cache struct {
265276 // Get is a thread-safe way to lookup items
266277 // Every lookup, also touches the item, hence extending it's life
267278 func (cache *Cache) Get(key string) (interface{}, error) {
279 return cache.GetByLoader(key, nil)
280 }
281
282 // GetByLoader can take a per key loader function (ie. to propagate context)
283 func (cache *Cache) GetByLoader(key string, customLoaderFunction LoaderFunction) (interface{}, error) {
268284 cache.mutex.Lock()
269285 if cache.isShutDown {
270286 cache.mutex.Unlock()
285301 cache.metrics.Misses++
286302 err = ErrNotFound
287303 }
288 if cache.loaderFunction == nil || exists {
289 cache.mutex.Unlock()
290 }
291
292 if cache.loaderFunction != nil && !exists {
304
305 loaderFunction := cache.loaderFunction
306 if customLoaderFunction != nil {
307 loaderFunction = customLoaderFunction
308 }
309
310 if loaderFunction == nil || exists {
311 cache.mutex.Unlock()
312 }
313
314 if loaderFunction != nil && !exists {
293315 if lock, ok := cache.loaderLock[key]; ok {
294316 // if a lock is present then a fetch is in progress and we wait.
295317 cache.mutex.Unlock()
309331 cache.loaderLock[key] = m
310332 cache.mutex.Unlock()
311333 // cache is not blocked during IO
312 dataToReturn, err = cache.invokeLoader(key)
334 dataToReturn, err = cache.invokeLoader(key, loaderFunction)
313335 cache.mutex.Lock()
314336 m.Broadcast()
315337 // cleanup so that we don't block consecutive access.
326348 return dataToReturn, err
327349 }
328350
329 func (cache *Cache) invokeLoader(key string) (dataToReturn interface{}, err error) {
351 func (cache *Cache) invokeLoader(key string, loaderFunction LoaderFunction) (dataToReturn interface{}, err error) {
330352 var ttl time.Duration
331353
332 dataToReturn, ttl, err = cache.loaderFunction(key)
354 dataToReturn, ttl, err = loaderFunction(key)
333355 if err == nil {
334356 err = cache.SetWithTTL(key, dataToReturn, ttl)
335357 if err != nil {
1717
1818 func TestMain(m *testing.M) {
1919 goleak.VerifyTestMain(m)
20 }
21
22 // The SimpleCache interface enables quick-start.
23 func TestCache_SimpleCache(t *testing.T) {
24 t.Parallel()
25 var cache SimpleCache = NewCache()
26
27 cache.SetTTL(time.Second)
28 cache.Set("k", "v")
29 cache.Get("k")
30 cache.Purge()
31 cache.Close()
32
33 }
34
35 // Issue / PR #39: add customer loader function for each Get() #
36 // some middleware prefers to define specific context's etc per Get.
37 // This is faciliated by supplying a loder function with Get's.
38 func TestCache_GetByLoader(t *testing.T) {
39 t.Parallel()
40 cache := NewCache()
41 defer cache.Close()
42
43 globalLoader := func(key string) (data interface{}, ttl time.Duration, err error) {
44 return "global", 0, nil
45 }
46 cache.SetLoaderFunction(globalLoader)
47
48 localLoader := func(key string) (data interface{}, ttl time.Duration, err error) {
49 return "local", 0, nil
50 }
51
52 key, _ := cache.Get("test")
53 assert.Equal(t, "global", key)
54
55 cache.Remove("test")
56
57 localKey, _ := cache.GetByLoader("test", localLoader)
58 assert.Equal(t, "local", localKey)
59
60 cache.Remove("test")
61
62 globalKey, _ := cache.GetByLoader("test", globalLoader)
63 assert.Equal(t, "global", globalKey)
64
65 cache.Remove("test")
66
67 defaultKey, _ := cache.GetByLoader("test", nil)
68 assert.Equal(t, "global", defaultKey)
69
70 cache.Remove("test")
2071 }
2172
2273 // Issue #38: Feature request: ability to know why an expiry has occurred