diff --git a/adapter.go b/adapter.go index 4c2e093..03ab517 100644 --- a/adapter.go +++ b/adapter.go @@ -651,6 +651,14 @@ func (a *Adapter) Size(key string) (int64, error) { _, err = a.ReadAt(key, []byte{0}, 0) //ignore errors as we just want to populate the size cache si, ok = a.sizeCache.Get(key) } + if err == nil && !ok { + //first block may be in the block cache, but the size was evicted from the size cache, so we force + //a direct read to the source to repopulate the size cache. This should happen extremely + //unfrequently. + _, err = a.srcReadAt(key, []byte{0}, 0) + si, ok = a.sizeCache.Get(key) + } + if ok { size := si.(int64) if size == -1 { diff --git a/adapter_test.go b/adapter_test.go index 44e0dbc..da0d99b 100644 --- a/adapter_test.go +++ b/adapter_test.go @@ -466,3 +466,12 @@ func TestLogging(t *testing.T) { _, _ = r.Read(buf) assert.Contains(t, lbuf.String(), "GET thekey off=0 len=131072") } + +func TestSizeCacheEviction(t *testing.T) { + bc, _ := NewAdapter(rr, SizeCache(1)) + _, err := bc.Size("thekey") + assert.NoError(t, err) + _, _ = bc.Size("enoent") + _, err = bc.Size("thekey") + assert.NoError(t, err) +}