-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
278 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// Package cached provides a cached provider for xload. | ||
// This loader can be used to cache the results of any loader. | ||
// | ||
// Useful for loaders that have a high latency, or loaders that are | ||
// called frequently. | ||
package cached |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package cached_test | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/gojekfarm/xtools/xload" | ||
"github.com/gojekfarm/xtools/xload/providers/cached" | ||
) | ||
|
||
func Example() { | ||
// This example shows how to use the cached loader | ||
// with a remote loader. | ||
|
||
ctx := context.Background() | ||
cfg := struct { | ||
Title string `env:"TITLE"` | ||
Link string `env:"LINK"` | ||
ButtonLabel string `env:"BUTTON_LABEL"` | ||
}{} | ||
|
||
remoteLoader := xload.LoaderFunc(func(ctx context.Context, key string) (string, error) { | ||
// Load the value from a remote source. | ||
|
||
return "", nil | ||
}) | ||
|
||
err := xload.Load( | ||
ctx, &cfg, | ||
cached.NewLoader( | ||
remoteLoader, | ||
cached.TTL(5*60*time.Minute), | ||
), | ||
) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
type CustomCache struct{} | ||
|
||
func NewCustomCache() *CustomCache { | ||
return &CustomCache{} | ||
} | ||
|
||
func (c *CustomCache) Get(key string) (string, error) { | ||
return "", nil | ||
} | ||
|
||
func (c *CustomCache) Set(key, value string, ttl time.Duration) error { | ||
return nil | ||
} | ||
|
||
func Example_customCache() { | ||
// This example shows how to use a custom cache | ||
// with the cached loader. | ||
|
||
ctx := context.Background() | ||
cfg := struct { | ||
Title string `env:"TITLE"` | ||
Link string `env:"LINK"` | ||
ButtonLabel string `env:"BUTTON_LABEL"` | ||
}{} | ||
|
||
remoteLoader := xload.LoaderFunc(func(ctx context.Context, key string) (string, error) { | ||
// Load the value from a remote source. | ||
|
||
return "", nil | ||
}) | ||
|
||
err := xload.Load( | ||
ctx, &cfg, | ||
cached.NewLoader( | ||
remoteLoader, | ||
cached.TTL(5*60*time.Minute), | ||
cached.Cache(NewCustomCache()), | ||
), | ||
) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,119 @@ | ||
package cached | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
|
||
"github.com/gojekfarm/xtools/xload" | ||
) | ||
|
||
type config struct { | ||
Key1 string `env:"KEY_1"` | ||
Key2 string `env:"KEY_2"` | ||
Key3 string `env:"KEY_3"` | ||
} | ||
|
||
func TestNewLoader(t *testing.T) { | ||
loader := xload.MapLoader(map[string]string{ | ||
"KEY_1": "value-1", | ||
"KEY_2": "value-2", | ||
}) | ||
|
||
cachedLoader := NewLoader(loader) | ||
|
||
t.Run("Cache MISS", func(t *testing.T) { | ||
cfg := config{} | ||
|
||
err := xload.Load(context.TODO(), &cfg, cachedLoader) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "value-1", cfg.Key1) | ||
assert.Equal(t, "value-2", cfg.Key2) | ||
}) | ||
|
||
t.Run("Cache HIT", func(t *testing.T) { | ||
cfg := config{} | ||
|
||
err := xload.Load(context.TODO(), &cfg, cachedLoader) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "value-1", cfg.Key1) | ||
assert.Equal(t, "value-2", cfg.Key2) | ||
}) | ||
} | ||
|
||
func TestNewLoader_WithTTL(t *testing.T) { | ||
loader := xload.MapLoader(map[string]string{ | ||
"KEY_1": "value-1", | ||
"KEY_2": "value-2", | ||
}) | ||
|
||
ttl := 123 * time.Second | ||
|
||
mc := NewMockCache(t) | ||
mc.On("Get", mock.Anything).Return("", nil).Times(3) | ||
mc.On("Set", mock.Anything, mock.Anything, ttl).Return(nil).Times(3) | ||
|
||
cachedLoader := NewLoader(loader, TTL(ttl), Cache(mc)) | ||
|
||
cfg := config{} | ||
|
||
err := xload.Load(context.Background(), &cfg, cachedLoader) | ||
assert.NoError(t, err) | ||
|
||
mc.AssertExpectations(t) | ||
} | ||
|
||
func TestNewLoader_ForwardError(t *testing.T) { | ||
failingLoader := xload.LoaderFunc(func(ctx context.Context, key string) (string, error) { | ||
return "", assert.AnError | ||
}) | ||
|
||
cachedLoader := NewLoader(failingLoader) | ||
|
||
cfg := config{} | ||
|
||
err := xload.Load(context.Background(), &cfg, cachedLoader) | ||
assert.Error(t, err) | ||
assert.Equal(t, assert.AnError, err) | ||
} | ||
|
||
func TestNewLoader_CacheError(t *testing.T) { | ||
loader := xload.MapLoader(map[string]string{ | ||
"KEY_1": "value-1", | ||
"KEY_2": "value-2", | ||
}) | ||
|
||
cfg := config{} | ||
|
||
t.Run("Cache SET error", func(t *testing.T) { | ||
mc := NewMockCache(t) | ||
|
||
mc.On("Get", "KEY_1").Return("", nil) | ||
mc.On("Set", "KEY_1", "value-1", mock.Anything).Return(assert.AnError) | ||
|
||
cachedLoader := NewLoader(loader, Cache(mc)) | ||
|
||
err := xload.Load(context.Background(), &cfg, cachedLoader) | ||
assert.Error(t, err) | ||
assert.Equal(t, assert.AnError, err) | ||
|
||
mc.AssertExpectations(t) | ||
}) | ||
|
||
t.Run("Cache GET error", func(t *testing.T) { | ||
mc := NewMockCache(t) | ||
|
||
mc.On("Get", "KEY_1").Return("", assert.AnError) | ||
|
||
cachedLoader := NewLoader(loader, Cache(mc)) | ||
|
||
err := xload.Load(context.Background(), &cfg, cachedLoader) | ||
assert.Error(t, err) | ||
assert.Equal(t, assert.AnError, err) | ||
|
||
mc.AssertExpectations(t) | ||
}) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.