Skip to content
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

Fix promise lost in ClientSide AuthHandler #3902

Conversation

hangc0276
Copy link
Contributor

Motivation

#3783 changed the AddEntry Request type from BookieProtocol.AddRequest to ByteBuf or ByteBufList, leading to the AddEntry request being added into waitingForAuth queue in the client-side AuthHandler

if (toSend instanceof ByteBuf) {
request = ((ByteBuf) toSend).retainedDuplicate();
} else {
request = ByteBufList.clone((ByteBufList) toSend);
}

} else if (msg instanceof ByteBuf || msg instanceof ByteBufList) {
waitingForAuth.add(msg);

For the requests in the waitingForAuth, they will be polled out by AuthHandshakeCompleteCallback#operationComplete.

public void operationComplete(int rc, Void v) {
if (rc == BKException.Code.OK) {
synchronized (this) {
authenticated = true;
Object msg = waitingForAuth.poll();
while (msg != null) {
ctx.writeAndFlush(msg);
msg = waitingForAuth.poll();
}
}
} else {

However, the waitingForAuth queue only stores the AddEntry request, and it ignores the related ChannelPromise. When polling requests from the waitingForAuth queue in AuthHandshakeCompleteCallback#operationComplete, those requests will be written and flushed into the Netty channel without passing any ChannelPromises, and Netty will use voidPromise by default.

In a word, the AddEntry request side passed ChannelPromise will be replaced with voidPromise, and the original promise will never be complete and the following operations won't execute.

ChannelPromise promise = channel.newPromise().addListener(future -> {
if (future.isSuccess()) {
nettyOpLogger.registerSuccessfulEvent(MathUtils.elapsedNanos(startTime), TimeUnit.NANOSECONDS);
CompletionValue completion = completionObjects.get(key);
if (completion != null) {
completion.setOutstanding();
}
} else {
nettyOpLogger.registerFailedEvent(MathUtils.elapsedNanos(startTime), TimeUnit.NANOSECONDS);
}
});

There are two impactions:

  • The nettyOpLogger metric won't update
  • The addEntryOutstanding counter metric won't update

Changes

Store the ChannelPromise along with the request in the client-side AuthHandle and pass it to the Netty channel when polling out.

Copy link
Member

@zymap zymap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have a test?

Copy link
Member

@horizonzy horizonzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch

Copy link
Contributor

@dlg99 dlg99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test

Copy link
Member

@wenbingshen wenbingshen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice Catch!

It doesn't seem very easy to add an AddEntry request before the auth handshake is complete, especially getting it into the waitingForAuth queue, and the auth request will also trigger the promise execution.

@hangc0276
Copy link
Contributor Author

We need to add a unit test for this change, move to the next release

@shoothzj
Copy link
Member

As dicussed in #4293 I think we can close this PR now.

@shoothzj shoothzj closed this May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants