From 1df99514caef9794ed6ae2af74efad5f108b31e2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 19 Apr 2018 11:36:14 -0700 Subject: [PATCH] agent/cache: send the RefreshTimeout into the backend fetch --- agent/cache/cache.go | 7 ++++++- agent/cache/cache_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/agent/cache/cache.go b/agent/cache/cache.go index d58d797291..9296a5fb18 100644 --- a/agent/cache/cache.go +++ b/agent/cache/cache.go @@ -134,6 +134,10 @@ type RegisterOptions struct { // This makes the type available for Get but does not automatically perform // any prefetching. In order to populate the cache, Get must be called. func (c *Cache) RegisterType(n string, typ Type, opts *RegisterOptions) { + if opts == nil { + opts = &RegisterOptions{} + } + c.typesLock.Lock() defer c.typesLock.Unlock() c.types[n] = typeEntry{Type: typ, Opts: opts} @@ -290,6 +294,7 @@ func (c *Cache) fetch(t, key string, r Request) (<-chan struct{}, error) { // Start building the new entry by blocking on the fetch. result, err := tEntry.Type.Fetch(FetchOptions{ MinIndex: entry.Index, + Timeout: tEntry.Opts.RefreshTimeout, }, r) if err == nil { @@ -336,7 +341,7 @@ func (c *Cache) fetch(t, key string, r Request) (<-chan struct{}, error) { // If refresh is enabled, run the refresh in due time. The refresh // below might block, but saves us from spawning another goroutine. - if tEntry.Opts != nil && tEntry.Opts.Refresh { + if tEntry.Opts.Refresh { c.refresh(tEntry.Opts, t, key, r) } }() diff --git a/agent/cache/cache_test.go b/agent/cache/cache_test.go index e5db006e69..49edc6e28d 100644 --- a/agent/cache/cache_test.go +++ b/agent/cache/cache_test.go @@ -336,6 +336,39 @@ func TestCacheGet_periodicRefresh(t *testing.T) { TestCacheGetChResult(t, resultCh, 12) } +// Test that the backend fetch sets the proper timeout. +func TestCacheGet_fetchTimeout(t *testing.T) { + t.Parallel() + + require := require.New(t) + + typ := TestType(t) + defer typ.AssertExpectations(t) + c := TestCache(t) + + // Register the type with a timeout + timeout := 10 * time.Minute + c.RegisterType("t", typ, &RegisterOptions{ + RefreshTimeout: timeout, + }) + + // Configure the type + var actual time.Duration + typ.Static(FetchResult{Value: 42}, nil).Times(1).Run(func(args mock.Arguments) { + opts := args.Get(0).(FetchOptions) + actual = opts.Timeout + }) + + // Get, should fetch + req := TestRequest(t, RequestInfo{Key: "hello"}) + result, err := c.Get("t", req) + require.Nil(err) + require.Equal(42, result) + + // Test the timeout + require.Equal(timeout, actual) +} + // Test that Get partitions the caches based on DC so two equivalent requests // to different datacenters are automatically cached even if their keys are // the same.