Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/streams/developer-guide/config-streams.html
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,10 @@ <h4><a class="toc-backref" href="#id5">bootstrap.servers</a><a class="headerlink
<td>100 milliseconds</td>
</tr>
<tr class="row-even"><td>replication.factor</td>
<td>High</td>
<td>Medium</td>
<td colspan="2">The replication factor for changelog topics and repartition topics created by the application.
If your broker cluster is on version 2.4 or newer, you can set -1 to use the broker default replication factor.</td>
<td>1</td>
The default of <code>-1</code> (meaning: use broker default replication factor) requires broker version 2.4 or newer.</td>
<td>-1</td>
</tr>
<tr class="row-even"><td>retry.backoff.ms</td>
<td>Medium</td>
Expand Down
7 changes: 6 additions & 1 deletion docs/streams/upgrade-guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,12 @@ <h3><a id="streams_api_changes_300" href="#streams_api_changes_300">Streams API
<li>Connect-json: As of Kafka Streams no longer has a compile time dependency on "connect:json" module (<a href="https://issues.apache.org/jira/browse/KAFKA-5146">KAFKA-5146</a>).
Projects that were relying on this transitive dependency will have to explicitly declare it.</li>
</ul>

<p>
The default value for configuration parameter <code>replication.factor</code> was changed to <code>-1</code>
(meaning: use broker default replication factor).
The <code>replication.factor</code> value of <code>-1</code> requires broker version 2.4 or newer.
</p>

<h3><a id="streams_api_changes_280" href="#streams_api_changes_280">Streams API changes in 2.8.0</a></h3>
<p>
We extended <code>StreamJoined</code> to include the options <code>withLoggingEnabled()</code> and <code>withLoggingDisabled()</code> in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,8 @@ public class StreamsConfig extends AbstractConfig {
/** {@code replication.factor} */
@SuppressWarnings("WeakerAccess")
public static final String REPLICATION_FACTOR_CONFIG = "replication.factor";
private static final String REPLICATION_FACTOR_DOC = "The replication factor for change log topics and repartition topics created by the stream processing application." +
" If your broker cluster is on version 2.4 or newer, you can set -1 to use the broker default replication factor.";
private static final String REPLICATION_FACTOR_DOC = "The replication factor for change log topics and repartition topics created by the stream processing application."
+ " The default of <code>-1</code> (meaning: use broker default replication factor) requires broker version 2.4 or newer";

/** {@code request.timeout.ms} */
@SuppressWarnings("WeakerAccess")
Expand Down Expand Up @@ -593,11 +593,6 @@ public class StreamsConfig extends AbstractConfig {
Type.LIST,
Importance.HIGH,
CommonClientConfigs.BOOTSTRAP_SERVERS_DOC)
.define(REPLICATION_FACTOR_CONFIG,
Type.INT,
1,
Importance.HIGH,
REPLICATION_FACTOR_DOC)
.define(STATE_DIR_CONFIG,
Type.STRING,
System.getProperty("java.io.tmpdir") + File.separator + "kafka-streams",
Expand Down Expand Up @@ -685,6 +680,11 @@ public class StreamsConfig extends AbstractConfig {
in(AT_LEAST_ONCE, EXACTLY_ONCE, EXACTLY_ONCE_BETA),
Importance.MEDIUM,
PROCESSING_GUARANTEE_DOC)
.define(REPLICATION_FACTOR_CONFIG,
Type.INT,
-1,
Importance.MEDIUM,
REPLICATION_FACTOR_DOC)
.define(SECURITY_PROTOCOL_CONFIG,
Type.STRING,
CommonClientConfigs.DEFAULT_SECURITY_PROTOCOL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.TopicExistsException;
import org.apache.kafka.common.errors.UnknownTopicOrPartitionException;
import org.apache.kafka.common.errors.UnsupportedVersionException;
import org.apache.kafka.common.serialization.ByteArrayDeserializer;
import org.apache.kafka.common.utils.LogContext;
import org.apache.kafka.common.utils.Time;
Expand Down Expand Up @@ -439,13 +440,34 @@ public Set<String> makeReady(final Map<String, InternalTopicConfig> topics) {
final Throwable cause = executionException.getCause();
if (cause instanceof TopicExistsException) {
// This topic didn't exist earlier or its leader not known before; just retain it for next round of validation.
log.info("Could not create topic {}. Topic is probably marked for deletion (number of partitions is unknown).\n" +
"Will retry to create this topic in {} ms (to let broker finish async delete operation first).\n" +
"Error message was: {}", topicName, retryBackOffMs, cause.toString());
log.info(
"Could not create topic {}. Topic is probably marked for deletion (number of partitions is unknown).\n"
+
"Will retry to create this topic in {} ms (to let broker finish async delete operation first).\n"
+
"Error message was: {}", topicName, retryBackOffMs,
cause.toString());
} else {
log.error("Unexpected error during topic creation for {}.\n" +
"Error message was: {}", topicName, cause.toString());
throw new StreamsException(String.format("Could not create topic %s.", topicName), cause);

if (cause instanceof UnsupportedVersionException) {
final String errorMessage = cause.getMessage();
if (errorMessage != null &&
errorMessage.startsWith("Creating topics with default partitions/replication factor are only supported in CreateTopicRequest version 4+")) {

throw new StreamsException(String.format(
Comment thread
ableegoldman marked this conversation as resolved.
"Could not create topic %s, because brokers don't support configuration replication.factor=-1."
+ " You can change the replication.factor config or upgrade your brokers to version 2.4 or newer to avoid this error.",
topicName)
);
}
} else {
throw new StreamsException(
String.format("Could not create topic %s.", topicName),
cause
);
}
}
} catch (final TimeoutException retriableException) {
log.error("Creating topic {} timed out.\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
*/
package org.apache.kafka.streams.processor.internals;

import java.util.Collection;

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.

nit: import in the wrong place

import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.admin.Config;
import org.apache.kafka.clients.admin.ConfigEntry;
import org.apache.kafka.clients.admin.CreateTopicsOptions;
import org.apache.kafka.clients.admin.CreateTopicsResult;
import org.apache.kafka.clients.admin.CreateTopicsResult.TopicMetadataAndConfig;
import org.apache.kafka.clients.admin.DeleteTopicsResult;
Expand All @@ -40,7 +42,13 @@
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.TopicExistsException;
import org.apache.kafka.common.errors.UnknownTopicOrPartitionException;
import org.apache.kafka.common.errors.UnsupportedVersionException;
import org.apache.kafka.common.internals.KafkaFutureImpl;
import org.apache.kafka.common.message.CreateTopicsRequestData;
import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableReplicaAssignmentCollection;
import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopic;
import org.apache.kafka.common.message.CreateTopicsRequestData.CreatableTopicCollection;
import org.apache.kafka.common.requests.CreateTopicsRequest;
import org.apache.kafka.common.utils.MockTime;
import org.apache.kafka.common.utils.Time;
import org.apache.kafka.streams.StreamsConfig;
Expand Down Expand Up @@ -222,6 +230,55 @@ private void shouldRetryCreateTopicWhenRetriableExceptionIsThrown(final Exceptio
));
}

@Test
public void shouldThrowInformativeExceptionForOlderBrokers() {
final AdminClient admin = new MockAdminClient() {
@Override
public CreateTopicsResult createTopics(final Collection<NewTopic> newTopics,
final CreateTopicsOptions options) {
final CreatableTopic topicToBeCreated = new CreatableTopic();
topicToBeCreated.setAssignments(new CreatableReplicaAssignmentCollection());
topicToBeCreated.setNumPartitions((short) 1);
// set unsupported replication factor for older brokers
topicToBeCreated.setReplicationFactor((short) -1);

final CreatableTopicCollection topicsToBeCreated = new CreatableTopicCollection();
topicsToBeCreated.add(topicToBeCreated);

try {
new CreateTopicsRequest.Builder(
new CreateTopicsRequestData()
.setTopics(topicsToBeCreated)
.setTimeoutMs(0)
.setValidateOnly(options.shouldValidateOnly()))
.build((short) 3); // pass in old unsupported request version for old brokers

throw new IllegalStateException("Building CreateTopicRequest should have thrown.");
} catch (final UnsupportedVersionException expected) {
final KafkaFutureImpl<TopicMetadataAndConfig> future = new KafkaFutureImpl<>();
future.completeExceptionally(expected);

return new CreateTopicsResult(Collections.singletonMap(topic1, future)) { };
}
}
};

final StreamsConfig streamsConfig = new StreamsConfig(config);
final InternalTopicManager topicManager = new InternalTopicManager(Time.SYSTEM, admin, streamsConfig);

final InternalTopicConfig topicConfig = new RepartitionTopicConfig(topic1, Collections.emptyMap());
topicConfig.setNumberOfPartitions(1);

final StreamsException exception = assertThrows(
StreamsException.class,
() -> topicManager.makeReady(Collections.singletonMap(topic1, topicConfig))
);
assertThat(
exception.getMessage(),
equalTo("Could not create topic " + topic1 + ", because brokers don't support configuration replication.factor=-1."
+ " You can change the replication.factor config or upgrade your brokers to version 2.4 or newer to avoid this error."));
}

@Test
public void shouldThrowTimeoutExceptionIfTopicExistsDuringSetup() {
setupTopicInMockAdminClient(topic1, Collections.emptyMap());
Expand Down