-
Notifications
You must be signed in to change notification settings - Fork 141
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
Extract Committer and RebalanceCoordinator classes from Runloop + unit tests #1375
Merged
Merged
Changes from all commits
Commits
Show all changes
53 commits
Select commit
Hold shift + click to select a range
fd0c49d
Refactor stream completion status in preparation of additional logging
svroonland 0d6258b
Add logging + fix condition
svroonland 399dcac
Also some debug logging while waiting
svroonland c56dc69
Fix lint
svroonland 11b3238
Increase timeout
svroonland dc38739
Correct race condition
svroonland 2ee212c
Remove sequential
svroonland 9caee50
Update zio-kafka/src/main/scala/zio/kafka/consumer/internal/Runloop.s…
svroonland e034b77
Update zio-kafka/src/main/scala/zio/kafka/consumer/internal/Runloop.s…
svroonland 5b2d13e
Merge branch 'master' into more-rebalance-safe-commits-logging
svroonland 221b283
Update zio-kafka/src/main/scala/zio/kafka/consumer/internal/Runloop.s…
svroonland bad1def
Stricter comparison of pending commit offset to last pulled offset
svroonland a7f7cd2
Merge remote-tracking branch 'origin/master' into more-rebalance-safe…
svroonland cc377dd
More rebalance safe commits logging alt (#1367)
erikvanoosten 7994954
Remove withFilter usage
svroonland d3e0270
Fix timeToDeadlineMillis
svroonland 54494f3
Extract a Committer and RunloopRebalanceListener from the Runloop
svroonland 1e47de2
Fix unstable test, seems unrelated
svroonland ac4e978
Fix timeToDeadlineMillis
svroonland 5917c1d
Small convenience method
svroonland dc614da
Adjust unrepresentative test
svroonland 02532da
Document parameter
svroonland 6ad6eaf
Inline RebalanceEvent modifications
svroonland 9c36a5d
Use startTime in Commit
svroonland 07189e2
Merge branch 'master' into separate-rebalance-listener-file
svroonland d6db595
Merge commit '727e7d7acce4cb0a6f301451e1b25df3dd887e2b' into separate…
svroonland 02a36ee
Merge remote-tracking branch 'origin/master' into separate-rebalance-…
svroonland d1957d8
Do not depend on entire ConsumerSettings in Committer
svroonland 807fdf9
Make Committer better testable
svroonland 98a1031
Tests for Committer
svroonland 810362b
Let RunloopRebalanceListener own its last event
svroonland 2310ea1
Extract Committer trait
svroonland 51d3a06
Add last committed offset to stream completion status
svroonland 3439e10
Some tests for the rebalance listener
svroonland 8fb3622
Renames
svroonland b60bd8e
More tests + cleanup
svroonland c995799
Merge commit '1f8d5904' into separate-rebalance-listener-file
svroonland 7744d66
Merge commit '18aa941d' into separate-rebalance-listener-file
svroonland 05d710c
Merge commit 'e1a41448' into separate-rebalance-listener-file
svroonland ae15221
Merge commit '504074f6' into separate-rebalance-listener-file
svroonland 4acefdf
Move CommittOffsets to Committer as it is part of its interface
svroonland 0fd4114
Cleanup
svroonland 3915b08
cFix doc
svroonland e86d757
Formatting
svroonland ea59926
Merge branch 'master' into separate-rebalance-listener-file
svroonland 4072dae
Merge branch 'master' into separate-rebalance-listener-file
svroonland b6c9a26
Merge branch 'master' into separate-rebalance-listener-file
erikvanoosten 7cd3f52
Process review comments
svroonland 7e21ebb
Separate file for mocked metrics
svroonland c517f46
Fix
svroonland b170243
Styling
svroonland 0e9812f
Fix flaky test
svroonland d3ce328
Merge remote-tracking branch 'origin/master' into separate-rebalance-…
svroonland File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
204 changes: 204 additions & 0 deletions
204
zio-kafka-test/src/test/scala/zio/kafka/consumer/internal/CommitterSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
package zio.kafka.consumer.internal | ||
|
||
import org.apache.kafka.clients.consumer.OffsetAndMetadata | ||
import org.apache.kafka.common.TopicPartition | ||
import org.apache.kafka.common.errors.RebalanceInProgressException | ||
import zio.kafka.consumer.diagnostics.Diagnostics | ||
import zio.test._ | ||
import zio.{ durationInt, Promise, Ref, ZIO } | ||
|
||
import java.util.{ Map => JavaMap } | ||
import scala.jdk.CollectionConverters.MapHasAsJava | ||
|
||
object CommitterSpec extends ZIOSpecDefault { | ||
override def spec = suite("Committer")( | ||
test("signals that a new commit is available") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter | ||
.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
_ <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
} yield assertCompletes | ||
}, | ||
test("handles a successful commit by completing the commit effect") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => ZIO.attempt(callback.onComplete(offsets, null))) | ||
_ <- commitFiber.join | ||
} yield assertCompletes | ||
}, | ||
test("handles a failed commit by completing the commit effect with a failure") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => | ||
ZIO.attempt(callback.onComplete(offsets, new RuntimeException("Commit failed"))) | ||
) | ||
result <- commitFiber.await | ||
} yield assertTrue(result.isFailure) | ||
}, | ||
test("retries when rebalancing") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => | ||
ZIO.attempt(callback.onComplete(offsets, new RebalanceInProgressException("Rebalance in progress"))) | ||
) | ||
_ <- committer.processQueuedCommits((offsets, callback) => ZIO.attempt(callback.onComplete(offsets, null))) | ||
result <- commitFiber.await | ||
} yield assertTrue(result.isSuccess) | ||
}, | ||
test("adds 1 to the committed last offset") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
_ <- committer.commit(Map(tp -> new OffsetAndMetadata(1))).forkScoped | ||
_ <- commitAvailable.await | ||
committedOffsets <- Promise.make[Nothing, JavaMap[TopicPartition, OffsetAndMetadata]] | ||
_ <- committer.processQueuedCommits((offsets, callback) => | ||
committedOffsets.succeed(offsets) *> ZIO.attempt(callback.onComplete(offsets, null)) | ||
) | ||
offsetsCommitted <- committedOffsets.await | ||
} yield assertTrue( | ||
offsetsCommitted == Map(tp -> new OffsetAndMetadata(2)).asJava | ||
) | ||
}, | ||
test("batches commits from multiple partitions and offsets") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitsAvailable <- Promise.make[Nothing, Unit] | ||
nrCommitsDone <- Ref.make(0) | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = | ||
ZIO.whenZIO(nrCommitsDone.updateAndGet(_ + 1).map(_ == 3))(commitsAvailable.succeed(())).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
tp2 = new TopicPartition("topic", 1) | ||
commitFiber1 <- committer.commit(Map(tp -> new OffsetAndMetadata(1))).forkScoped | ||
commitFiber2 <- committer.commit(Map(tp -> new OffsetAndMetadata(2))).forkScoped | ||
commitFiber3 <- committer.commit(Map(tp2 -> new OffsetAndMetadata(3))).forkScoped | ||
_ <- commitsAvailable.await | ||
committedOffsets <- Promise.make[Nothing, JavaMap[TopicPartition, OffsetAndMetadata]] | ||
_ <- committer.processQueuedCommits((offsets, callback) => | ||
committedOffsets.succeed(offsets) *> ZIO.attempt(callback.onComplete(offsets, null)) | ||
) | ||
_ <- commitFiber1.join zip commitFiber2.join zip commitFiber3.join | ||
offsetsCommitted <- committedOffsets.await | ||
} yield assertTrue( | ||
offsetsCommitted == Map(tp -> new OffsetAndMetadata(3), tp2 -> new OffsetAndMetadata(4)).asJava | ||
) | ||
}, | ||
test("keeps track of pending commits") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => ZIO.attempt(callback.onComplete(offsets, null))) | ||
pendingCommitsDuringCommit <- committer.pendingCommitCount | ||
_ <- committer.cleanupPendingCommits | ||
pendingCommitsAfterCommit <- committer.pendingCommitCount | ||
_ <- commitFiber.join | ||
} yield assertTrue(pendingCommitsDuringCommit == 1 && pendingCommitsAfterCommit == 0) | ||
}, | ||
test("keep track of committed offsets") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => ZIO.attempt(callback.onComplete(offsets, null))) | ||
committedOffsets <- committer.getCommittedOffsets | ||
_ <- commitFiber.join | ||
} yield assertTrue(committedOffsets.offsets == Map(tp -> 0L)) | ||
}, | ||
test("clean committed offsets of no-longer assigned partitions") { | ||
for { | ||
runtime <- ZIO.runtime[Any] | ||
commitAvailable <- Promise.make[Nothing, Unit] | ||
committer <- LiveCommitter.make( | ||
10.seconds, | ||
Diagnostics.NoOp, | ||
new DummyMetrics, | ||
onCommitAvailable = commitAvailable.succeed(()).unit, | ||
sameThreadRuntime = runtime | ||
) | ||
tp = new TopicPartition("topic", 0) | ||
commitFiber <- committer.commit(Map(tp -> new OffsetAndMetadata(0))).forkScoped | ||
_ <- commitAvailable.await | ||
_ <- committer.processQueuedCommits((offsets, callback) => ZIO.attempt(callback.onComplete(offsets, null))) | ||
_ <- committer.keepCommitsForPartitions(Set.empty) | ||
committedOffsets <- committer.getCommittedOffsets | ||
_ <- commitFiber.join | ||
} yield assertTrue(committedOffsets.offsets.isEmpty) | ||
} | ||
) @@ TestAspect.withLiveClock @@ TestAspect.nonFlaky(100) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Why is the retrying needed here, and not in other tests?
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 couldn't figure that out either..