Skip to content

KAFKA-10357: Extract setup of repartition topics from Streams partition assignor#9848

Merged
ableegoldman merged 8 commits intoapache:trunkfrom
cadonna:AK10357-explicit_user_init
Jan 22, 2021
Merged

KAFKA-10357: Extract setup of repartition topics from Streams partition assignor#9848
ableegoldman merged 8 commits intoapache:trunkfrom
cadonna:AK10357-explicit_user_init

Conversation

@cadonna
Copy link
Copy Markdown
Member

@cadonna cadonna commented Jan 8, 2021

To implement the explicit user initialization of Kafka Streams as
described in KIP-698, we first need to extract the code for the
setup of the repartition topics from the Streams partition assignor
so that it can also be called outside of a rebalance.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

…tition assignor

To implement the explicit user initialization of Kafka Streams as
described in KIP-698, we first need to extract the code for the
setup of the repartition topics from the Streams partition assignor
so that it can also be called outside of a rebalance.
@cadonna
Copy link
Copy Markdown
Member Author

cadonna commented Jan 8, 2021

Call for review: @ableegoldman @guozhangwang @lct45 @wcarlson5

return Collections.unmodifiableMap(topicPartitionInfos);
}

private Map<String, InternalTopicConfig> computeRepartitionTopicConfig(final Map<Integer, TopicsInfo> topicGroups,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is there a reason you renamed this from computeRepartitionTopicMetadata to computeRepartitionTopicConfig?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I thought since the returned value is a bunch of configs computeRepartitionTopicConfig() would be more precise.

Copy link
Copy Markdown

@lct45 lct45 left a comment

Choose a reason for hiding this comment

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

Overall, LGTM. Looks like most of the logic has stayed consistent with what was there. Thanks for the PR @cadonna !


if (numPartitions == null) {
partitionCountNeeded = true;
log.trace("Unable to determine number of partitions for {}, another iteration is needed",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe I'm missing something, but it looks like we want to go through the do loop again if we have null partitions, but in this case wouldn't we hit the if statement below and throw an exception, since at this point partitionCountNeeded == True and progressMadeThisIteration == False ? Or does that just log an exception and continue through the do loop?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@lct45 sort of; the point of progressMadeThisIteration is to break out of the loop entirely if we detect that we're infinitely looping, as was the case in a recent-ish bug. We want to continue looping only as long as we're actually gaining new information/filling in the partition count of some topic group (subtopology).

So yes, if progressMadeThisIteration = false after the full loop, but we still don't have all the partition counts (partitionCountNeeded = true), then oh well. Something went wrong 🙂 We should throw

private final Node[] inSyncReplicas;
private final Node[] offlineReplicas;

// Used only by tests
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The usual lying comment. This constructor is not only used in tests.

Copy link
Copy Markdown
Member

@ableegoldman ableegoldman left a comment

Choose a reason for hiding this comment

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

Nice work. A few of the variable names were kind of throwing me off, but you can apply my suggestions (or not :P) in a followup PR if you'd prefer. This one pretty much LGTM, looking forward to the next PR


private void checkIfExternalSourceTopicsExist(final TopicsInfo topicsInfo,
final Cluster clusterMetadata) {
final Set<String> externalSourceTopics = new HashSet<>(topicsInfo.sourceTopics);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

prop: rename to missingExternalSourceTopics or similar


if (numPartitions == null) {
partitionCountNeeded = true;
log.trace("Unable to determine number of partitions for {}, another iteration is needed",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@lct45 sort of; the point of progressMadeThisIteration is to break out of the loop entirely if we detect that we're infinitely looping, as was the case in a recent-ish bug. We want to continue looping only as long as we're actually gaining new information/filling in the partition count of some topic group (subtopology).

So yes, if progressMadeThisIteration = false after the full loop, but we still don't have all the partition counts (partitionCountNeeded = true), then oh well. Something went wrong 🙂 We should throw

final String repartitionSourceTopic) {
Integer partitionCount = null;
// try set the number of partitions for this repartition topic if it is not set yet
for (final TopicsInfo upstreamTopicsInfo : topicGroups.values()) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's a bit confusing to call this upstreamTopicsInfo since that will only be true of one (or some) of these topic groups. Most of them are not upstream of the current

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, I was also not sure. I renamed some of the variables. Let me know if it is better now.

final Cluster clusterMetadata = niceMock(Cluster.class);

@Before
public void setUp() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Did you mean to leave in an empty method?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, I will remove it.

metadata,
logPrefix
);
repartitionTopics.setup();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why not just do the setup inside the constructor?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That is a valid question. When we introduce the explicit initialization and the manual and automatic configs, we need to distinguish between setting up the internal topics and verifying the internal topics. Hence, there will be two methods on the RepartitionTopic class. We will create the object and then according to the configs we will either just verify or verify and setup the repartition topics. We could accomplish the same with a flag in the constructor but I thought the code might be easier to understand with two methods.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Makes sense, thanks

@ableegoldman
Copy link
Copy Markdown
Member

@cadonna looks like checkstyleTest is failing

@cadonna
Copy link
Copy Markdown
Member Author

cadonna commented Jan 18, 2021

@ableegoldman Thank you for the info!
This happens when you try to take shortcuts Friday evening. 😁

Copy link
Copy Markdown
Contributor

@guozhangwang guozhangwang left a comment

Choose a reason for hiding this comment

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

Made a pass on the PR. Overall LGTM.

I think once they current comments are addressed it can be merged cc @ableegoldman

final Map<Integer, TopicsInfo> topicGroups = taskManager.builder().topicGroups();

final Map<TopicPartition, PartitionInfo> allRepartitionTopicPartitions = prepareRepartitionTopics(topicGroups, metadata);
final Map<TopicPartition, PartitionInfo> allRepartitionTopicPartitions = prepareRepartitionTopics(metadata);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: line 365 above can be moved down now since it is only needed before line 379.


// make sure the repartition source topics exist with the right number of partitions,
// create these topics if necessary
internalTopicManager.makeReady(repartitionTopicMetadata);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not related to this PR: when reading the makeReady code again, I feel that the way we get the retries config by first constructing a dummy admin client can be simplified. Also, it is debatable that if we only do verify, then do we really need to retry or not since the admin client itself already retries internally.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think we should keep this in mind. For this ticket, we need to touch makeReady() anyways, because we need to separate verification from creation.

* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kafka.streams.processor.internals;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As always, thanks for the great test coverage!

@cadonna
Copy link
Copy Markdown
Member Author

cadonna commented Jan 22, 2021

@ableegoldman @guozhangwang, could someone of you merge this PR since it seems there are no further open question.

@ableegoldman
Copy link
Copy Markdown
Member

One unrelated test failure in SocketServerTest.testConnectionRatePerIp

@ableegoldman ableegoldman merged commit 019cd4a into apache:trunk Jan 22, 2021
@ableegoldman
Copy link
Copy Markdown
Member

Merged to trunk

ijuma added a commit to ijuma/kafka that referenced this pull request Jan 26, 2021
…e-allocations-lz4

* apache-github/trunk: (562 commits)
  MINOR: remove unused code from MessageTest (apache#9961)
  MINOR: Fix visibility of Log.{unflushedMessages, addSegment} methods (apache#9966)
  KAFKA-12229: Restore original class loader in integration tests using EmbeddedConnectCluster during shutdown  (apache#9942)
  KAFKA-12190: Fix setting of file permissions on non-POSIX filesystems (apache#9947)
  MINOR: Remove `toStruct` and `fromStruct` methods from generated protocol classes (apache#9960)
  MINOR: Fix typo in Utils#toPositive (apache#9943)
  MINOR: MessageUtil: remove some deadcode (apache#9931)
  MINOR: Update zstd-jni to 1.4.8-2 (apache#9957)
  MINOR: Revert assertion in MockProducerTest (apache#9956)
  MINOR: Optimize assertions in unit tests (apache#9955)
  MINOR: Tag `RaftEventSimulationTest` as `integration` and tweak it (apache#9925)
  MINOR: Update to Gradle 6.8.1 (apache#9953)
  MINOR: A few small group coordinator cleanups (apache#9952)
  MINOR: Upgrade ducktape to version 0.8.1  (apache#9933)
  MINOR: fix record time in test shouldWipeOutStandbyStateDirectoryIfCheckpointIsMissing (apache#9948)
  MINOR: Restore interrupt status when closing (apache#9863)
  KAFKA-10357: Extract setup of repartition topics from Streams partition assignor (apache#9848)
  KAFKA-12212; Bump Metadata API version to remove `ClusterAuthorizedOperations` fields (KIP-700) (apache#9945)
  MINOR: log 2min processing summary of StreamThread loop (apache#9941)
  MINOR: Drop enable.metadata.quorum config (apache#9934)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants