-
Notifications
You must be signed in to change notification settings - Fork 38.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
etcd3/watcher: Event.Object should have the same rev as etcd delete #25396
Conversation
/cc @xiang90 @wojtek-t @timothysc It's a problem I found with test failure. After fixing it, the test failure never happen. |
// which it gets deleted. Users use that revision to tell ordering. | ||
rev = e.rev | ||
} | ||
oldObj, err = decodeObj(codec, versioner, getResp.Kvs[0].Value, rev) |
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.
this is strange... why shall we change the revision of the old object? for the watch issue, can you show me the code for etcd2? i would assume there are two objs in the event curObj and oldObj and e.Rev should be the rev of curObj. So the rev of the oldObj should not matter at all for ordering purpose. 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.
The etcd2 code is written in first comment too:
kubernetes/pkg/storage/etcd/etcd_watcher.go
Lines 437 to 442 in 995f022
if res.Node != nil { | |
// Note that this sends the *old* object with the etcd index for the time at | |
// which it gets deleted. This will allow users to restart the watch at the right | |
// index. | |
node.ModifiedIndex = res.Node.ModifiedIndex | |
} |
watch.Event contains only one object.
So the rev of the oldObj should not matter at all for ordering purpose. No?
I have the same concern. The object is actually returned via Informer too.
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... This seems to be fragile...
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.
They use the event number to signal the last known resource version in the informer in case there is a watch break.
LGTM |
5b8257e
to
f656dc6
Compare
@@ -123,7 +123,7 @@ func TestDeleteTriggerWatch(t *testing.T) { | |||
if err := store.Delete(ctx, key, &api.Pod{}, nil); err != nil { | |||
t.Fatalf("Delete failed: %v", err) | |||
} | |||
testCheckResult(t, 0, watch.Deleted, w, storedObj) | |||
testCheckResult(t, 0, watch.Deleted, w, 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.
can we still check the expected storeObject? we probably need to change the rev of the storeObj? Or if we do not care about the triggered result, we should explicitly express that when calling the testCheckResult func.
instead of previous object's revision.
@@ -227,14 +265,17 @@ func (c *testCodec) Decode(data []byte, defaults *unversioned.GroupVersionKind, | |||
return nil, nil, errors.New("Expected decoding failure") | |||
} | |||
|
|||
func testCheckResult(t *testing.T, i int, expectEventType watch.EventType, w watch.Interface, expectObj *api.Pod) { | |||
func testCheckResult(t *testing.T, i int, expectEventType watch.EventType, w watch.Interface, expectObj *api.Pod, ignoreResult bool) { |
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... how about adding another function called testExpectReceivingEvent, which only tries to receive event from the given chan? I dislike the bool arg.
30f2a64
to
3592152
Compare
@@ -227,14 +265,25 @@ func (c *testCodec) Decode(data []byte, defaults *unversioned.GroupVersionKind, | |||
return nil, nil, errors.New("Expected decoding failure") | |||
} | |||
|
|||
func testCheckEventType(t *testing.T, expectEventType watch.EventType, w watch.Interface) { |
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.
@xiang90
Your suggestion sounds actually a good idea.
I have split another function to check event type specifically.
GCE e2e build/test passed for commit 30f2a64ca8386b5c9b1184d4b5c374fddc07cc2f. |
Automatic merge from submit-queue |
What's the problem?
When a delete is watched, the revision should be larger than any previous to guarantee ordering. However, currently etcd3 decodes the previous rev into returned object:
kubernetes/pkg/storage/etcd3/watcher.go
Line 322 in 995f022
This will break, for example, cacher's assumption here if it re-watch.
kubernetes/pkg/storage/cacher.go
Lines 579 to 581 in 995f022
The etcd2 impl. also takes the current ModifiedIndex to ensure it's a larger number:
kubernetes/pkg/storage/etcd/etcd_watcher.go
Lines 437 to 442 in 995f022
What's this PR?
It fixes above problem by using etcd's delete revision.