-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically create folder for KV cache #1757
Conversation
5de13d4
to
13714de
Compare
@@ -616,7 +617,32 @@ func (c *client) writeCacheToFile() error { | |||
return nil | |||
} | |||
|
|||
func (c *client) createCacheDir() error { | |||
path := path.Dir(c.opts.CacheFileFn()(c.opts.Prefix())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think os.MkdirAll
is what you're looking for here.
This might be helpful as an example: https://github.com/m3db/m3/blob/master/src/dbnode/server/server.go#L188
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point with os.MkdirAll
, thanks for the hint.
I tried using lockfile.CreateAndAcquire
but somehow the other tests are failing then:
--- FAIL: TestCache (0.70s)
Error Trace: store_test.go:198
Error: Received unexpected error "grpc: the client connection is closing"
--- FAIL: TestStaleDelete__FromGet (61.54s)
Error Trace: store_test.go:832
Error: Should be true
Messages: timed out waiting for client to read values from cache
--- FAIL: TestStaleDelete__FromWatch (62.06s)
Error Trace: store_test.go:917
Error: Should be true
Messages: timed out waiting for client to read values from cache
I'll just leave it with os.MkDirAll
for now, but happy to take advice on how to properly implement the fs lock, if required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I wasn't suggesting that you use lockfile.CreateAndAcquire
I was just pointing to its implementation which uses os.MkdirAll (and passes the right permissions as well)
src/cluster/kv/etcd/store_test.go
Outdated
defer os.RemoveAll(tdir) | ||
require.NoError(t, err) | ||
|
||
cdir := path.Join(tdir, randSeq(10)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure why you need the randSeq when you're already using a new random test directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think when calling ioutil.TempDir
, it will already create a random directory. So I'm using TempDir
and then choose a random dir name cdir
be created by NewStore
into TempDir
. Then I can test for the existence of cdir
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this feels like an overkill, a const name would do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I can just use a const. I was thinking that there might be a case where this test could be run in parallel on the same machine, which might lead to multiple tests trying to create the same directory. But maybe I was overthinking :)
@cw9 Mind taking a look at this? I know you had some experience with the caching |
1f684d4
to
1bdf215
Compare
@@ -125,6 +126,28 @@ func TestNoCache(t *testing.T) { | |||
require.Equal(t, 0, len(store.(*client).cacheUpdatedCh)) | |||
} | |||
|
|||
func TestCacheDirCreation(t *testing.T) { | |||
ec, opts, closeFn := testStore(t) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move defer closeFn()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/cluster/kv/etcd/store_test.go
Outdated
defer os.RemoveAll(tdir) | ||
require.NoError(t, err) | ||
|
||
cdir := path.Join(tdir, randSeq(10)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this feels like an overkill, a const name would do here.
src/cluster/kv/etcd/store_test.go
Outdated
ec, opts, closeFn := testStore(t) | ||
|
||
tdir, err := ioutil.TempDir("", "m3tests") | ||
defer os.RemoveAll(tdir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this defer
be called after require.NoError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
|
||
cdir := path.Join(tdir, randSeq(10)) | ||
fname := path.Join(cdir, "mk3kv.json") | ||
opts = opts.SetCacheFileFn(func(string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of this, can you test to make sure the dir
you created is compatible with c.opts.Prefix()
?, try some writes and then read from the cache maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
1bdf215
to
804924d
Compare
Codecov Report
@@ Coverage Diff @@
## master #1757 +/- ##
=========================================
- Coverage 72.3% 70.9% -1.4%
=========================================
Files 986 76 -910
Lines 83010 10472 -72538
=========================================
- Hits 60028 7433 -52595
+ Misses 19006 2536 -16470
+ Partials 3976 503 -3473
Continue to review full report at Codecov.
|
src/cluster/kv/etcd/store.go
Outdated
path := path.Dir(c.opts.CacheFileFn()(c.opts.Prefix())) | ||
if _, err := os.Stat(path); err != nil { | ||
if os.IsNotExist(err) { | ||
if err := os.MkdirAll(path, 0755); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I was a little vague about this. I think if you use os.MkdirAll
you can avoid the os.Stat
and os.IsNotExist
. If the path is already a directory then it will just return nil so I think the existing checks are redundant.
The permissions thing is gonna be kind of annoying :/
We actually flow the new directory permissions around the codebase as options, so if you take a look at server.go
you'll see that when we call lockfile.CreateAndAcquire(lockPath, newDirectoryMode)
(again, you dont need to use that function, just using it as an example that does something similar) the newDirectoryMode
is passed in based on whatever its configured in our FilesystemOptions
so I think we'll need to allow setting a NewDirectoryMode
on whatever options are used to construct this store and then flow that into here if that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I didn't get it the first time, sorry about that. Fixed it now.
And the permission thing was a bit annoying indeed haha. I think I got it now but it was quite the treasure hunt and I had to touch a couple of files along my way (tried to recap it in my commit message of 0d53e7e). Let me know if there is anything wrong or if I forgot anything
Nw, triggering a build on this now for CI. |
src/cluster/client/etcd/config.go
Outdated
@@ -111,7 +113,8 @@ func (cfg Configuration) NewOptions() Options { | |||
SetCacheDir(cfg.CacheDir). | |||
SetClusters(cfg.etcdClusters()). | |||
SetServicesOptions(cfg.SDConfig.NewOptions()). | |||
SetWatchWithRevision(cfg.WatchWithRevision) | |||
SetWatchWithRevision(cfg.WatchWithRevision). | |||
SetNewDirectoryMode(cfg.NewDirectoryMode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, you might want to only set this if it's been set, maybe make it a pointer type?
Otherwise the option will always be set to os.FileMode(0)
which is not desirable, we'd prefer the default of 0755 I believe?
NewDirectoryMode *os.FileMode` yaml:"newDirectoryMode"`
if v := cfg.NewDirectoryMode; v != nil {
opts = opts.SetNewDirectoryMode(*v)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I made it a pointer type and included some unit tests as well.
zap.String("path", path), | ||
zap.Error(err), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to return err
here, otherwise it will flow through to the create successful path no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely! Forgot that to put back in after refactoring, fixed now.
- `os.MkDir` -> `os.MkDirAll` - Test is now checking if created directory is indeed a directory - Caught error of function in `initCache()`
- Move from random dir name to constant - Use `c.opts.Prefix()` for file name - Test cache is working with `Set` and `Get`
In `dbnode/server.go` `envCfg` is holding `kv.Store`. In `dbnode/environment/config.go` during configuration `etcdclient` gets initiated, so its options had to be extended that `etcdclient.opts.NewDirMode()` yields the necessary dirMode (which gets passed to `envCfg`). `NewStore()` in `cluster/kv/etcd/store.go` can then access the dirMode through the client options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What this PR does / why we need it:
Fixes #1751
Special notes for your reviewer:
Does this PR introduce a user-facing and/or backwards incompatible change?:
Does this PR require updating code package or user-facing documentation?: