From a7857e51a62660c05aa698b3a86c6e088d94f732 Mon Sep 17 00:00:00 2001 From: Francesco Cosentino Date: Wed, 4 Jan 2023 01:31:30 +0100 Subject: [PATCH] Get example with mimor cosmetics --- examples/README.md | 4 +- examples/get/get.go | 65 +++++++++++++++++++++++++++ hypercache.go | 18 +++++--- tests/hypercache_get_multiple_test.go | 8 ++-- 4 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 examples/get/get.go diff --git a/examples/README.md b/examples/README.md index d9ec00d..29b041b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,4 +4,6 @@ This directory contains examples of using the HyperCache package. **Do not use these examples in production.** All the code in this directory is for demonstration purposes only. -1. [List](./list/list.go) - A simple example of using the HyperCache package to store a list of items and retrieve the list filtering and sorting the results. +1. [`Get`](./get/get.go) - An example of using the HyperCache package to fetch one or more items and retrieve a single or multiple items from cache. + +2. [List](./list/list.go) - A simple example of using the HyperCache package to store a list of items and retrieve the list filtering and sorting the results. diff --git a/examples/get/get.go b/examples/get/get.go new file mode 100644 index 0000000..9a5b85e --- /dev/null +++ b/examples/get/get.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + "log" + "time" + + "github.com/hyp3rd/hypercache" +) + +func main() { + // Create a new HyperCache with a capacity of 10 + cache, err := hypercache.NewHyperCache(10) + if err != nil { + fmt.Println(err) + return + } + // Close the cache when the program exits + defer cache.Close() + + log.Println("adding items to the cache") + // Add 10 items to the cache + for i := 0; i < 10; i++ { + key := fmt.Sprintf("key%d", i) + val := fmt.Sprintf("val%d", i) + + err = cache.Set(key, val, time.Minute) + + if err != nil { + fmt.Printf("unexpected error: %v\n", err) + } + } + + log.Println("fetching items from the cache using the `GetMultiple` method") + // Retrieve the specific of items from the cache + items, errs := cache.GetMultiple("key1", "key7", "key9", "key11") + + // Print the errors if any + for k, e := range errs { + log.Printf("error fetching item %s: %s\n", k, e) + } + + // Print the items + for k, v := range items { + fmt.Println(k, v) + } + + log.Println("fetching items from the cache using the `GetOrSet` method") + // Retrieve a specific of item from the cache + // If the item is not found, set it and return the value + val, err := cache.GetOrSet("key11", "val11", time.Minute) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(val) + + log.Println("fetching items from the cache using the simple `Get` method") + item, ok := cache.Get("key7") + if !ok { + fmt.Println("item not found") + return + } + fmt.Println(item) +} diff --git a/hypercache.go b/hypercache.go index 1b361b2..c492c85 100644 --- a/hypercache.go +++ b/hypercache.go @@ -335,21 +335,29 @@ func (cache *HyperCache) GetOrSet(key string, value interface{}, expiration time } // GetMultiple retrieves the items with the given keys from the cache. If an item is not found, it is not included in the returned map. -func (cache *HyperCache) GetMultiple(keys ...string) (result map[string]interface{}, errors []error) { - result = make(map[string]interface{}, len(keys)) +func (cache *HyperCache) GetMultiple(keys ...string) (result map[string]interface{}, errors map[string]error) { + result = make(map[string]interface{}, len(keys)) // Preallocate the result map + errors = make(map[string]error, len(keys)) // Preallocate the errors map + for _, key := range keys { item, ok := cache.items.Get(key) if !ok { - errors = append(errors, ErrKeyNotFound) + // Add the key to the errors map and continue + errors[key] = ErrKeyNotFound continue } + // Check if the item has expired if item.Expired() { + // Put the item back in the pool CacheItemPool.Put(item) - errors = append(errors, ErrKeyExpired) + // Add the key to the errors map + errors[key] = ErrKeyExpired + // Trigger the expiration loop go cache.expirationLoop() } else { item.Touch() // Update the last access time and access count + // Add the item to the result map result[key] = item.Value } @@ -406,7 +414,7 @@ func (cache *HyperCache) List(options ...FilteringOption) ([]*CacheItem, error) return items, nil } -// Remove removes the items with the given key from the cache. If an item is not found, it does nothing. +// Remove removes items with the given key from the cache. If an item is not found, it does nothing. func (cache *HyperCache) Remove(keys ...string) { for _, key := range keys { cache.evictionAlgorithm.Delete(key) diff --git a/tests/hypercache_get_multiple_test.go b/tests/hypercache_get_multiple_test.go index ad879f2..c1e1e35 100644 --- a/tests/hypercache_get_multiple_test.go +++ b/tests/hypercache_get_multiple_test.go @@ -14,14 +14,14 @@ func TestGetMultiple(t *testing.T) { name string keys []string wantValues map[string]interface{} - wantErrs []error + wantErrs map[string]error setup func(*hypercache.HyperCache) }{ { name: "get multiple keys with values", keys: []string{"key1", "key2", "key3"}, wantValues: map[string]interface{}{"key1": 1, "key2": 2, "key3": 3}, - wantErrs: []error(nil), + wantErrs: map[string]error(map[string]error{}), setup: func(cache *hypercache.HyperCache) { cache.Set("key1", 1, 0) cache.Set("key2", 2, 0) @@ -32,7 +32,7 @@ func TestGetMultiple(t *testing.T) { name: "get multiple keys with missing values", keys: []string{"key1", "key2", "key3"}, wantValues: map[string]interface{}{"key1": 1, "key3": 3}, - wantErrs: []error{hypercache.ErrKeyNotFound}, + wantErrs: map[string]error{"key2": hypercache.ErrKeyNotFound}, setup: func(cache *hypercache.HyperCache) { cache.Set("key1", 1, 0) cache.Set("key3", 3, 0) @@ -42,7 +42,7 @@ func TestGetMultiple(t *testing.T) { name: "get multiple keys with expired values", keys: []string{"key1", "key2", "key3"}, wantValues: map[string]interface{}{"key2": 2, "key3": 3}, - wantErrs: []error{hypercache.ErrKeyNotFound}, + wantErrs: map[string]error{"key1": hypercache.ErrKeyNotFound}, setup: func(cache *hypercache.HyperCache) { cache.Set("key1", 1, time.Millisecond) time.Sleep(2 * time.Millisecond)