-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
kv: recursive blocking queries are not triggered by partial nested deletes #195
Comments
Yeah this is a current limitation, haven't found a great way to fix it yet. Probably need to implement tombstones, which are then periodically GC'd. Issue is this:
To fix this, there must be a mechanism by which the index rolls forward. This introduces a new problem which is that tombstones now accumulate. |
That makes sense. I skimmed through the code that runs the query this evening and added something that will complete a blocking query early if the length of the entries drops, but it's so hacky and not technically correct (the delete may occur before the first run) that I don't want to submit a pull request. |
Well, ok... Here's the diff in case you're interested in seeing the hack ;o) diff --git a/consul/kvs_endpoint.go b/consul/kvs_endpoint.go
index 91d8f3b..43f3778 100644
--- a/consul/kvs_endpoint.go
+++ b/consul/kvs_endpoint.go
@@ -100,7 +100,10 @@ func (k *KVS) List(args *structs.KeyRequest, reply *structs.IndexedDirEntries) e
// Get the local state
state := k.srv.fsm.State()
- return k.srv.blockingRPC(&args.QueryOptions,
+ var maxIndex uint64
+ var prevLen int
+ var terminated bool
+ err := k.srv.blockingRPC(&args.QueryOptions,
&reply.QueryMeta,
state.QueryTables("KVSList"),
func() error {
@@ -119,18 +122,29 @@ func (k *KVS) List(args *structs.KeyRequest, reply *structs.IndexedDirEntries) e
reply.Entries = nil
} else {
// Determine the maximum affected index
- var maxIndex uint64
+ maxIndex = 0
for _, e := range ent {
if e.ModifyIndex > maxIndex {
maxIndex = e.ModifyIndex
}
}
-
- reply.Index = maxIndex
reply.Entries = ent
+ // ugly hack to terminate the query upon deletion of key
+ if len(ent) < prevLen {
+ reply.Index = args.MinQueryIndex + 1
+ terminated = true
+ } else {
+ reply.Index = maxIndex
+ prevLen = len(ent)
+ }
}
return nil
})
+ // recover from ugly hack
+ if terminated {
+ reply.Index = maxIndex
+ }
+ return err
}
// ListKeys is used to list all keys with a given prefix to a seperator
|
^ diff edited to be slightly less but still hacky |
Yeah this is a bit sketchy since it doesn't work well depending on the ordering of commands. e.g. if the delete happens before the watch, it will still hang. Also the index returned is not actually accurate. |
+1 |
I figured it'd be easiest to add some quick and dirty test cases to consul-kv to demonstrate.
The text was updated successfully, but these errors were encountered: