diff --git a/core/cfg/flags.go b/core/cfg/flags.go index 944e227e..a861a5e3 100644 --- a/core/cfg/flags.go +++ b/core/cfg/flags.go @@ -30,7 +30,7 @@ import ( "github.com/urfave/cli" ) -const GEESEFS_VERSION = "0.43.8-dc.2" +const GEESEFS_VERSION = "0.43.8-dc.3" var flagCategories map[string]string diff --git a/core/dir.go b/core/dir.go index 8df75705..ec541e78 100644 --- a/core/dir.go +++ b/core/dir.go @@ -1876,9 +1876,12 @@ func (parent *Inode) loadSymlinksCache() error { return err } - // If data is nil, the file hasn't changed (304 Not Modified) + // If data is nil, the file hasn't changed (304 Not Modified). The cached copy + // is still current, so re-arm the TTL: without this the guard above never + // passes again and every later miss re-issues the conditional GET. if data == nil { s3Log.Debugf("loadSymlinksCache: file unchanged (304), dir=%v", parent.FullName()) + parent.dir.symlinksCacheTime = time.Now() return nil } diff --git a/core/symlinks_test.go b/core/symlinks_test.go index 725dc578..e9080194 100644 --- a/core/symlinks_test.go +++ b/core/symlinks_test.go @@ -1297,3 +1297,38 @@ func (s *SymlinksTest) TestBatchRemoveOnlySymlink(t *C) { parent.mu.Unlock() } +func (s *SymlinksTest) TestCacheNotModifiedRearmsTTL(t *C) { + mock := newMockConditionalBackend() + _, parent := newTestDirInode(mock, 1*time.Hour) + + // Give the directory a symlinks file so the reload can come back 304. + data := NewSymlinksFileData() + data.AddSymlink("link1", "../target1") + _, err := SaveSymlinksFile(mock, "", ".geesefs_symlinks", data, "") + t.Assert(err, IsNil) + + gets := 0 + mock.onGetBlob = func(param *GetBlobInput) { gets++ } + + parent.mu.Lock() + defer parent.mu.Unlock() + + // First load populates the cache and records the ETag. + err = parent.loadSymlinksCache() + t.Assert(err, IsNil) + t.Assert(gets, Equals, 1) + t.Assert(parent.dir.symlinksCache.HasSymlink("link1"), Equals, true) + + // Expire the cache; the reload sends If-None-Match and gets a 304 back. + parent.dir.symlinksCacheTime = time.Time{} + err = parent.loadSymlinksCache() + t.Assert(err, IsNil) + t.Assert(gets, Equals, 2) + + // The 304 confirmed the cache is current, so the next miss within the TTL + // must be served locally instead of re-issuing the conditional GET. + err = parent.loadSymlinksCache() + t.Assert(err, IsNil) + t.Assert(gets, Equals, 2) + t.Assert(parent.dir.symlinksCache.HasSymlink("link1"), Equals, true) +}