diff --git a/Makefile b/Makefile index 531e66b..961ab50 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ bench: # run runs the example specified in the example variable with the optional arguments specified in the ARGS variable. run: - go run examples/$(example)/$(example).go $(ARGS) + go run examples/$(example)/*.go $(ARGS) # vet runs the Go vet static analysis tool on all packages in the project. vet: diff --git a/backend/backend.go b/backend/backend.go index ba12f2e..d56445f 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -7,7 +7,7 @@ import ( // IBackendConstrain is the interface that defines the constrain type that must be implemented by cache backends. type IBackendConstrain interface { - InMemory | RedisBackend + InMemory | Redis } // IInMemory is the interface that must be implemented by in-memory cache backends. @@ -25,7 +25,7 @@ type IRedisBackend[T IBackendConstrain] interface { // IBackend[T] is the interface that must be implemented by cache backends. IBackend[T] // List the items in the cache that meet the specified criteria. - List(options ...FilterOption[RedisBackend]) ([]*models.Item, error) + List(options ...FilterOption[Redis]) ([]*models.Item, error) // Clear removes all items from the cache. Clear() error } @@ -58,9 +58,9 @@ func NewBackend[T IBackendConstrain](backendType string, opts ...any) (IBackend[ } return NewInMemory(Options...) case "redis": - Options := make([]Option[RedisBackend], len(opts)) + Options := make([]Option[Redis], len(opts)) for i, option := range opts { - Options[i] = option.(Option[RedisBackend]) + Options[i] = option.(Option[Redis]) } return NewRedisBackend(Options...) default: diff --git a/backend/options.go b/backend/options.go index 3d3ff4f..b0ab041 100644 --- a/backend/options.go +++ b/backend/options.go @@ -20,8 +20,8 @@ func (inm *InMemory) setSortAscending(ascending bool) { inm.SortAscending = ascending } -// setSortAscending sets the `SortAscending` field of the `RedisBackend` backend. -func (rb *RedisBackend) setSortAscending(ascending bool) { +// setSortAscending sets the `SortAscending` field of the `Redis` backend. +func (rb *Redis) setSortAscending(ascending bool) { rb.SortAscending = ascending } @@ -30,8 +30,8 @@ func (inm *InMemory) setSortBy(sortBy string) { inm.SortBy = sortBy } -// setSortBy sets the `SortBy` field of the `RedisBackend` backend. -func (rb *RedisBackend) setSortBy(sortBy string) { +// setSortBy sets the `SortBy` field of the `Redis` backend. +func (rb *Redis) setSortBy(sortBy string) { rb.SortBy = sortBy } @@ -48,11 +48,27 @@ func (inm *InMemory) setFilterFunc(filterFunc FilterFunc) { inm.FilterFunc = filterFunc } -// setFilterFunc sets the `FilterFunc` field of the `RedisBackend` backend. -func (rb *RedisBackend) setFilterFunc(filterFunc FilterFunc) { +// setFilterFunc sets the `FilterFunc` field of the `Redis` backend. +func (rb *Redis) setFilterFunc(filterFunc FilterFunc) { rb.FilterFunc = filterFunc } +// iConfigurableBackend is an interface that defines the methods that a backend should implement to be configurable. +type iConfigurableBackend interface { + // setCapacity sets the capacity of the cache. + setCapacity(capacity int) +} + +// setCapacity sets the `Capacity` field of the `InMemory` backend. +func (inm *InMemory) setCapacity(capacity int) { + inm.capacity = capacity +} + +// setCapacity sets the `Capacity` field of the `Redis` backend. +func (rb *Redis) setCapacity(capacity int) { + rb.capacity = capacity +} + // Option is a function type that can be used to configure the `HyperCache` struct. type Option[T IBackendConstrain] func(*T) @@ -64,22 +80,24 @@ func ApplyOptions[T IBackendConstrain](backend *T, options ...Option[T]) { } // WithCapacity is an option that sets the capacity of the cache. -func WithCapacity[T InMemory](capacity int) Option[InMemory] { - return func(backend *InMemory) { - backend.capacity = capacity +func WithCapacity[T IBackendConstrain](capacity int) Option[T] { + return func(a *T) { + if configurable, ok := any(a).(iConfigurableBackend); ok { + configurable.setCapacity(capacity) + } } } // WithRedisClient is an option that sets the redis client to use. -func WithRedisClient[T RedisBackend](client *redis.Client) Option[RedisBackend] { - return func(backend *RedisBackend) { +func WithRedisClient[T Redis](client *redis.Client) Option[Redis] { + return func(backend *Redis) { backend.rdb = client } } // WithKeysSetName is an option that sets the name of the set that holds the keys of the items in the cache -func WithKeysSetName[T RedisBackend](keysSetName string) Option[RedisBackend] { - return func(backend *RedisBackend) { +func WithKeysSetName[T Redis](keysSetName string) Option[Redis] { + return func(backend *Redis) { backend.keysSetName = keysSetName } } @@ -88,8 +106,8 @@ func WithKeysSetName[T RedisBackend](keysSetName string) Option[RedisBackend] { // - The default serializer is `serializer.MsgpackSerializer`. // - The `serializer.JSONSerializer` can be used to serialize and deserialize the items in the cache as JSON. // - The interface `serializer.ISerializer` can be implemented to use a custom serializer. -func WithSerializer[T RedisBackend](serializer serializer.ISerializer) Option[RedisBackend] { - return func(backend *RedisBackend) { +func WithSerializer[T Redis](serializer serializer.ISerializer) Option[Redis] { + return func(backend *Redis) { backend.Serializer = serializer } } @@ -132,11 +150,4 @@ func WithFilterFunc[T any](fn func(item *models.Item) bool) FilterOption[T] { filterable.setFilterFunc(fn) } } - - // return func(a *T) { - // switch filter := any(a).(type) { - // case *InMemory: - // filter.FilterFunc = fn - // } - // } } diff --git a/backend/redis.go b/backend/redis.go index 42f4eb4..721d74f 100644 --- a/backend/redis.go +++ b/backend/redis.go @@ -12,18 +12,19 @@ import ( "github.com/hyp3rd/hypercache/types" ) -// RedisBackend is a cache backend that stores the items in a redis implementation. -type RedisBackend struct { - rdb *redis.Client // redis client to interact with the redis server - capacity int // capacity of the cache, limits the number of items that can be stored in the cache - keysSetName string // keysSetName is the name of the set that holds the keys of the items in the cache +// Redis is a cache backend that stores the items in a redis implementation. +type Redis struct { + rdb *redis.Client // redis client to interact with the redis server + capacity int // capacity of the cache, limits the number of items that can be stored in the cache + keysSetName string // keysSetName is the name of the set that holds the keys of the items in the cache + // mutex sync.RWMutex // mutex to protect the cache from concurrent access Serializer serializer.ISerializer // Serializer is the serializer used to serialize the items before storing them in the cache SortFilters // SortFilters holds the filters applied when listing the items in the cache } // NewRedisBackend creates a new redis cache with the given options. -func NewRedisBackend[T RedisBackend](redisOptions ...Option[RedisBackend]) (backend IRedisBackend[T], err error) { - rb := &RedisBackend{} +func NewRedisBackend[T Redis](redisOptions ...Option[Redis]) (backend IRedisBackend[T], err error) { + rb := &Redis{} // Apply the backend options ApplyOptions(rb, redisOptions...) @@ -31,18 +32,23 @@ func NewRedisBackend[T RedisBackend](redisOptions ...Option[RedisBackend]) (back if rb.rdb == nil { return nil, errors.ErrNilClient } - // Check if the capacity is valid + // Check if the `capacity` is valid if rb.capacity < 0 { return nil, errors.ErrInvalidCapacity } + // Check if the `keysSetName` is empty if rb.keysSetName == "" { rb.keysSetName = "hypercache" } - rb.Serializer, err = serializer.New("msgpack") - if err != nil { - return nil, err + // Check if the serializer is nil + if rb.Serializer == nil { + // Set a the serializer to default to `msgpack` + rb.Serializer, err = serializer.New("msgpack") + if err != nil { + return nil, err + } } // return the new backend @@ -50,12 +56,12 @@ func NewRedisBackend[T RedisBackend](redisOptions ...Option[RedisBackend]) (back } // Capacity returns the maximum number of items that can be stored in the cache. -func (cacheBackend *RedisBackend) Capacity() int { +func (cacheBackend *Redis) Capacity() int { return cacheBackend.capacity } // SetCapacity sets the capacity of the cache. -func (cacheBackend *RedisBackend) SetCapacity(capacity int) { +func (cacheBackend *Redis) SetCapacity(capacity int) { if capacity < 0 { return } @@ -63,22 +69,22 @@ func (cacheBackend *RedisBackend) SetCapacity(capacity int) { } // itemCount returns the number of items in the cache. -func (cacheBackend *RedisBackend) itemCount() int { +func (cacheBackend *Redis) itemCount() int { count, _ := cacheBackend.rdb.DBSize(context.Background()).Result() return int(count) } // Size returns the number of items in the cache. -func (cacheBackend *RedisBackend) Size() int { +func (cacheBackend *Redis) Size() int { return cacheBackend.itemCount() } // Get retrieves the Item with the given key from the cacheBackend. If the item is not found, it returns nil. -func (cacheBackend *RedisBackend) Get(key string) (item *models.Item, ok bool) { - pipe := cacheBackend.rdb.TxPipeline() +func (cacheBackend *Redis) Get(key string) (item *models.Item, ok bool) { + // pipe := cacheBackend.rdb.Conn().Pipeline() // Check if the key is in the set of keys - // isMember, err := cacheBackend.rdb.SIsMember(context.Background(), cacheBackend.keysSetName, key).Result() - isMember, err := pipe.SIsMember(context.Background(), cacheBackend.keysSetName, key).Result() + isMember, err := cacheBackend.rdb.SIsMember(context.Background(), cacheBackend.keysSetName, key).Result() + // isMember, err := pipe.SIsMember(context.Background(), cacheBackend.keysSetName, key).Result() if err != nil { return nil, false } @@ -88,13 +94,12 @@ func (cacheBackend *RedisBackend) Get(key string) (item *models.Item, ok bool) { // Get the item from the cacheBackend item = models.ItemPool.Get().(*models.Item) - // data, err := cacheBackend.rdb.HGet(context.Background(), key, "data").Bytes() - data, err := pipe.HGet(context.Background(), key, "data").Bytes() - pipe.Exec(context.Background()) + // Return the item to the pool + defer models.ItemPool.Put(item) + data, err := cacheBackend.rdb.HGet(context.Background(), key, "data").Bytes() + // data, _ := pipe.HGet(context.Background(), key, "data").Bytes() + // _, err = pipe.Exec(context.Background()) if err != nil { - // Return the item to the pool - models.ItemPool.Put(item) - // Check if the item is not found if err == redis.Nil { return nil, false @@ -110,13 +115,12 @@ func (cacheBackend *RedisBackend) Get(key string) (item *models.Item, ok bool) { } // Set stores the Item in the cacheBackend. -func (cacheBackend *RedisBackend) Set(item *models.Item) error { +func (cacheBackend *Redis) Set(item *models.Item) error { pipe := cacheBackend.rdb.TxPipeline() // Check if the item is valid if err := item.Valid(); err != nil { // Return the item to the pool - models.ItemPool.Put(item) return err } @@ -124,7 +128,6 @@ func (cacheBackend *RedisBackend) Set(item *models.Item) error { data, err := cacheBackend.Serializer.Marshal(item) if err != nil { // Return the item to the pool - models.ItemPool.Put(item) return err } @@ -152,7 +155,7 @@ func (cacheBackend *RedisBackend) Set(item *models.Item) error { } // List returns a list of all the items in the cacheBackend that match the given filter options. -func (cacheBackend *RedisBackend) List(options ...FilterOption[RedisBackend]) ([]*models.Item, error) { +func (cacheBackend *Redis) List(options ...FilterOption[Redis]) ([]*models.Item, error) { // Apply the filter options ApplyFilterOptions(cacheBackend, options...) @@ -181,15 +184,14 @@ func (cacheBackend *RedisBackend) List(options ...FilterOption[RedisBackend]) ([ for _, cmd := range cmds { data, _ := cmd.(*redis.StringCmd).Bytes() // Ignore the error because it is already checked in the pipeline transaction item := models.ItemPool.Get().(*models.Item) + // Return the item to the pool + defer models.ItemPool.Put(item) err := cacheBackend.Serializer.Unmarshal(data, item) if err == nil { if cacheBackend.FilterFunc != nil && !cacheBackend.FilterFunc(item) { continue } items = append(items, item) - } else { - // Return the item to the pool - models.ItemPool.Put(item) } } @@ -227,13 +229,18 @@ func (cacheBackend *RedisBackend) List(options ...FilterOption[RedisBackend]) ([ } // Remove removes an item from the cache with the given key -func (cacheBackend *RedisBackend) Remove(keys ...string) error { - _, err := cacheBackend.rdb.Del(context.Background(), keys...).Result() +func (cacheBackend *Redis) Remove(keys ...string) error { + pipe := cacheBackend.rdb.TxPipeline() + + pipe.SRem(context.Background(), cacheBackend.keysSetName, keys).Result() + pipe.Del(context.Background(), keys...).Result() + + _, err := pipe.Exec(context.Background()) return err } // Clear removes all items from the cache -func (cacheBackend *RedisBackend) Clear() error { +func (cacheBackend *Redis) Clear() error { _, err := cacheBackend.rdb.FlushDB(context.Background()).Result() return err } diff --git a/backend/redis/options.go b/backend/redis/options.go index e5b5046..21e28aa 100644 --- a/backend/redis/options.go +++ b/backend/redis/options.go @@ -7,7 +7,7 @@ import ( "github.com/go-redis/redis/v9" ) -// Option is a function type that can be used to configure the `RedisBackend`. +// Option is a function type that can be used to configure the `Redis`. type Option func(*redis.Options) // ApplyOptions applies the given options to the given backend. diff --git a/config.go b/config.go index 0cec5ae..1e824a6 100644 --- a/config.go +++ b/config.go @@ -10,8 +10,8 @@ import ( type Config[T backend.IBackendConstrain] struct { // InMemoryOptions is a slice of options that can be used to configure the `InMemory`. InMemoryOptions []backend.Option[backend.InMemory] - // RedisOptions is a slice of options that can be used to configure the `RedisBackend`. - RedisOptions []backend.Option[backend.RedisBackend] + // RedisOptions is a slice of options that can be used to configure the `Redis`. + RedisOptions []backend.Option[backend.Redis] // HyperCacheOptions is a slice of options that can be used to configure `HyperCache`. HyperCacheOptions []Option[T] } @@ -29,7 +29,7 @@ type Config[T backend.IBackendConstrain] struct { func NewConfig[T backend.IBackendConstrain]() *Config[T] { return &Config[T]{ InMemoryOptions: []backend.Option[backend.InMemory]{}, - RedisOptions: []backend.Option[backend.RedisBackend]{}, + RedisOptions: []backend.Option[backend.Redis]{}, HyperCacheOptions: []Option[T]{ WithExpirationInterval[T](30 * time.Minute), WithEvictionAlgorithm[T]("lfu"), diff --git a/eviction/eviction.go b/eviction/eviction.go index 0a7dcb6..51aba41 100644 --- a/eviction/eviction.go +++ b/eviction/eviction.go @@ -45,21 +45,33 @@ func RegisterEvictionAlgorithm(name string, createFunc func(capacity int) (IAlgo algorithmRegistry[name] = createFunc } +// RegisterEvictionAlgorithms registers a set of eviction algorithms. +func RegisterEvictionAlgorithms(algorithms map[string]func(capacity int) (IAlgorithm, error)) { + for name, createFunc := range algorithms { + algorithmRegistry[name] = createFunc + } +} + // Register the default eviction algorithms. func init() { - RegisterEvictionAlgorithm("arc", func(capacity int) (IAlgorithm, error) { - return NewARC(capacity) - }) - RegisterEvictionAlgorithm("lru", func(capacity int) (IAlgorithm, error) { - return NewLRU(capacity) - }) - RegisterEvictionAlgorithm("clock", func(capacity int) (IAlgorithm, error) { - return NewClockAlgorithm(capacity) - }) - RegisterEvictionAlgorithm("lfu", func(capacity int) (IAlgorithm, error) { - return NewLFUAlgorithm(capacity) - }) - RegisterEvictionAlgorithm("cawolfu", func(capacity int) (IAlgorithm, error) { - return NewCAWOLFU(capacity) - }) + // Define the default eviction algorithms. + algorithms := map[string]func(capacity int) (IAlgorithm, error){ + "arc": func(capacity int) (IAlgorithm, error) { + return NewARC(capacity) + }, + "lru": func(capacity int) (IAlgorithm, error) { + return NewLRU(capacity) + }, + "clock": func(capacity int) (IAlgorithm, error) { + return NewClockAlgorithm(capacity) + }, + "lfu": func(capacity int) (IAlgorithm, error) { + return NewLFUAlgorithm(capacity) + }, + "cawolfu": func(capacity int) (IAlgorithm, error) { + return NewCAWOLFU(capacity) + }, + } + // Register the default eviction algorithms. + RegisterEvictionAlgorithms(algorithms) } diff --git a/examples/eviction/eviction.go b/examples/eviction/eviction.go index 1462141..c68c336 100644 --- a/examples/eviction/eviction.go +++ b/examples/eviction/eviction.go @@ -29,7 +29,7 @@ func executeExample(evictionInterval time.Duration) { } config.InMemoryOptions = []backend.Option[backend.InMemory]{ - backend.WithCapacity(10), + backend.WithCapacity[backend.InMemory](10), } // Create a new HyperCache with a capacity of 10 diff --git a/examples/redis/redis.go b/examples/redis/redis.go index 2336fa5..2686926 100644 --- a/examples/redis/redis.go +++ b/examples/redis/redis.go @@ -22,9 +22,14 @@ func main() { panic(err) } - conf := &hypercache.Config[backend.RedisBackend]{ - RedisOptions: []backend.Option[backend.RedisBackend]{ + conf := &hypercache.Config[backend.Redis]{ + RedisOptions: []backend.Option[backend.Redis]{ backend.WithRedisClient(redisStore.Client), + backend.WithCapacity[backend.Redis](20), + }, + HyperCacheOptions: []hypercache.Option[backend.Redis]{ + hypercache.WithEvictionInterval[backend.Redis](time.Second * 5), + hypercache.WithEvictionAlgorithm[backend.Redis]("lru"), }, } @@ -33,24 +38,27 @@ func main() { panic(err) } - for i := 0; i < 400; i++ { + for i := 0; i < 50; i++ { err = hyperCache.Set(fmt.Sprintf("key-%d", i), fmt.Sprintf("value-%d", i), time.Hour) if err != nil { panic(err) } } + fmt.Println("size", hyperCache.Size()) + fmt.Println("capacity", hyperCache.Capacity()) + allItems, err := hyperCache.List( - backend.WithSortBy[backend.RedisBackend](types.SortByKey), - backend.WithSortOrderAsc[backend.RedisBackend](true), - backend.WithFilterFunc[backend.RedisBackend](func(item *models.Item) bool { - return item.Value != "value-210" + backend.WithSortBy[backend.Redis](types.SortByKey), + backend.WithSortOrderAsc[backend.Redis](true), + backend.WithFilterFunc[backend.Redis](func(item *models.Item) bool { + return item.Value != "value-16" }), ) // Check for errors if err != nil { - panic(err) + fmt.Println(err) } // Print the list of items @@ -58,5 +66,30 @@ func main() { fmt.Println(item.Key, item.Value) } - // fmt.Println(value) + fmt.Println("size", hyperCache.Size()) + fmt.Println("capacity", hyperCache.Capacity()) + + time.Sleep(time.Second * 10) + + allItems, err = hyperCache.List( + backend.WithSortBy[backend.Redis](types.SortByKey), + backend.WithSortOrderAsc[backend.Redis](true), + backend.WithFilterFunc[backend.Redis](func(item *models.Item) bool { + return item.Value != "value-16" + }), + ) + // Check for errors + if err != nil { + fmt.Println(err) + } + + // Print the list of items + for _, item := range allItems { + fmt.Println(item.Key, item.Value) + } + + value, ok := hyperCache.Get("key-9") + if ok { + fmt.Println(value) + } } diff --git a/examples/stats/stats.go b/examples/stats/stats.go index 3e8d170..51a647d 100644 --- a/examples/stats/stats.go +++ b/examples/stats/stats.go @@ -20,7 +20,7 @@ func main() { } config.InMemoryOptions = []backend.Option[backend.InMemory]{ - backend.WithCapacity(100), + backend.WithCapacity[backend.InMemory](100), } // Create a new HyperCache with a capacity of 10 diff --git a/hypercache.go b/hypercache.go index 2fc083e..11ac4f6 100644 --- a/hypercache.go +++ b/hypercache.go @@ -8,6 +8,7 @@ package hypercache // It can implement a service interface to interact with the cache with middleware support (default or custom). import ( + "fmt" "sync" "time" @@ -70,7 +71,7 @@ func NewInMemoryWithDefaults(capacity int) (hyperCache *HyperCache[backend.InMem // Set the in-memory backend options config.InMemoryOptions = []backend.Option[backend.InMemory]{ - backend.WithCapacity(capacity), + backend.WithCapacity[backend.InMemory](capacity), } // Initialize the cache hyperCache, err = New(config) @@ -100,7 +101,7 @@ func New[T backend.IBackendConstrain](config *Config[T]) (hyperCache *HyperCache switch t { case "backend.InMemory": hyperCache.backend, err = backend.NewInMemory(config.InMemoryOptions...) - case "backend.RedisBackend": + case "backend.Redis": hyperCache.backend, err = backend.NewRedisBackend(config.RedisOptions...) default: err = errors.ErrInvalidBackendType @@ -219,10 +220,10 @@ func (hyperCache *HyperCache[T]) expirationLoop() { }), ) - } else if cb, ok := hyperCache.backend.(*backend.RedisBackend); ok { + } else if cb, ok := hyperCache.backend.(*backend.Redis); ok { items, err = cb.List( - backend.WithSortBy[backend.RedisBackend](types.SortByExpiration), - backend.WithFilterFunc[backend.RedisBackend](func(item *models.Item) bool { + backend.WithSortBy[backend.Redis](types.SortByExpiration), + backend.WithFilterFunc[backend.Redis](func(item *models.Item) bool { return item.Expiration > 0 && time.Since(item.LastAccess) > item.Expiration }), ) @@ -280,10 +281,19 @@ func (hyperCache *HyperCache[T]) evictionLoop() { func (hyperCache *HyperCache[T]) evictItem() (string, bool) { key, ok := hyperCache.evictionAlgorithm.Evict() if !ok { + fmt.Println("failed evicting item: ", key) + return "", false } - hyperCache.backend.Remove(key) + fmt.Println("evicting item: ", key) + + err := hyperCache.backend.Remove(key) + if err != nil { + fmt.Println("failed evicting item: ", key, err) + + return "", false + } return key, true } @@ -330,6 +340,7 @@ func (hyperCache *HyperCache[T]) Set(key string, value any, expiration time.Dura return nil } +// SetMultiple adds multiple items to the cache with the given key-value pairs. If an item with the same key already exists, it updates the value of the existing item. func (hyperCache *HyperCache[T]) SetMultiple(items map[string]any, expiration time.Duration) error { // Create a new cache item and set its properties cacheItems := make([]*models.Item, 0, len(items)) @@ -370,6 +381,7 @@ func (hyperCache *HyperCache[T]) SetMultiple(items map[string]any, expiration ti func (hyperCache *HyperCache[T]) Get(key string) (value any, ok bool) { item, ok := hyperCache.backend.Get(key) if !ok { + fmt.Println("not found") return nil, false } @@ -487,7 +499,7 @@ func (hyperCache *HyperCache[T]) List(filters ...any) ([]*models.Item, error) { if hyperCache.cacheBackendChecker.IsRedis() { // if the backend is a Redis, we set the listFunc to the ListRedis function - listInstance = listRedis(hyperCache.backend.(*backend.RedisBackend)) + listInstance = listRedis(hyperCache.backend.(*backend.Redis)) } // calling the corresponding implementation of the list function @@ -512,12 +524,12 @@ func listInMemory(cacheBackend *backend.InMemory) listFunc { } } -func listRedis(cacheBackend *backend.RedisBackend) listFunc { +func listRedis(cacheBackend *backend.Redis) listFunc { return func(options ...any) ([]*models.Item, error) { // here we are converting the filters of any type to the specific FilterOption type for the Redis - filterOptions := make([]backend.FilterOption[backend.RedisBackend], len(options)) + filterOptions := make([]backend.FilterOption[backend.Redis], len(options)) for i, option := range options { - filterOptions[i] = option.(backend.FilterOption[backend.RedisBackend]) + filterOptions[i] = option.(backend.FilterOption[backend.Redis]) } return cacheBackend.List(filterOptions...) } @@ -542,7 +554,7 @@ func (hyperCache *HyperCache[T]) Clear() error { if cb, ok := hyperCache.backend.(*backend.InMemory); ok { items, err = cb.List() cb.Clear() - } else if cb, ok := hyperCache.backend.(*backend.RedisBackend); ok { + } else if cb, ok := hyperCache.backend.(*backend.Redis); ok { items, err = cb.List() if err != nil { return err diff --git a/hypercache_test.go b/hypercache_test.go index 98343c2..be5eeb1 100644 --- a/hypercache_test.go +++ b/hypercache_test.go @@ -52,7 +52,7 @@ func TestHyperCache_WithExpirationInterval(t *testing.T) { WithExpirationInterval[backend.InMemory](1 * time.Hour), }, InMemoryOptions: []backend.Option[backend.InMemory]{ - backend.WithCapacity(10), + backend.WithCapacity[backend.InMemory](10), }, } // Test with custom expiration interval @@ -73,7 +73,7 @@ func TestHyperCache_WithEvictionInterval(t *testing.T) { WithEvictionInterval[backend.InMemory](1 * time.Hour), }, InMemoryOptions: []backend.Option[backend.InMemory]{ - backend.WithCapacity(10), + backend.WithCapacity[backend.InMemory](10), }, } // Test with custom eviction interval @@ -95,7 +95,7 @@ func TestHyperCache_WithMaxEvictionCount(t *testing.T) { WithMaxEvictionCount[backend.InMemory](5), }, InMemoryOptions: []backend.Option[backend.InMemory]{ - backend.WithCapacity(10), + backend.WithCapacity[backend.InMemory](10), }, } cache, err = New(config) diff --git a/tests/benchmark/hypercache_get_benchmark_test.go b/tests/benchmark/hypercache_get_benchmark_test.go index e72b7e7..0d03cc0 100644 --- a/tests/benchmark/hypercache_get_benchmark_test.go +++ b/tests/benchmark/hypercache_get_benchmark_test.go @@ -32,7 +32,7 @@ func BenchmarkHyperCache_Get_ProactiveEviction(b *testing.B) { } config.InMemoryOptions = []backend.Option[backend.InMemory]{ - backend.WithCapacity(1000), + backend.WithCapacity[backend.InMemory](1000), } // Create a new HyperCache with a capacity of 10 diff --git a/tests/benchmark/hypercache_list_benchmark_test.go b/tests/benchmark/hypercache_list_benchmark_test.go index a1d1b63..5ce9ce3 100644 --- a/tests/benchmark/hypercache_list_benchmark_test.go +++ b/tests/benchmark/hypercache_list_benchmark_test.go @@ -8,8 +8,8 @@ import ( ) func BenchmarkHyperCache_List(b *testing.B) { - // Create a new HyperCache with a capacity of 1000 - cache, _ := hypercache.NewInMemoryWithDefaults(1000) + // Create a new HyperCache with a capacity of 100000 + cache, _ := hypercache.NewInMemoryWithDefaults(100000) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/tests/benchmark/hypercache_set_benchmark_test.go b/tests/benchmark/hypercache_set_benchmark_test.go index e6c590a..381abe1 100644 --- a/tests/benchmark/hypercache_set_benchmark_test.go +++ b/tests/benchmark/hypercache_set_benchmark_test.go @@ -10,8 +10,8 @@ import ( ) func BenchmarkHyperCache_Set(b *testing.B) { - // Create a new HyperCache with a capacity of 1000 - cache, _ := hypercache.NewInMemoryWithDefaults(1000) + // Create a new HyperCache with a capacity of 100000 + cache, _ := hypercache.NewInMemoryWithDefaults(100000) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -21,7 +21,7 @@ func BenchmarkHyperCache_Set(b *testing.B) { } func BenchmarkHyperCache_Set_Proactive_Eviction(b *testing.B) { - // Create a new HyperCache with a capacity of 1000 + // Create a new HyperCache with a capacity of 989697 config := hypercache.NewConfig[backend.InMemory]() config.HyperCacheOptions = []hypercache.Option[backend.InMemory]{ hypercache.WithEvictionInterval[backend.InMemory](0), @@ -29,7 +29,7 @@ func BenchmarkHyperCache_Set_Proactive_Eviction(b *testing.B) { } config.InMemoryOptions = []backend.Option[backend.InMemory]{ - backend.WithCapacity(1000), + backend.WithCapacity[backend.InMemory](100000), } // Create a new HyperCache with a capacity of 10 diff --git a/tests/hypercache_get_multiple_test.go b/tests/hypercache_get_multiple_test.go index de5336e..698f069 100644 --- a/tests/hypercache_get_multiple_test.go +++ b/tests/hypercache_get_multiple_test.go @@ -60,7 +60,7 @@ func TestGetMultiple(t *testing.T) { hypercache.WithExpirationInterval[backend.InMemory](time.Millisecond), }, InMemoryOptions: []backend.Option[backend.InMemory]{ - backend.WithCapacity(10), + backend.WithCapacity[backend.InMemory](10), }, } cache, err := hypercache.New(config) diff --git a/utils/types.go b/utils/types.go index 22988b2..770598c 100644 --- a/utils/types.go +++ b/utils/types.go @@ -32,13 +32,13 @@ func (c *CacheBackendChecker[T]) IsInMemory() bool { return ok } -// IsRedisBackend returns true if the backend is a RedisBackend +// IsRedisBackend returns true if the backend is a Redis func (c *CacheBackendChecker[T]) IsRedis() bool { - _, ok := c.Backend.(*backend.RedisBackend) + _, ok := c.Backend.(*backend.Redis) return ok } -// func (c *CacheBackendChecker[T]) IsRedisBackend() (backend.RedisBackend, bool) { -// obj, ok := c.backend.(*backend.RedisBackend) +// func (c *CacheBackendChecker[T]) IsRedisBackend() (backend.Redis, bool) { +// obj, ok := c.backend.(*backend.Redis) // return *obj, ok // }