-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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 a couple of bugs in exclusive producer #9554
Conversation
StringBuilder errorMsg = new StringBuilder(); | ||
errorMsg.append("Topic has an existing exclusive producer"); | ||
if (producers.keys().hasMoreElements()) { | ||
errorMsg.append(": " + producers.keys().nextElement()); |
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'm not sure this avoids the race altogether since there's no atomicity between checking hasMoreElements()
and nextElement()
. I think we could get an iterator and use that to check, since it will be guaranteed to be consistent.
if (producers.keys().hasMoreElements()) { | ||
errorMsg.append(": " + producers.keys().nextElement()); | ||
} |
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.
if (producers.keys().hasMoreElements()) { | |
errorMsg.append(": " + producers.keys().nextElement()); | |
} | |
producers.keySet().stream().findFirst().map(p -> errorMsg.append(": " ).append(p)); |
if (producers.keys().hasMoreElements()) { | ||
errorMsg.append(": " + producers.keys().nextElement()); | ||
} |
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.
if (producers.keys().hasMoreElements()) { | |
errorMsg.append(": " + producers.keys().nextElement()); | |
} | |
producers.keySet().stream().findFirst().map(p -> errorMsg.append(": " ).append(p)); |
1. Fix uncaught exception in exclusive producer 2. Incorrect logic when producer is removed
71a7682
to
08a9c96
Compare
@@ -109,6 +109,9 @@ | |||
|
|||
protected volatile Optional<Long> topicEpoch = Optional.empty(); | |||
private volatile boolean hasExclusiveProducer; | |||
// pointer to the exclusive producer | |||
private volatile Producer exclusiveProducer; |
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 we just use a ref to the name instead? Otherwise it will provide a much longer toString() representation
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.
We could. Just wanted to preserve the existing logging behavior.
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 existing one was printing the key of the map, hence just the producer name
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.
changed
return FutureUtil.failedFuture(new ProducerBusyException( | ||
"Topic has an existing exclusive producer: " + producers.keys().nextElement())); | ||
return FutureUtil.failedFuture( | ||
new ProducerFencedException("Topic has an existing exclusive producer: " + exclusiveProducer)); |
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.
A shared producer will not get fenced, instead it will get a busy 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.
good catch
@@ -619,17 +629,21 @@ public void removeProducer(Producer producer) { | |||
|
|||
protected void handleProducerRemoved(Producer producer) { | |||
// decrement usage only if this was a valid producer close | |||
long newCount = USAGE_COUNT_UPDATER.decrementAndGet(this); | |||
if (newCount == 0) { | |||
USAGE_COUNT_UPDATER.decrementAndGet(this); |
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.
Since we add an issue withe consumers here, can you add a test with consumer, to make sure we don’t break it in the future?
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.
sure
* Fix a couple of bugs in exclusive producer 1. Fix uncaught exception in exclusive producer 2. Incorrect logic when producer is removed Co-authored-by: Jerry Peng <jerryp@splunk.com>
Motivation
When multiple producers contend to become the exclusive producer. A race condition can occur and the following exception can happen but gets silently swallowed which eventually leads to a client timeout.
Also
USAGE_COUNT_UPDATER
is used incorrectly inhandleProducerRemoved()