-
Notifications
You must be signed in to change notification settings - Fork 2.9k
NIFI-15226 Allow ConsumeKafka to use static partition mapping #10538
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
base: main
Are you sure you want to change the base?
NIFI-15226 Allow ConsumeKafka to use static partition mapping #10538
Conversation
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.nifi</groupId> | ||
| <artifactId>nifi-framework-nar-utils</artifactId> |
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.
This dependency appears to be unused, can it be removed?
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.
org.apache.nifi.mock.MockComponentLogger is referenced in TestConsumerPartitionsUtil
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 clarifying. In that case, this dependency should be removed and MockComponentLogger should be replaced with MockComponentLog from nifi-mock to avoid referencing framework modules in extension modules.
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 preserved this class from the older change. But actually we don't need either. We can just mock the logger with Mockito.
exceptionfactory
left a 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.
The initial build fails on the following tests:
Error: ConsumeKafkaTest.testVerifyFailed:116 » NullPointer Cannot invoke "org.apache.nifi.kafka.service.api.consumer.PollingContext.getTopics()" because "this.pollingContext" is null
Error: ConsumeKafkaTest.testVerifySuccessful:99 » NullPointer Cannot invoke "org.apache.nifi.kafka.service.api.consumer.PollingContext.getTopics()" because "this.pollingContext" is null
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Outdated
Show resolved
Hide resolved
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Outdated
Show resolved
Hide resolved
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Show resolved
Hide resolved
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Outdated
Show resolved
Hide resolved
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Outdated
Show resolved
Hide resolved
...afka-service-shared/src/main/java/org/apache/nifi/kafka/service/Kafka3ConnectionService.java
Outdated
Show resolved
Hide resolved
exceptionfactory
left a 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.
Thanks for the work on this @tpalfy. I noted a handful of minor recommendations, and plan to take a closer look at some of the implementation details.
| private final AutoOffsetReset autoOffsetReset; | ||
|
|
||
| public Subscription(final String groupId, final Collection<String> topics, final AutoOffsetReset autoOffsetReset) { | ||
| public Subscription(final String groupId, final Integer partition, final Collection<String> topics, final AutoOffsetReset autoOffsetReset) { |
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.
Very minor, but I recommend placing partition after topics to align with general hierarchy:
| public Subscription(final String groupId, final Integer partition, final Collection<String> topics, final AutoOffsetReset autoOffsetReset) { | |
| public Subscription(final String groupId, final Collection<String> topics, final Integer partition, final AutoOffsetReset autoOffsetReset) { |
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| import static org.mockito.Mockito.mock; | ||
|
|
||
| public class TestConsumerPartitionsUtil { |
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.
Minor note, the public modifiers on the class and method level are not necessary for JUnit 5. Since this is a new test class, recommend removing them.
| } | ||
|
|
||
| @Test | ||
| public void testNoPartitionAssignments() throws UnknownHostException { |
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.
UnknownHostException does not appear to be thrown in this and other methods.
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.
ConsumerPartitionsUtil.getPartitionsForHost throws it.
|
|
||
| @Test | ||
| public void testNoPartitionAssignments() throws UnknownHostException { | ||
| final Map<String, String> properties = Collections.singletonMap("key", "value"); |
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.
| final Map<String, String> properties = Collections.singletonMap("key", "value"); | |
| final Map<String, String> properties = Map.of("key", "value"); |
| return createPollingContext(context, null); | ||
| } | ||
|
|
||
| private PollingContext createPollingContext(final ProcessContext context, Integer partition) { |
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.
| private PollingContext createPollingContext(final ProcessContext context, Integer partition) { | |
| private PollingContext createPollingContext(final ProcessContext context, final Integer partition) { |
| @Override | ||
| public void onTrigger(final ProcessContext context, final ProcessSession session) { | ||
| final KafkaConsumerService consumerService = getConsumerService(context); | ||
| final PollingContext pollingContext = Optional.ofNullable(consumerServiceToPartitionedPollingContext.get(consumerService)) |
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.
Creating an Optional wrapper is not necessary, and does not add sufficient value for running on every invocation of onTrigger, so I recommend replacing with a standard conditional.
| throw new ProcessException("Illegal Partition Assignment: There are " | ||
| + numAssignedPartitions + " partitions statically assigned using the " + PARTITIONS_PROPERTY_PREFIX + ".* property names," | ||
| + " but the Kafka topic(s) have " + partitionCount + " partitions"); | ||
| } |
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.
Recommend using formatted strings instead of concatenation for this message.
| try { | ||
| assignedPartitions = ConsumerPartitionsUtil.getPartitionsForHost(context.getAllProperties(), getLogger()); | ||
| } catch (final UnknownHostException uhe) { | ||
| throw new ProcessException("Could not determine localhost's hostname", uhe); |
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.
| throw new ProcessException("Could not determine localhost's hostname", uhe); | |
| throw new ProcessException("Failed to resolve local host address", uhe); |
| return !hostnameToPartitionMapping.isEmpty(); | ||
| } | ||
|
|
||
| public static int getPartitionAssignmentCount(final Map<String, String> properties) { |
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.
Recommend moving all public methods before all private methods in this class.
| return null; | ||
| } | ||
|
|
||
| logger.info("Found the following mapping of hosts to partitions: {}", hostnameToPartitionString); |
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.
This seems more appropriate as a debug level message.
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.
@tpalfy Tested with different scenarios, including fewer or more concurrent tasks than partitions, and it works as expected.
Added one minor comment inline and one more thing here: There is some legacy code referencing partition properties in DynamicPropertyValidator. Please clean this up, as the partition dynamic properties are not applied to the Kafka controller service.
...undle/nifi-kafka-processors/src/main/java/org/apache/nifi/kafka/processors/ConsumeKafka.java
Show resolved
Hide resolved
…nstead of just having it commented out)
6269ef2 to
d1da7f6
Compare
turcsanyip
left a 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.
Thanks for the latest changes @tpalfy.
+1 from my side.
|
Thanks for the updates @tpalfy and thanks for the review @turcsanyip, I will follow up and also review the latest changes soon. |
Summary
NIFI-15226
Tracking
Please complete the following tracking steps prior to pull request creation.
Issue Tracking
Pull Request Tracking
NIFI-00000NIFI-00000Pull Request Formatting
mainbranchVerification
Please indicate the verification steps performed prior to pull request creation.
Build
./mvnw clean install -P contrib-checkLicensing
LICENSEandNOTICEfilesDocumentation