Skip to content

KAFKA-7030: Add configuration to disable message down-conversion (KIP-283)#5192

Merged
hachikuji merged 7 commits into
apache:trunkfrom
dhruvilshah3:conversion-config
Jun 14, 2018
Merged

KAFKA-7030: Add configuration to disable message down-conversion (KIP-283)#5192
hachikuji merged 7 commits into
apache:trunkfrom
dhruvilshah3:conversion-config

Conversation

@dhruvilshah3
Copy link
Copy Markdown
Contributor

Committer Checklist (excluded from commit message)

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

Copy link
Copy Markdown
Contributor

@hachikuji hachikuji left a comment

Choose a reason for hiding this comment

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

Thanks, left a few comments.

val fetchRequest = FetchRequest.Builder.forConsumer(Int.MaxValue, 0, createPartitionMap(1024,
topics)).build(1)
val fetchResponse = sendFetchRequest(topicMap.head._2, fetchRequest)
topics.foreach(tp => assertEquals(Errors.UNSUPPORTED_VERSION, fetchResponse.responseData().get(tp).error))
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.

This assertion is satisfied even if topics doesn't contain all the expected topics. Similarly below.

"exceeds this threshold. This configuration is ignored if message.timestamp.type=LogAppendTime.";

public static final String MESSAGE_DOWNCONVERSION_ENABLE_CONFIG = "message.downconversion.enable";
public static final String MESSAGE_DOWNCONVERSION_ENABLE_DOC = "This configuration controls whether down-conversion of message formats is enabled to satisfy consume requests.";
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.

We should mention the impact of this config on old clients.

// For fetch requests from clients, check if down-conversion is disabled for the particular partition
if (!fetchRequest.isFromFollower && downConvertMagic.isDefined && !replicaManager.messageDownConversionEnabled(tp).getOrElse(true)) {
trace(s"Conversion to message format ${downConvertMagic.get} is disabled for partition $tp. Sending unsupported version response to $clientId.")
new FetchResponse.PartitionData(Errors.UNSUPPORTED_VERSION, FetchResponse.INVALID_HIGHWATERMARK,
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.

Could we use errorResponse?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, no. errorResponse returns FetchResponse.PartitionData[Records] but we want FetchResponse.PartitionData[BaseRecords] here.

Copy link
Copy Markdown
Contributor

@hachikuji hachikuji Jun 13, 2018

Choose a reason for hiding this comment

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

Found the incantation to make this work:

    def errorResponse[T >: MemoryRecords <: BaseRecords](error: Errors): FetchResponse.PartitionData[T] = {
      new FetchResponse.PartitionData[T](error, FetchResponse.INVALID_HIGHWATERMARK, FetchResponse.INVALID_LAST_STABLE_OFFSET,
        FetchResponse.INVALID_LOG_START_OFFSET, null, MemoryRecords.EMPTY)
    }

This says that T is a supertype of MemoryRecords and a subtype of BaseRecords. Since Records and BaseRecords both satisfy this bound, it works. I already did this locally, so I'll just push to this branch and merge.

}
}.getOrElse(unconvertedRecords)
// For fetch requests from clients, check if down-conversion is disabled for the particular partition
if (!fetchRequest.isFromFollower && downConvertMagic.isDefined && !replicaManager.messageDownConversionEnabled(tp).getOrElse(true)) {
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.

It's a little vexing we have to hit ReplicaManager a second time and repeat the same logic to extract the config. What if we just exposed an API to get the LogConfig directly for a partition?

}

def convertRecords(tp: TopicPartition, unconvertedRecords: Records): BaseRecords = {
def convertFetchedData(tp: TopicPartition,
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.

Perhaps we should call this maybeConvertFetchedData since the conversion may or may not happen depending on whether it is needed and permitted.

}
}

def convertRecords(tp: TopicPartition, unconvertedRecords: Records, downConvertMagic: Option[Byte]): BaseRecords = {
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: This method is a little odd since the conversion only happens if downConvertMagic is not None. It seems a little more natural to move the map to the caller. Since we're not hiding much, I'd probably just suggest inlining it below.

}.toMap
}

private def createPartitionMap(maxPartitionBytes: Int, topicPartitions: Seq[TopicPartition],
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.

Seems like we're borrowing some code from FetchTest. Would it make sense to extend it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Probably wouldn't make sense to extend it. I tried extracting some logic into a utility class but looks like it needs some amount of refactoring.


@Test
def testV1FetchWithDownConversionDisabled(): Unit = {
initProducer()
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.

You can do this in a @Before method.

Copy link
Copy Markdown
Contributor

@hachikuji hachikuji left a comment

Choose a reason for hiding this comment

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

Thanks, left a couple additional comments.

"implement the <code>org.apache.kafka.server.policy.CreateTopicPolicy</code> interface."
val AlterConfigPolicyClassNameDoc = "The alter configs policy class that should be used for validation. The class should " +
"implement the <code>org.apache.kafka.server.policy.AlterConfigPolicy</code> interface."
val LogMessageDownConversionEnableDoc = "This configuration controls whether down-conversion of message formats is enabled to satisfy consume requests."
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.

Seems not ideal to have this documentation in two places. I know you are just following the current pattern, but if we don't actually have any difference to communicate, perhaps we should just refer to the documentation in TopicConfig?

}

@Test
def testV1FetchFromReplica(): Unit = {
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.

I think the point of this test is to ensure that the downconversion config does not apply to replicas? Probably worth spelling this out. Also, I'm wondering if we should mention this in the config documentation?

}.getOrElse(unconvertedRecords)
// For fetch requests from clients, check if down-conversion is disabled for the particular partition
if (downConvertMagic.isDefined && !fetchRequest.isFromFollower &&
!logConfig.map(_.messageDownConversionEnable.booleanValue()).getOrElse(true)) {
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.

I think this can be simplified: !logConfig.forall(_.messageDownConversionEnable)?

@hachikuji hachikuji force-pushed the conversion-config branch from 72d8db0 to 248d13e Compare June 13, 2018 23:14
Copy link
Copy Markdown
Contributor

@hachikuji hachikuji left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the patch!

@hachikuji hachikuji merged commit 9a71bfb into apache:trunk Jun 14, 2018
hachikuji pushed a commit that referenced this pull request Jun 14, 2018
…-283) (#5192)

Add support for the topic-level `message.downconversion.enable` config as part of KIP-283.
@dhruvilshah3 dhruvilshah3 deleted the conversion-config branch June 14, 2018 06:38
ying-zheng pushed a commit to ying-zheng/kafka that referenced this pull request Jul 6, 2018
…-283) (apache#5192)

Add support for the topic-level `message.downconversion.enable` config as part of KIP-283.
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.

2 participants