-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
*: Add progress notify request watch request #9869
Conversation
cc @wenjiaswe |
continue | ||
} | ||
go printWatchCh(c, ch, execArgs) | ||
case "progress": |
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.
Q. Does this work? Think watch streams are not shared in etcdctl? So, this progress request would be no-op?
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. I'm not familiar with that aspect of etcdctl. Here's a sample run I just did:
ETCDCTL_API=3 bin/etcdctl watch --interactive
watch a
progress
progress notify: 14
watch b
progress
progress notify: 14
Is there a case you can think of that might exercise a problem with the separate watch streams?
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.
@jpbetz Oh, actually you are right. This is for interactive watch command, so requests are sharing the stream. I was thinking of just regular watch command, and a separate progress command.
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.
@gyuho I'll add more edge cases to the TestWatchRequestProgress
clientv3/integration test that I added in this PR. I currently just does: (1) start a watch (2) put a k/v (3) verify the k/v is recieved over the watch (4) request progress (5) check that progress is received over the watch.
Corner cases might be:
- No watches
- More than one watch
- Put a key not visible to the watch, ensure progress is incremented
If you think of any others, let me know.
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 modified the watch stream publisher to send the progress notify responses on all watch channels, the result is etcdctl now does:
ETCDCTL_API=3 bin/etcdctl watch --interactive
watch a
progress
progress notify: 14
watch b
progress
progress notify: 14
progress notify: 14
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.
@jpbetz I tried those corner cases with this branch, and confirmed that it's covered. I can't think of any other, for now. Thanks!
etcdserver/etcdserverpb/rpc.proto
Outdated
@@ -367,6 +367,9 @@ message ResponseHeader { | |||
// member_id is the ID of the member which sent the response. | |||
uint64 member_id = 2; | |||
// revision is the key-value store revision when the request was applied. | |||
// For watch progress responses, the header.revision indicates progress. All future events | |||
// recieved in this stream are guarenteed to have a higher revision number than the |
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.
s/guarenteed/guaranteed/
:)
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 and re-ran genproto.
03a8503
to
b82ede6
Compare
clientv3/watch.go
Outdated
@@ -608,7 +662,28 @@ func (w *watchGrpcStream) dispatchEvent(pbresp *pb.WatchResponse) bool { | |||
Canceled: pbresp.Canceled, | |||
cancelReason: pbresp.CancelReason, | |||
} | |||
ws, ok := w.substreams[pbresp.WatchId] | |||
|
|||
if wr.IsProgressNotify() { |
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.
@gyuho Since progress notify is global, does it make sense to broadcast the watch response to all channel substreams? This will change the behavior of existing progress notifies as well, but makes it easier to ensure any watch caches being updated via a WatchChan are updated with the latest progress.
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.
Yes, since Progress Notify request is sent with no specific watch ID, it makes sense to dispatch globally.
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.
0f2d760
to
fbade37
Compare
ea801b9
to
fb75b83
Compare
Codecov Report
@@ Coverage Diff @@
## master #9869 +/- ##
==========================================
+ Coverage 69.03% 69.11% +0.07%
==========================================
Files 385 385
Lines 35703 35757 +54
==========================================
+ Hits 24648 24713 +65
+ Misses 9260 9238 -22
- Partials 1795 1806 +11
Continue to review full report at Codecov.
|
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.
Just requesting some clarifications. With the code, the use case makes much more sense now.
LGTM.
I tried this branch, and works good.
@@ -355,6 +355,23 @@ foo # key | |||
bar_latest # value of foo key after modification | |||
``` | |||
|
|||
## Watch progress | |||
|
|||
Applications may want to check the progress of a watch to determine how up-to-date the watch stream is. For example, if a watch is used to update a cache, it can be useful to know if the cache is stale compared to the revision from a qoroum read. |
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.
s/qoroum/quorum/
:)
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.
Can we also clarify this revision in watch response to progress notify request is revision from the local node that the watch stream is connected to? Since quorum read cannot be returned from the partitioned node, mention something like "stale compared to the revision fetched from a healthy cluster (e.g. revision in quorum read response)".
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, yes, I should be more explicit about that revision is returned. Fixing.
clientv3/integration/watch_test.go
Outdated
t.Fatalf("expected resp.IsProgressNotify() == true") | ||
} | ||
if resp.Header.Revision != 3 { | ||
t.Fatalf("resp.Header.Revision expected 2, got %d", resp.Header.Revision) |
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.
s/resp.Header.Revision expected 2/resp.Header.Revision expected 3/
?
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. Thanks for the catch.
clientv3/watch.go
Outdated
@@ -72,6 +72,9 @@ type Watcher interface { | |||
|
|||
// Close closes the watcher and cancels all watch requests. | |||
Close() error | |||
|
|||
// RequestProgress requests a progress notify response be sent in all watch channels. | |||
RequestProgress(ctx context.Context) error |
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 this above Close method? Also rename this to just Progress?
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.
Actually, after second thought RequestProgress is better.
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.
Thanks @xiang90, I've moved above Close()
.
ca942a3
to
1186f46
Compare
@jpbetz We still need to preserve the old behavior of progress notification. |
@xiang90 Good point. Problem with current Protocol Buffer definition is we do not differentiate between regular progress notify and the one triggered via request progress. Also another problem is we do not expose watch response ID that can be used to pinpoint which stream to receive progress notify. So, it makes sense to broadcast the response for manually triggered progress request. But, it breaks the behavior of periodic progress notify response. Maybe add an extra field to indicate that this response is requested by the request progress request? |
@gyuho Looks like within |
Sounds good. Adding extra check |
To preserve the previous behavior I've assigned -1 watch IDs to watch responses for This makes it clear that the response is not associated with any particular watch id, which seems helpful in preventing from the watch response from being mis-interpreted. Since it's not obvious that it should be broadcast to all channels, I've added a comment explaining that. |
Can we fix the CI?
We just need to whitelist |
Eek. Fixing! Looks like this should have failed during |
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 thanks!
Add
RequestProgress
function toWatcher
interface to request a progress notify response in all watch channels.That can be used to check if a watcher is "caught up" to a particular revision, which is useful when determining if a watch cache is stale by comparing the progress revision to the revision returned in a quorum read.
Note that this also changes how progress notify events are communicated. They are now broadcast to all watch channels.
Fixes #9855
Example etcdctl usage: