-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-2669; Fix LogCleanerIntegrationTest #327
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
Changes from 3 commits
39c356a
2616cad
6cbb4a5
74cd5e7
0f4d1cf
69ffb13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,12 +149,25 @@ class LogCleaner(val config: CleanerConfig, | |
| } | ||
|
|
||
| /** | ||
| * For testing, a way to know when work has completed. This method blocks until the | ||
| * For testing, a way to know when work has completed. This method waits until the | ||
| * cleaner has processed up to the given offset on the specified topic/partition | ||
| * | ||
| * @param topic The Topic to be cleaned | ||
| * @param part The partition of the topic to be cleaned | ||
| * @param offset The first dirty offset that the cleaner doesn't have to clean | ||
| * @param maxWaitMs The maximum time in ms to wait for cleaner | ||
| * | ||
| * @return A boolean indicating whether the work has completed before timeout | ||
| */ | ||
| def awaitCleaned(topic: String, part: Int, offset: Long, timeout: Long = 30000L): Unit = { | ||
| while(!cleanerManager.allCleanerCheckpoints.contains(TopicAndPartition(topic, part))) | ||
| Thread.sleep(10) | ||
| def awaitCleaned(topic: String, part: Int, offset: Long, maxWaitMs: Long = 60000L): Boolean = { | ||
| var remainingWaitMs = maxWaitMs | ||
| while (cleanerManager.allCleanerCheckpoints.get(TopicAndPartition(topic, part)).fold(true)(_ < offset)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What will happen if allCleanerCheckpoints does not contain the partition?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was originally concerned that if the partition is not included due to some bugs then we are doomed to wait for 1 minute in practice; but then I realize this function is only going to be used in testing, so this should be fine. |
||
| if (remainingWaitMs == 0) | ||
| return false | ||
| Thread.sleep(math.min(100, remainingWaitMs)) | ||
| remainingWaitMs = math.max(0, remainingWaitMs - 100) | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The following is more idiomatic: while (cleanerManager.allCleanerCheckpoints.get(TopicAndPartition(topic, part)).fold(true)(_ < offset)
Thread.sleep(10)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice approach. I will follow your suggestion. |
||
| return true | ||
| } | ||
|
|
||
| /** | ||
|
|
||
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 for implementing the timeout. I, personally, prefer the following implementation:
It avoids
return, which is discouraged in Scala, makes the loop condition clearer and the timeout only controls when to exit the loop, the return value is based onisCleanedonly.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.
Thank you. This is a very nice usage of nested function in Scala:) I have updated the patch as you suggested.
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.
Great, thanks. Sorry to nitpick, but you don't need the
math.maxinremainingWaitMs = ...since we check for > 0 (that is, it's OK for the value to be negative). Looks good otherwise.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.
One question: is there a reason why we are reducing the
remainingWaitMsby 100 instead of the actual sleep time like in my suggested version (just curious)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.
@ijuma Thanks for your suggestion:) I have replaced that statement by
remainingWaitMs -= 100.I think, w.r.t. functionality, my
Thread.sleep(math.min(100, remainingWaitMs))is exactly the same as yourval sleepTime = math.min(100, remainingWaitMs)andThread.sleep(sleepTime), right? I think the only difference is that my implementation used 1 less lines here and avoided extra variablesleepTime.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 for updating it!
There are two differences:
100in two places. If someone decides that the sleep time should be a different value, they may miss the fact that they have to update it in two places.100even if sleep time was lower because ofmath.min. This won't have any effect with the current loop condition, but it could change in a future update.These minor issues add-up and make refactoring harder.
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 think the first problem is minor and it is OK to change it twice. But I agree it is a valid problem. In stead of following either of our approach, I think it is better to do
sleepInterval = 100to make this an explicit configuration to solve the problem here.I am a bit confused by your comments on the 2nd problem... I had this implementation previously that didn't have this problem:
Then you made the following comment:
Therefore I change the implementation to do
remainingWaitMs -= 100. Actually I am fine with both solutions. But now I am confused by your latest comment that "it is not OK to have remainingWaitMs < 0". Did I misunderstand your comment?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.
sleepInterval = 100is better if you want to make it possible for callers to configure that parameter. It seems to me that it's unnecessary, but up to you. It is not the worst thing in the world to have to change two things in adjacent lines, so you can also keep it as is if committers are fine with the code (there is also a slight readability penalty as users have to figure out that the100in both cases represent the same thing). It is a minor thing for sure, but personally I try to write code so that there are no minor things when the solution is easy. :)I think I didn't explain myself well regarding point 2, but let's just drop it as it's subtle and it's not worth spending the time discussing it in this context.
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.
@ijuma Thanks:) I have updated patch to follow the code you suggested. Please have a look.