Search in sources :

Example 36 with StreamsException

use of org.apache.kafka.streams.errors.StreamsException in project apache-kafka-on-k8s by banzaicloud.

the class InternalTopicManager method makeReady.

/**
 * Prepares a set of given internal topics.
 *
 * If a topic does not exist creates a new topic.
 * If a topic with the correct number of partitions exists ignores it.
 * If a topic exists already but has different number of partitions we fail and throw exception requesting user to reset the app before restarting again.
 */
public void makeReady(final Map<String, InternalTopicConfig> topics) {
    final Map<String, Integer> existingTopicPartitions = getNumPartitions(topics.keySet());
    final Set<InternalTopicConfig> topicsToBeCreated = validateTopicPartitions(topics.values(), existingTopicPartitions);
    if (topicsToBeCreated.size() > 0) {
        final Set<NewTopic> newTopics = new HashSet<>();
        for (final InternalTopicConfig internalTopicConfig : topicsToBeCreated) {
            final Map<String, String> topicConfig = internalTopicConfig.getProperties(defaultTopicConfigs, windowChangeLogAdditionalRetention);
            log.debug("Going to create topic {} with {} partitions and config {}.", internalTopicConfig.name(), internalTopicConfig.numberOfPartitions(), topicConfig);
            newTopics.add(new NewTopic(internalTopicConfig.name(), internalTopicConfig.numberOfPartitions(), replicationFactor).configs(topicConfig));
        }
        int remainingRetries = retries;
        boolean retry;
        do {
            retry = false;
            final CreateTopicsResult createTopicsResult = adminClient.createTopics(newTopics);
            final Set<String> createTopicNames = new HashSet<>();
            for (final Map.Entry<String, KafkaFuture<Void>> createTopicResult : createTopicsResult.values().entrySet()) {
                try {
                    createTopicResult.getValue().get();
                    createTopicNames.add(createTopicResult.getKey());
                } catch (final ExecutionException couldNotCreateTopic) {
                    final Throwable cause = couldNotCreateTopic.getCause();
                    final String topicName = createTopicResult.getKey();
                    if (cause instanceof TimeoutException) {
                        retry = true;
                        log.debug("Could not get number of partitions for topic {} due to timeout. " + "Will try again (remaining retries {}).", topicName, remainingRetries - 1);
                    } else if (cause instanceof TopicExistsException) {
                        createTopicNames.add(createTopicResult.getKey());
                        log.info(String.format("Topic %s exist already: %s", topicName, couldNotCreateTopic.getMessage()));
                    } else {
                        throw new StreamsException(String.format("Could not create topic %s.", topicName), couldNotCreateTopic);
                    }
                } catch (final InterruptedException fatalException) {
                    Thread.currentThread().interrupt();
                    log.error(INTERRUPTED_ERROR_MESSAGE, fatalException);
                    throw new IllegalStateException(INTERRUPTED_ERROR_MESSAGE, fatalException);
                }
            }
            if (retry) {
                final Iterator<NewTopic> it = newTopics.iterator();
                while (it.hasNext()) {
                    if (createTopicNames.contains(it.next().name())) {
                        it.remove();
                    }
                }
                continue;
            }
            return;
        } while (remainingRetries-- > 0);
        final String timeoutAndRetryError = "Could not create topics. " + "This can happen if the Kafka cluster is temporary not available. " + "You can increase admin client config `retries` to be resilient against this error.";
        log.error(timeoutAndRetryError);
        throw new StreamsException(timeoutAndRetryError);
    }
}
Also used : KafkaFuture(org.apache.kafka.common.KafkaFuture) StreamsException(org.apache.kafka.streams.errors.StreamsException) TopicExistsException(org.apache.kafka.common.errors.TopicExistsException) CreateTopicsResult(org.apache.kafka.clients.admin.CreateTopicsResult) NewTopic(org.apache.kafka.clients.admin.NewTopic) ExecutionException(java.util.concurrent.ExecutionException) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet) TimeoutException(org.apache.kafka.common.errors.TimeoutException)

Example 37 with StreamsException

use of org.apache.kafka.streams.errors.StreamsException in project apache-kafka-on-k8s by banzaicloud.

the class AbstractStateManager method reinitializeStateStoresForPartitions.

public void reinitializeStateStoresForPartitions(final Logger log, final Map<String, StateStore> stateStores, final Map<String, String> storeToChangelogTopic, final Collection<TopicPartition> partitions, final InternalProcessorContext processorContext) {
    final Map<String, String> changelogTopicToStore = inverseOneToOneMap(storeToChangelogTopic);
    final Set<String> storeToBeReinitialized = new HashSet<>();
    final Map<String, StateStore> storesCopy = new HashMap<>(stateStores);
    for (final TopicPartition topicPartition : partitions) {
        checkpointableOffsets.remove(topicPartition);
        storeToBeReinitialized.add(changelogTopicToStore.get(topicPartition.topic()));
    }
    try {
        checkpoint.write(checkpointableOffsets);
    } catch (final IOException fatalException) {
        log.error("Failed to write offset checkpoint file to {} while re-initializing {}: {}", checkpoint, stateStores, fatalException);
        throw new StreamsException("Failed to reinitialize global store.", fatalException);
    }
    for (final Map.Entry<String, StateStore> entry : storesCopy.entrySet()) {
        final StateStore stateStore = entry.getValue();
        final String storeName = stateStore.name();
        if (storeToBeReinitialized.contains(storeName)) {
            try {
                stateStore.close();
            } catch (final RuntimeException ignoreAndSwallow) {
            /* ignore */
            }
            processorContext.uninitialize();
            stateStores.remove(entry.getKey());
            // store directory as <taskDir>/<storeName> but nests it with an intermediate <taskDir>/rocksdb/<storeName>
            try {
                Utils.delete(new File(baseDir + File.separator + "rocksdb" + File.separator + storeName));
            } catch (final IOException fatalException) {
                log.error("Failed to reinitialize store {}.", storeName, fatalException);
                throw new StreamsException(String.format("Failed to reinitialize store %s.", storeName), fatalException);
            }
            try {
                Utils.delete(new File(baseDir + File.separator + storeName));
            } catch (final IOException fatalException) {
                log.error("Failed to reinitialize store {}.", storeName, fatalException);
                throw new StreamsException(String.format("Failed to reinitialize store %s.", storeName), fatalException);
            }
            stateStore.init(processorContext, stateStore);
        }
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) StreamsException(org.apache.kafka.streams.errors.StreamsException) StateStore(org.apache.kafka.streams.processor.StateStore) IOException(java.io.IOException) TopicPartition(org.apache.kafka.common.TopicPartition) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) File(java.io.File) HashSet(java.util.HashSet)

Example 38 with StreamsException

use of org.apache.kafka.streams.errors.StreamsException in project apache-kafka-on-k8s by banzaicloud.

the class GlobalStateManagerImpl method topicPartitionsForStore.

private List<TopicPartition> topicPartitionsForStore(final StateStore store) {
    final String sourceTopic = topology.storeToChangelogTopic().get(store.name());
    List<PartitionInfo> partitionInfos;
    int attempts = 0;
    while (true) {
        try {
            partitionInfos = globalConsumer.partitionsFor(sourceTopic);
            break;
        } catch (final TimeoutException retryableException) {
            if (++attempts > retries) {
                log.error("Failed to get partitions for topic {} after {} retry attempts due to timeout. " + "The broker may be transiently unavailable at the moment. " + "You can increase the number of retries via configuration parameter `retries`.", sourceTopic, retries, retryableException);
                throw new StreamsException(String.format("Failed to get partitions for topic %s after %d retry attempts due to timeout. " + "The broker may be transiently unavailable at the moment. " + "You can increase the number of retries via configuration parameter `retries`.", sourceTopic, retries), retryableException);
            }
            log.debug("Failed to get partitions for topic {} due to timeout. The broker may be transiently unavailable at the moment. " + "Backing off for {} ms to retry (attempt {} of {})", sourceTopic, retryBackoffMs, attempts, retries, retryableException);
            Utils.sleep(retryBackoffMs);
        }
    }
    if (partitionInfos == null || partitionInfos.isEmpty()) {
        throw new StreamsException(String.format("There are no partitions available for topic %s when initializing global store %s", sourceTopic, store.name()));
    }
    final List<TopicPartition> topicPartitions = new ArrayList<>();
    for (PartitionInfo partition : partitionInfos) {
        topicPartitions.add(new TopicPartition(partition.topic(), partition.partition()));
    }
    return topicPartitions;
}
Also used : TopicPartition(org.apache.kafka.common.TopicPartition) StreamsException(org.apache.kafka.streams.errors.StreamsException) ArrayList(java.util.ArrayList) PartitionInfo(org.apache.kafka.common.PartitionInfo) TimeoutException(org.apache.kafka.common.errors.TimeoutException)

Example 39 with StreamsException

use of org.apache.kafka.streams.errors.StreamsException in project apache-kafka-on-k8s by banzaicloud.

the class GlobalStateManagerImpl method initialize.

@Override
public Set<String> initialize() {
    try {
        if (!stateDirectory.lockGlobalState()) {
            throw new LockException(String.format("Failed to lock the global state directory: %s", baseDir));
        }
    } catch (IOException e) {
        throw new LockException(String.format("Failed to lock the global state directory: %s", baseDir));
    }
    try {
        this.checkpointableOffsets.putAll(checkpoint.read());
    } catch (IOException e) {
        try {
            stateDirectory.unlockGlobalState();
        } catch (IOException e1) {
            log.error("Failed to unlock the global state directory", e);
        }
        throw new StreamsException("Failed to read checkpoints for global state globalStores", e);
    }
    final List<StateStore> stateStores = topology.globalStateStores();
    for (final StateStore stateStore : stateStores) {
        globalStoreNames.add(stateStore.name());
        stateStore.init(processorContext, stateStore);
    }
    return Collections.unmodifiableSet(globalStoreNames);
}
Also used : LockException(org.apache.kafka.streams.errors.LockException) StreamsException(org.apache.kafka.streams.errors.StreamsException) StateStore(org.apache.kafka.streams.processor.StateStore) IOException(java.io.IOException)

Example 40 with StreamsException

use of org.apache.kafka.streams.errors.StreamsException in project apache-kafka-on-k8s by banzaicloud.

the class StoreChangelogReader method initialize.

private void initialize() {
    if (!restoreConsumer.subscription().isEmpty()) {
        throw new StreamsException("Restore consumer should not be subscribed to any topics (" + restoreConsumer.subscription() + ")");
    }
    // first refresh the changelog partition information from brokers, since initialize is only called when
    // the needsInitializing map is not empty, meaning we do not know the metadata for some of them yet
    refreshChangelogInfo();
    Map<TopicPartition, StateRestorer> initializable = new HashMap<>();
    for (Map.Entry<TopicPartition, StateRestorer> entry : needsInitializing.entrySet()) {
        final TopicPartition topicPartition = entry.getKey();
        if (hasPartition(topicPartition)) {
            initializable.put(entry.getKey(), entry.getValue());
        }
    }
    // where we already have all of the data
    try {
        endOffsets.putAll(restoreConsumer.endOffsets(initializable.keySet()));
    } catch (final TimeoutException e) {
        // if timeout exception gets thrown we just give up this time and retry in the next run loop
        log.debug("Could not fetch end offset for {}; will fall back to partition by partition fetching", initializable);
        return;
    }
    final Iterator<TopicPartition> iter = initializable.keySet().iterator();
    while (iter.hasNext()) {
        final TopicPartition topicPartition = iter.next();
        final Long endOffset = endOffsets.get(topicPartition);
        // we add this check just in case
        if (endOffset != null) {
            final StateRestorer restorer = needsInitializing.get(topicPartition);
            if (restorer.checkpoint() >= endOffset) {
                restorer.setRestoredOffset(restorer.checkpoint());
                iter.remove();
            } else if (restorer.offsetLimit() == 0 || endOffset == 0) {
                restorer.setRestoredOffset(0);
                iter.remove();
            } else {
                restorer.setEndingOffset(endOffset);
            }
            needsInitializing.remove(topicPartition);
        } else {
            log.info("End offset cannot be found form the returned metadata; removing this partition from the current run loop");
            iter.remove();
        }
    }
    // set up restorer for those initializable
    if (!initializable.isEmpty()) {
        startRestoration(initializable);
    }
}
Also used : HashMap(java.util.HashMap) TopicPartition(org.apache.kafka.common.TopicPartition) StreamsException(org.apache.kafka.streams.errors.StreamsException) HashMap(java.util.HashMap) Map(java.util.Map) TimeoutException(org.apache.kafka.common.errors.TimeoutException)

Aggregations

StreamsException (org.apache.kafka.streams.errors.StreamsException)186 Test (org.junit.Test)90 KafkaException (org.apache.kafka.common.KafkaException)41 TopicPartition (org.apache.kafka.common.TopicPartition)38 TimeoutException (org.apache.kafka.common.errors.TimeoutException)36 HashMap (java.util.HashMap)27 Map (java.util.Map)25 HashSet (java.util.HashSet)18 Properties (java.util.Properties)17 TaskId (org.apache.kafka.streams.processor.TaskId)14 ConsumerRecord (org.apache.kafka.clients.consumer.ConsumerRecord)13 StreamsConfig (org.apache.kafka.streams.StreamsConfig)12 ArrayList (java.util.ArrayList)11 ExecutionException (java.util.concurrent.ExecutionException)11 TaskMigratedException (org.apache.kafka.streams.errors.TaskMigratedException)11 IOException (java.io.IOException)10 Set (java.util.Set)10 LogContext (org.apache.kafka.common.utils.LogContext)10 MockTime (org.apache.kafka.common.utils.MockTime)10 StateStore (org.apache.kafka.streams.processor.StateStore)10