From d3489eba5dfc0ecdc032016d9db0746213dd5f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 14 Nov 2018 10:51:41 +0100 Subject: [PATCH] cache/filecache: Use time.Duration for maxAge Fixes #5438 --- cache/filecache/filecache.go | 11 +++++------ cache/filecache/filecache_config.go | 18 +++++++++++++++--- cache/filecache/filecache_config_test.go | 11 ++++++----- cache/filecache/filecache_test.go | 6 +++--- .../en/getting-started/configuration.md | 4 ++-- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/cache/filecache/filecache.go b/cache/filecache/filecache.go index c6ea02681..da0a90d57 100644 --- a/cache/filecache/filecache.go +++ b/cache/filecache/filecache.go @@ -36,8 +36,9 @@ import ( type Cache struct { Fs afero.Fs - // Max age in seconds. - maxAge int + // Max age for items in this cache. Negative duration means forever, + // 0 is effectively turning this cache off. + maxAge time.Duration nlocker *locker.Locker } @@ -49,7 +50,7 @@ type ItemInfo struct { } // NewCache creates a new file cache with the given filesystem and max age. -func NewCache(fs afero.Fs, maxAge int) *Cache { +func NewCache(fs afero.Fs, maxAge time.Duration) *Cache { return &Cache{ Fs: fs, nlocker: locker.NewLocker(), @@ -227,9 +228,7 @@ func (c *Cache) getOrRemove(id string) hugio.ReadSeekCloser { return nil } - expiry := time.Now().Add(-time.Duration(c.maxAge) * time.Second) - expired := fi.ModTime().Before(expiry) - if expired { + if time.Now().Sub(fi.ModTime()) > c.maxAge { c.Fs.Remove(id) return nil } diff --git a/cache/filecache/filecache_config.go b/cache/filecache/filecache_config.go index f83e19e0e..9913fd7e2 100644 --- a/cache/filecache/filecache_config.go +++ b/cache/filecache/filecache_config.go @@ -17,6 +17,7 @@ import ( "path" "path/filepath" "strings" + "time" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugolib/paths" @@ -62,8 +63,8 @@ type cachesConfig map[string]cacheConfig type cacheConfig struct { // Max age of cache entries in this cache. Any items older than this will // be removed and not returned from the cache. - // -1 means forever, 0 means cache is disabled. - MaxAge int + // a negative value means forever, 0 means cache is disabled. + MaxAge time.Duration // The directory where files are stored. Dir string @@ -107,7 +108,18 @@ func decodeConfig(p *paths.Paths) (cachesConfig, error) { for k, v := range m { cc := defaultCacheConfig - if err := mapstructure.WeakDecode(v, &cc); err != nil { + dc := &mapstructure.DecoderConfig{ + Result: &cc, + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + WeaklyTypedInput: true, + } + + decoder, err := mapstructure.NewDecoder(dc) + if err != nil { + return c, err + } + + if err := decoder.Decode(v); err != nil { return nil, err } diff --git a/cache/filecache/filecache_config_test.go b/cache/filecache/filecache_config_test.go index 209be823d..22fb1b56b 100644 --- a/cache/filecache/filecache_config_test.go +++ b/cache/filecache/filecache_config_test.go @@ -17,6 +17,7 @@ import ( "path/filepath" "runtime" "testing" + "time" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/hugofs" @@ -34,10 +35,10 @@ func TestDecodeConfig(t *testing.T) { configStr := ` [caches] [caches.getJSON] -maxAge = 1234 +maxAge = "10m" dir = "/path/to/c1" [caches.getCSV] -maxAge = 3456 +maxAge = "11h" dir = "/path/to/c2" [caches.images] dir = "/path/to/c3" @@ -56,11 +57,11 @@ dir = "/path/to/c3" assert.Equal(4, len(decoded)) c2 := decoded["getcsv"] - assert.Equal(3456, c2.MaxAge) + assert.Equal("11h0m0s", c2.MaxAge.String()) assert.Equal(filepath.FromSlash("/path/to/c2"), c2.Dir) c3 := decoded["images"] - assert.Equal(-1, c3.MaxAge) + assert.Equal(time.Duration(-1), c3.MaxAge) assert.Equal(filepath.FromSlash("/path/to/c3"), c3.Dir) } @@ -96,7 +97,7 @@ dir = "/path/to/c3" assert.Equal(4, len(decoded)) for _, v := range decoded { - assert.Equal(0, v.MaxAge) + assert.Equal(time.Duration(0), v.MaxAge) } } diff --git a/cache/filecache/filecache_test.go b/cache/filecache/filecache_test.go index 4f5336be5..b3b8376ed 100644 --- a/cache/filecache/filecache_test.go +++ b/cache/filecache/filecache_test.go @@ -44,7 +44,7 @@ func TestFileCache(t *testing.T) { cacheDir = "CACHEDIR" [caches] [caches.getJSON] -maxAge = 111 +maxAge = "10h" dir = ":cacheDir/c" ` @@ -62,7 +62,7 @@ dir = ":cacheDir/c" c := caches.Get("GetJSON") assert.NotNil(c) - assert.Equal(111, c.maxAge) + assert.Equal("10h0m0s", c.maxAge.String()) bfs, ok := c.Fs.(*afero.BasePathFs) assert.True(ok) @@ -151,7 +151,7 @@ func TestFileCacheConcurrent(t *testing.T) { configStr := ` [caches] [caches.getjson] -maxAge = 1 +maxAge = "1s" dir = "/cache/c" ` diff --git a/docs/content/en/getting-started/configuration.md b/docs/content/en/getting-started/configuration.md index de978f510..cb2eed4cd 100644 --- a/docs/content/en/getting-started/configuration.md +++ b/docs/content/en/getting-started/configuration.md @@ -439,8 +439,8 @@ You can override any of these cache setting in your own `config.toml`. : This is the value of the `resourceDir` config option. maxAge -: This is the time in seconds before a cache entry will be evicted, -1 means forever and 0 effectively turns that particular cache off. - +: This is the duration before a cache entry will be evicted, -1 means forever and 0 effectively turns that particular cache off. Uses Go's `time.Duration`, so valid values are `"10s"` (10 seconds), `"10m"` (10 minutes) and `"10m"` (10 hours). + dir : The absolute path to where the files for this cache will be stored. Allowed starting placeholders are `:cacheDir` and `:resourceDir` (see above).