fs/cache: make sure we call the Shutdown method on backends

This change ensures we call the Shutdown method on backends when
they drop out of the fs/cache and at program exit.

Some backends implement the optional fs.Shutdowner interface. Until now,
Shutdown is only checked and called, when a backend is wrapped (e.g.
crypt, compress, ...).

To have a general way to perform operations at the end of the backend
lifecycle with proper error handling, we can call Shutdown at cache
clear time.

We add a finalize hook to the cache which will be called when values
drop out of the cache.

Previous discussion: https://forum.rclone.org/t/31336
This commit is contained in:
Martin Czygan 2022-06-28 13:51:59 +02:00 committed by GitHub
parent 326c43ab3f
commit 5de9278650
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 7 deletions

View file

@ -333,3 +333,37 @@ func TestCacheRename(t *testing.T) {
assert.Equal(t, 1, c.Entries())
}
func TestCacheFinalize(t *testing.T) {
c := New()
numCalled := 0
c.SetFinalizer(func(v interface{}) {
numCalled++
})
create := func(path string) (interface{}, bool, error) {
return path, true, nil
}
_, _ = c.Get("ok", create)
assert.Equal(t, 0, numCalled)
c.Clear()
assert.Equal(t, 1, numCalled)
_, _ = c.Get("ok", create)
c.Delete("ok")
assert.Equal(t, 2, numCalled)
_, _ = c.Get("ok", create)
c.DeletePrefix("ok")
assert.Equal(t, 3, numCalled)
_, _ = c.Get("old", create)
_, _ = c.Get("new", create)
c.Rename("old", "new")
assert.Equal(t, 4, numCalled)
c.expireDuration = 1 * time.Millisecond
_, _ = c.Get("ok", create)
time.Sleep(2 * time.Millisecond)
c.cacheExpire() // "ok" and "new" fall out of cache
assert.Equal(t, 6, numCalled)
}