Skip to content

Commit bab2620

Browse files
authored
add optional logging, more test cases to cover corner cases (#51)
* add optional logging, more test cases to cover corner cases * fix tests
1 parent 8b9a55b commit bab2620

File tree

6 files changed

+192
-8
lines changed

6 files changed

+192
-8
lines changed

pkg/zcache/combined_cache.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/allegro/bigcache/v3"
77
"github.com/go-redis/redis/v8"
88
"github.com/zondax/golem/pkg/metrics"
9+
"go.uber.org/zap"
910
"time"
1011
)
1112

@@ -16,31 +17,55 @@ type CombinedCache interface {
1617
type combinedCache struct {
1718
localCache LocalCache
1819
remoteCache RemoteCache
20+
logger *zap.Logger
1921
ttl time.Duration
2022
isRemoteBestEffort bool
2123
metricsServer *metrics.TaskMetrics
2224
appName string
2325
}
2426

2527
func (c *combinedCache) Set(ctx context.Context, key string, value interface{}, _ time.Duration) error {
26-
if err := c.remoteCache.Set(ctx, key, value, c.ttl); err != nil && !c.isRemoteBestEffort {
27-
return err
28+
c.logger.Sugar().Debugf("set key on combined cache, key: [%s]", key)
29+
30+
if err := c.remoteCache.Set(ctx, key, value, c.ttl); err != nil {
31+
c.logger.Sugar().Errorf("error setting key on combined/remote cache, key: [%s], err: %s", key, err)
32+
if !c.isRemoteBestEffort {
33+
c.logger.Sugar().Debugf("emitting error as remote best effort is false, key: [%s]", key)
34+
return err
35+
}
2836
}
2937

3038
// ttl is controlled by cache instantiation, so it does not matter here
3139
if err := c.localCache.Set(ctx, key, value, c.ttl); err != nil {
40+
c.logger.Sugar().Errorf("error setting key on combined/local cache, key: [%s], err: %s", key, err)
3241
return err
3342
}
3443
return nil
3544
}
3645

3746
func (c *combinedCache) Get(ctx context.Context, key string, data interface{}) error {
47+
c.logger.Sugar().Debugf("get key on combined cache, key: [%s]", key)
48+
3849
err := c.localCache.Get(ctx, key, data)
3950
if err != nil {
51+
if c.localCache.IsNotFoundError(err) {
52+
c.logger.Sugar().Debugf("key not found on combined/local cache, key: [%s]", key)
53+
} else {
54+
c.logger.Sugar().Debugf("error getting key on combined/local cache, key: [%s], err: %s", key, err)
55+
}
56+
4057
if err := c.remoteCache.Get(ctx, key, data); err != nil {
58+
if c.remoteCache.IsNotFoundError(err) {
59+
c.logger.Sugar().Debugf("key not found on combined/remote cache, key: [%s]", key)
60+
} else {
61+
c.logger.Sugar().Debugf("error getting key on combined/remote cache, key: [%s], err: %s", key, err)
62+
}
63+
4164
return err
4265
}
4366

67+
c.logger.Sugar().Debugf("set value found on remote cache in the local cache, key: [%s]", key)
68+
4469
// Refresh data TTL on both caches
4570
_ = c.localCache.Set(ctx, key, data, c.ttl)
4671
_ = c.remoteCache.Set(ctx, key, data, c.ttl)
@@ -50,12 +75,18 @@ func (c *combinedCache) Get(ctx context.Context, key string, data interface{}) e
5075
}
5176

5277
func (c *combinedCache) Delete(ctx context.Context, key string) error {
78+
c.logger.Sugar().Debugf("delete key on combined cache, key: [%s]", key)
5379
err2 := c.remoteCache.Delete(ctx, key)
54-
if err2 != nil && !c.isRemoteBestEffort {
55-
return err2
80+
if err2 != nil {
81+
c.logger.Sugar().Errorf("error deleting key on combined/remote cache, key: [%s], err: %s", key, err2)
82+
if !c.isRemoteBestEffort {
83+
c.logger.Sugar().Debugf("emitting error as remote best effort is false, key: [%s]")
84+
return err2
85+
}
5686
}
5787

5888
if err1 := c.localCache.Delete(ctx, key); err1 != nil {
89+
c.logger.Sugar().Errorf("error deleting key on combined/local cache, key: [%s], err: %s", key, err1)
5990
return err1
6091
}
6192

@@ -73,6 +104,10 @@ func (c *combinedCache) GetStats() ZCacheStats {
73104
}
74105
}
75106

107+
func (c *combinedCache) IsNotFoundError(err error) bool {
108+
return c.remoteCache.IsNotFoundError(err) || c.localCache.IsNotFoundError(err)
109+
}
110+
76111
func (c *combinedCache) SetupAndMonitorMetrics(appName string, metricsServer metrics.TaskMetrics, updateInterval time.Duration) []error {
77112
c.metricsServer = &metricsServer
78113
c.appName = appName

pkg/zcache/combined_cache_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package zcache
33
import (
44
"context"
55
"github.com/stretchr/testify/suite"
6+
"go.uber.org/zap"
67
"os"
78
"testing"
89
"time"
@@ -20,13 +21,17 @@ type CombinedCacheTestSuite struct {
2021
cacheRemoteBrokenBestEffort CombinedCache
2122
cacheRemoteBrokenNotBestEffort CombinedCache
2223
cacheOkNotBestEffort CombinedCache
24+
cacheRemote RemoteCache
2325
}
2426

2527
func (suite *CombinedCacheTestSuite) SetupSuite() {
2628
mr, err := miniredis.Run()
2729
suite.Require().NoError(err)
2830
suite.mr = mr
2931

32+
logger, err := zap.NewDevelopment()
33+
suite.Require().NoError(err)
34+
3035
prefix := os.Getenv("PREFIX")
3136
suite.cacheRemoteBrokenBestEffort, err = NewCombinedCache(
3237
&CombinedConfig{
@@ -38,6 +43,7 @@ func (suite *CombinedCacheTestSuite) SetupSuite() {
3843
},
3944
IsRemoteBestEffort: true,
4045
GlobalPrefix: prefix,
46+
GlobalLogger: logger,
4147
})
4248
suite.Nil(err)
4349

@@ -50,6 +56,7 @@ func (suite *CombinedCacheTestSuite) SetupSuite() {
5056
},
5157
IsRemoteBestEffort: false,
5258
GlobalPrefix: prefix,
59+
GlobalLogger: logger,
5360
})
5461
suite.Nil(err)
5562

@@ -63,8 +70,16 @@ func (suite *CombinedCacheTestSuite) SetupSuite() {
6370
},
6471
IsRemoteBestEffort: false,
6572
GlobalPrefix: prefix,
73+
GlobalLogger: logger,
6674
})
6775
suite.Nil(err)
76+
77+
suite.cacheRemote, err = NewRemoteCache(&RemoteConfig{
78+
Addr: mr.Addr(),
79+
Logger: logger,
80+
Prefix: prefix,
81+
})
82+
suite.Nil(err)
6883
}
6984

7085
func (suite *CombinedCacheTestSuite) TearDownSuite() {
@@ -99,6 +114,37 @@ func (suite *CombinedCacheTestSuite) TestSetAndGet() {
99114
suite.Equal("", result3)
100115
}
101116

117+
func (suite *CombinedCacheTestSuite) TestGetFromRemoteToLocal() {
118+
ctx := context.Background()
119+
120+
// write value remotely directly
121+
err := suite.cacheRemote.Set(ctx, "onlyOnRemote", "value_on_remote", -1)
122+
suite.NoError(err)
123+
124+
// check value on combined cache, it should not find it locally or remotely (it should fail)
125+
var result1 string
126+
err = suite.cacheOkNotBestEffort.Get(ctx, "noFound", &result1)
127+
suite.Error(err)
128+
suite.Equal(suite.cacheOkNotBestEffort.IsNotFoundError(err), true)
129+
130+
// check value on combined cache, it should not find it locally, retrieve it remotely and write it back locally and remotely
131+
err = suite.cacheOkNotBestEffort.Get(ctx, "onlyOnRemote", &result1)
132+
suite.NoError(err)
133+
suite.Equal("value_on_remote", result1)
134+
135+
// check value again on combined cache, it should find it now locally
136+
var result2 string
137+
err = suite.cacheOkNotBestEffort.Get(ctx, "onlyOnRemote", &result2)
138+
suite.NoError(err)
139+
suite.Equal("value_on_remote", result2)
140+
141+
// check value directly on remote cache
142+
var result3 string
143+
err = suite.cacheRemote.Get(ctx, "onlyOnRemote", &result3)
144+
suite.NoError(err)
145+
suite.Equal("value_on_remote", result3)
146+
}
147+
102148
func (suite *CombinedCacheTestSuite) TestDelete() {
103149
ctx := context.Background()
104150

pkg/zcache/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package zcache
33
import (
44
"github.com/allegro/bigcache/v3"
55
"github.com/go-redis/redis/v8"
6+
"go.uber.org/zap"
67
"math"
78
"time"
89
)
@@ -22,11 +23,13 @@ type RemoteConfig struct {
2223
IdleTimeout time.Duration
2324
IdleCheckFrequency time.Duration
2425
Prefix string
26+
Logger *zap.Logger
2527
}
2628

2729
type LocalConfig struct {
2830
EvictionInSeconds int
2931
Prefix string
32+
Logger *zap.Logger
3033
}
3134

3235
func (c *RemoteConfig) ToRedisConfig() *redis.Options {
@@ -59,6 +62,7 @@ func (c *LocalConfig) ToBigCacheConfig() bigcache.Config {
5962
type CombinedConfig struct {
6063
Local *LocalConfig
6164
Remote *RemoteConfig
65+
GlobalLogger *zap.Logger
6266
GlobalTtlSeconds int
6367
GlobalPrefix string
6468
IsRemoteBestEffort bool

pkg/zcache/local_cache.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package zcache
33
import (
44
"context"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"github.com/allegro/bigcache/v3"
89
"github.com/zondax/golem/pkg/metrics"
10+
"go.uber.org/zap"
911
"time"
1012
)
1113

@@ -16,40 +18,64 @@ type LocalCache interface {
1618
type localCache struct {
1719
client *bigcache.BigCache
1820
prefix string
21+
logger *zap.Logger
1922
metricsServer *metrics.TaskMetrics
2023
appName string
2124
}
2225

2326
func (c *localCache) Set(_ context.Context, key string, value interface{}, _ time.Duration) error {
2427
realKey := getKeyWithPrefix(c.prefix, key)
2528

29+
c.logger.Sugar().Debugf("set key on local cache, fullKey: [%s], value: [%v]", realKey, value)
2630
val, err := json.Marshal(value)
2731
if err != nil {
2832
return err
2933
}
30-
return c.client.Set(realKey, val)
34+
35+
err = c.client.Set(realKey, val)
36+
if err != nil {
37+
c.logger.Sugar().Errorf("error setting new key on local cache, fullKey: [%s], err: [%s]", realKey, err)
38+
}
39+
40+
return err
3141
}
3242

3343
func (c *localCache) Get(_ context.Context, key string, data interface{}) error {
3444
realKey := getKeyWithPrefix(c.prefix, key)
3545

46+
c.logger.Sugar().Debugf("get key on local cache, fullKey: [%s]", realKey)
47+
3648
val, err := c.client.Get(realKey)
3749
if err != nil {
50+
if c.IsNotFoundError(err) {
51+
c.logger.Sugar().Debugf("key not found on local cache, fullKey: [%s]", realKey)
52+
} else {
53+
c.logger.Sugar().Errorf("error getting key on local cache, fullKey: [%s], err: [%s]", realKey, err)
54+
}
55+
3856
return err
3957
}
4058
return json.Unmarshal(val, &data)
4159
}
4260

4361
func (c *localCache) Delete(_ context.Context, key string) error {
4462
realKey := getKeyWithPrefix(c.prefix, key)
63+
c.logger.Sugar().Debugf("delete key on local cache, fullKey: [%s]", realKey)
64+
4565
return c.client.Delete(realKey)
4666
}
4767

4868
func (c *localCache) GetStats() ZCacheStats {
4969
stats := c.client.Stats()
70+
c.logger.Sugar().Debugf("local cache stats: [%v]", stats)
71+
5072
return ZCacheStats{Local: &stats}
5173
}
5274

75+
func (c *localCache) IsNotFoundError(err error) bool {
76+
return errors.Is(err, bigcache.ErrEntryNotFound)
77+
}
78+
5379
func (c *localCache) SetupAndMonitorMetrics(appName string, metricsServer metrics.TaskMetrics, updateInterval time.Duration) []error {
5480
c.metricsServer = &metricsServer
5581
c.appName = appName

0 commit comments

Comments
 (0)