Port over cache refresh changes (#7599)

This commit is contained in:
Brian Kassouf 2019-10-08 13:23:43 -07:00 committed by GitHub
parent f9199ceede
commit f43f84a354
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 15 deletions

View File

@ -13,6 +13,10 @@ import (
const (
// DefaultCacheSize is used if no cache size is specified for NewCache
DefaultCacheSize = 128 * 1024
// refreshCacheCtxKey is a ctx value that denotes the cache should be
// refreshed during a Get call.
refreshCacheCtxKey = "refresh_cache"
)
// These paths don't need to be cached by the LRU cache. This should
@ -26,6 +30,22 @@ var cacheExceptionsPaths = []string{
"core/raft/tls",
}
// CacheRefreshContext returns a context with an added value denoting if the
// cache should attempt a refresh.
func CacheRefreshContext(ctx context.Context, r bool) context.Context {
return context.WithValue(ctx, refreshCacheCtxKey, r)
}
// cacheRefreshFromContext is a helper to look up if the provided context is
// requesting a cache refresh.
func cacheRefreshFromContext(ctx context.Context) bool {
r, ok := ctx.Value(refreshCacheCtxKey).(bool)
if !ok {
return false
}
return r
}
// Cache is used to wrap an underlying physical backend
// and provide an LRU cache layer on top. Most of the reads done by
// Vault are for policy objects so there is a large read reduction
@ -140,11 +160,13 @@ func (c *Cache) Get(ctx context.Context, key string) (*Entry, error) {
defer lock.RUnlock()
// Check the LRU first
if raw, ok := c.lru.Get(key); ok {
if raw == nil {
return nil, nil
if !cacheRefreshFromContext(ctx) {
if raw, ok := c.lru.Get(key); ok {
if raw == nil {
return nil, nil
}
return raw.(*Entry), nil
}
return raw.(*Entry), nil
}
// Read from the underlying backend

View File

@ -17,6 +17,7 @@ func TestCache(t *testing.T) {
t.Fatal(err)
}
cache := physical.NewCache(inm, 0, logger)
cache.SetEnabled(true)
physical.ExerciseBackend(t, cache)
physical.ExerciseBackend_ListPrefix(t, cache)
}
@ -267,3 +268,62 @@ func TestCache_Disable(t *testing.T) {
cache.SetEnabled(false)
disabledTests()
}
func TestCache_Refresh(t *testing.T) {
logger := logging.NewVaultLogger(log.Debug)
inm, err := NewInmem(nil, logger)
if err != nil {
t.Fatal(err)
}
cache := physical.NewCache(inm, 0, logger)
cache.SetEnabled(true)
ent := &physical.Entry{
Key: "foo",
Value: []byte("bar"),
}
err = cache.Put(context.Background(), ent)
if err != nil {
t.Fatalf("err: %v", err)
}
ent2 := &physical.Entry{
Key: "foo",
Value: []byte("baz"),
}
// Update below cache
err = inm.Put(context.Background(), ent2)
if err != nil {
t.Fatalf("err: %v", err)
}
r, err := cache.Get(context.Background(), "foo")
if err != nil {
t.Fatalf("err: %v", err)
}
if string(r.Value) != "bar" {
t.Fatalf("expected value bar, got %s", string(r.Value))
}
// Refresh the cache
r, err = cache.Get(physical.CacheRefreshContext(context.Background(), true), "foo")
if err != nil {
t.Fatalf("err: %v", err)
}
if string(r.Value) != "baz" {
t.Fatalf("expected value baz, got %s", string(r.Value))
}
// Make sure new value is in cache
r, err = cache.Get(context.Background(), "foo")
if err != nil {
t.Fatalf("err: %v", err)
}
if string(r.Value) != "baz" {
t.Fatalf("expected value baz, got %s", string(r.Value))
}
}

View File

@ -13,7 +13,6 @@ require (
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/vault/sdk v0.1.14-0.20190919081434-645ac174deeb
github.com/mitchellh/mapstructure v1.1.2
github.com/shirou/gopsutil v0.0.0-20190731134726-d80c43f9c984 // indirect
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
gopkg.in/square/go-jose.v2 v2.3.1

View File

@ -1,6 +1,5 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@ -11,7 +10,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -69,9 +67,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/shirou/gopsutil v0.0.0-20190731134726-d80c43f9c984 h1:wsZAb4P8F7uQSwsnxE1gk9AHCcc5U0wvyDzcLwFY0Eo=
github.com/shirou/gopsutil v0.0.0-20190731134726-d80c43f9c984/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
@ -97,7 +92,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=

View File

@ -13,6 +13,10 @@ import (
const (
// DefaultCacheSize is used if no cache size is specified for NewCache
DefaultCacheSize = 128 * 1024
// refreshCacheCtxKey is a ctx value that denotes the cache should be
// refreshed during a Get call.
refreshCacheCtxKey = "refresh_cache"
)
// These paths don't need to be cached by the LRU cache. This should
@ -26,6 +30,22 @@ var cacheExceptionsPaths = []string{
"core/raft/tls",
}
// CacheRefreshContext returns a context with an added value denoting if the
// cache should attempt a refresh.
func CacheRefreshContext(ctx context.Context, r bool) context.Context {
return context.WithValue(ctx, refreshCacheCtxKey, r)
}
// cacheRefreshFromContext is a helper to look up if the provided context is
// requesting a cache refresh.
func cacheRefreshFromContext(ctx context.Context) bool {
r, ok := ctx.Value(refreshCacheCtxKey).(bool)
if !ok {
return false
}
return r
}
// Cache is used to wrap an underlying physical backend
// and provide an LRU cache layer on top. Most of the reads done by
// Vault are for policy objects so there is a large read reduction
@ -140,11 +160,13 @@ func (c *Cache) Get(ctx context.Context, key string) (*Entry, error) {
defer lock.RUnlock()
// Check the LRU first
if raw, ok := c.lru.Get(key); ok {
if raw == nil {
return nil, nil
if !cacheRefreshFromContext(ctx) {
if raw, ok := c.lru.Get(key); ok {
if raw == nil {
return nil, nil
}
return raw.(*Entry), nil
}
return raw.(*Entry), nil
}
// Read from the underlying backend