cache/filecache: Use time.Duration for maxAge
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 14 Nov 2018 09:51:41 +0000 (10:51 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 14 Nov 2018 22:14:50 +0000 (23:14 +0100)
Fixes #5438

cache/filecache/filecache.go
cache/filecache/filecache_config.go
cache/filecache/filecache_config_test.go
cache/filecache/filecache_test.go
docs/content/en/getting-started/configuration.md

index c6ea026812f567b5bbfcfd950c0e6070b5b7a251..da0a90d57dfbab55156da22c3c97f9ac7d640279 100644 (file)
@@ -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
                }
index f83e19e0e9b84efff57465201fbd170e714a99ae..9913fd7e2327bf2f6e848b042c24645090abedc7 100644 (file)
@@ -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
                }
 
index 209be823d5526f922997a8f21a7514d2461c3309..22fb1b56bd5c0b47cacf11396f908f5c30d2198b 100644 (file)
@@ -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)
        }
 
 }
index 4f5336be59c49175366c275a9c1854a8872e53f1..b3b8376ed6b2e415b6a106f843589bfee1bc9057 100644 (file)
@@ -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"
 
 `
index de978f5102a53428c1bff9550ed046a3fdb4e007..cb2eed4cde051799f7ae68a337fe6ba9af9f58ad 100644 (file)
@@ -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).