Skip to content

Commit

Permalink
feat(ARCO-283): remove freecache, combine methods with cache implemen…
Browse files Browse the repository at this point in the history
…tation (#643)
  • Loading branch information
pawellewandowski98 authored Dec 4, 2024
1 parent ddeca39 commit 568adb2
Show file tree
Hide file tree
Showing 17 changed files with 647 additions and 199 deletions.
6 changes: 2 additions & 4 deletions cmd/arc/services/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/bitcoin-sv/arc/internal/cache"

"github.com/bitcoin-sv/arc/config"
"github.com/coocood/freecache"
"github.com/go-redis/redis/v8"
)

Expand All @@ -15,9 +14,8 @@ var ErrCacheUnknownType = errors.New("unknown cache type")
// NewCacheStore creates a new CacheStore based on the provided configuration.
func NewCacheStore(cacheConfig *config.CacheConfig) (cache.Store, error) {
switch cacheConfig.Engine {
case config.FreeCache:
cacheSize := freecache.NewCache(cacheConfig.Freecache.Size)
return cache.NewFreecacheStore(cacheSize), nil
case config.InMemory:
return cache.NewMemoryStore(), nil
case config.Redis:
c := redis.NewClient(&redis.Options{
Addr: cacheConfig.Redis.Addr,
Expand Down
9 changes: 4 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
)

const (
FreeCache = "freecache"
Redis = "redis"
InMemory = "in-memory"
Redis = "redis"
)

type ArcConfig struct {
Expand Down Expand Up @@ -137,9 +137,8 @@ type PostgresConfig struct {
}

type CacheConfig struct {
Engine string `mapstructure:"engine"`
Freecache *FreeCacheConfig `mapstructure:"freecache"`
Redis *RedisConfig `mapstructure:"redis"`
Engine string `mapstructure:"engine"`
Redis *RedisConfig `mapstructure:"redis"`
}

type FreeCacheConfig struct {
Expand Down
7 changes: 2 additions & 5 deletions config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,8 @@ func getCallbackerConfig() *CallbackerConfig {

func getCacheConfig() *CacheConfig {
return &CacheConfig{
Engine: FreeCache,
Freecache: &FreeCacheConfig{
Size: 10 * 1024 * 1024, // Default size 10MB.
},
Redis: &RedisConfig{
Engine: InMemory, // use in memory cache
Redis: &RedisConfig{ // example of Redis config
Addr: "localhost:6379",
Password: "",
DB: 0,
Expand Down
6 changes: 2 additions & 4 deletions config/example_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@ broadcasting: # settings for connection to nodes
p2p: 18335

cache:
engine: freecache # cache engine - one of freecache | redis
freecache: # freecache configuration
size: 10000000 # size of cache
redis:
engine: redis # cache engine - in-memory/redis
redis: # redis cache configuration in case that engine: redis
addr: "localhost:6379"
password: ""
db: 1
Expand Down
20 changes: 15 additions & 5 deletions internal/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ import (
)

var (
ErrCacheNotFound = errors.New("key not found in cache")
ErrCacheFailedToSet = errors.New("failed to set value in cache")
ErrCacheFailedToDel = errors.New("failed to delete value from cache")
ErrCacheFailedToGet = errors.New("failed to get value from cache")
ErrCacheNotFound = errors.New("key not found in cache")
ErrCacheFailedToSet = errors.New("failed to set value in cache")
ErrCacheFailedToDel = errors.New("failed to delete value from cache")
ErrCacheFailedToGet = errors.New("failed to get value from cache")
ErrCacheFailedToScan = errors.New("failed to scan cache")
ErrCacheFailedToGetCount = errors.New("failed to get count from cache")
ErrCacheFailedToExecuteTx = errors.New("failed to execute transaction")
)

type Store interface {
Get(key string) ([]byte, error)
Set(key string, value []byte, ttl time.Duration) error
Del(key string) error
Del(keys ...string) error

MapGet(hashsetKey string, field string) ([]byte, error)
MapGetAll(hashsetKey string) (map[string][]byte, error)
MapSet(hashsetKey string, field string, value []byte) error
MapDel(hashsetKey string, fields ...string) error
MapLen(hashsetKey string) (int64, error)
MapExtractAll(hashsetKey string) (map[string][]byte, error)
}
50 changes: 0 additions & 50 deletions internal/cache/freecache.go

This file was deleted.

142 changes: 142 additions & 0 deletions internal/cache/in_memory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package cache

import (
"errors"
"sync"
"time"
)

type MemoryStore struct {
data sync.Map
}

func NewMemoryStore() *MemoryStore {
return &MemoryStore{}
}

// Get retrieves a value by key.
func (s *MemoryStore) Get(key string) ([]byte, error) {
value, found := s.data.Load(key)
if !found {
return nil, ErrCacheNotFound
}

bytes, ok := value.([]byte)
if !ok {
return nil, ErrCacheFailedToGet
}

return bytes, nil
}

// Set stores a key-value pair, ignoring the ttl parameter.
func (s *MemoryStore) Set(key string, value []byte, _ time.Duration) error {
s.data.Store(key, value)
return nil
}

// Del removes a key from the store.
func (s *MemoryStore) Del(keys ...string) error {
for _, k := range keys {
s.data.Delete(k)
}
return nil
}

// MapGet retrieves a value by key and hashsetKey. Return err if hashsetKey or key not found.
func (s *MemoryStore) MapGet(hashsetKey string, key string) ([]byte, error) {
hashValue, found := s.data.Load(hashsetKey)
if !found {
return nil, ErrCacheNotFound
}

hashMap, ok := hashValue.(map[string][]byte)
if !ok {
return nil, ErrCacheFailedToGet
}

fieldValue, exists := hashMap[key]
if !exists {
return nil, ErrCacheNotFound
}

return fieldValue, nil
}

// MapSet stores a key-value pair for specific hashsetKey.
func (s *MemoryStore) MapSet(hashsetKey string, key string, value []byte) error {
raw, _ := s.data.LoadOrStore(hashsetKey, make(map[string][]byte))

hashMap, ok := raw.(map[string][]byte)
if !ok {
return ErrCacheFailedToSet
}

hashMap[key] = value

s.data.Store(hashsetKey, hashMap)
return nil
}

// MapDel removes a value by key in specific hashsetKey.
func (s *MemoryStore) MapDel(hashsetKey string, keys ...string) error {
hashValue, found := s.data.Load(hashsetKey)
if !found {
return ErrCacheNotFound
}

hashMap, ok := hashValue.(map[string][]byte)
if !ok {
return errors.Join(ErrCacheFailedToDel, ErrCacheFailedToGet)
}

for _, k := range keys {
delete(hashMap, k)
}

s.data.Store(hashsetKey, hashMap)
return nil
}

// MapGetAll retrieves all key-value pairs for a specific hashsetKey. Return err if hashsetKey not found.
func (s *MemoryStore) MapGetAll(hashsetKey string) (map[string][]byte, error) {
hashValue, found := s.data.Load(hashsetKey)
if !found {
return nil, ErrCacheNotFound
}

hashMap, ok := hashValue.(map[string][]byte)
if !ok {
return nil, ErrCacheFailedToGet
}

return hashMap, nil
}

// MapExtractAll retrieves all key-value pairs for a specific hashsetKey and deletes the hashsetKey. Return err if hashsetKey not found.
func (s *MemoryStore) MapExtractAll(hashsetKey string) (map[string][]byte, error) {
hashValue, found := s.data.LoadAndDelete(hashsetKey)
if !found {
return nil, ErrCacheNotFound
}

hashMap, ok := hashValue.(map[string][]byte)
if !ok {
return nil, ErrCacheFailedToGet
}

return hashMap, nil
}

// MapLen returns the number of elements in a hashsetKey in memory.
func (s *MemoryStore) MapLen(hashsetKey string) (int64, error) {
hashMap, err := s.MapGetAll(hashsetKey)
if err != nil {
if errors.Is(err, ErrCacheNotFound) {
return 0, nil
}
return 0, err
}

return int64(len(hashMap)), nil
}
Loading

0 comments on commit 568adb2

Please sign in to comment.