All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.kafka.streams.processor.internals.namedtopology.RemoveNamedTopologyResult Maven / Gradle / Ivy

There is a newer version: 3.8.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.kafka.streams.processor.internals.namedtopology;

import org.apache.kafka.common.KafkaFuture;
import org.apache.kafka.common.internals.KafkaFutureImpl;
import org.apache.kafka.common.utils.LogContext;

import org.slf4j.Logger;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;

public class RemoveNamedTopologyResult {
    private final KafkaFutureImpl removeTopologyFuture;
    private final KafkaFutureImpl resetOffsetsFuture;

    public RemoveNamedTopologyResult(final KafkaFutureImpl removeTopologyFuture) {

        Objects.requireNonNull(removeTopologyFuture);
        this.removeTopologyFuture = removeTopologyFuture;
        this.resetOffsetsFuture = null;
    }

    public RemoveNamedTopologyResult(final KafkaFutureImpl removeTopologyFuture,
                                     final String removedTopology,
                                     final Runnable resetOffsets) {
        Objects.requireNonNull(removeTopologyFuture);
        this.removeTopologyFuture = removeTopologyFuture;
        resetOffsetsFuture = new ResetOffsetsFuture(removedTopology, removeTopologyFuture, resetOffsets);
    }

    public KafkaFuture removeTopologyFuture() {
        return removeTopologyFuture;
    }

    public KafkaFuture resetOffsetsFuture() {
        return resetOffsetsFuture;
    }

    /**
     * @return a {@link KafkaFuture} that completes successfully when all threads on this client have removed the
     * corresponding {@link NamedTopology} and all source topic offsets have been deleted (if applicable). At this
     * point no more of its tasks will be processed by the current client, but there may still be other clients which
     * do. It is only guaranteed that this {@link NamedTopology} has fully stopped processing when all clients have
     * successfully completed their corresponding {@link KafkaFuture}.
     */
    public final KafkaFuture all() {
        if (resetOffsetsFuture == null) {
            return removeTopologyFuture;
        } else {
            return resetOffsetsFuture;
        }
    }

    private static class ResetOffsetsFuture extends KafkaFutureImpl {
        private final Logger log;

        final Runnable resetOffsets;
        final KafkaFutureImpl removeTopologyFuture;

        public ResetOffsetsFuture(final String removedTopology,
                                  final KafkaFutureImpl removeTopologyFuture,
                                  final Runnable resetOffsets) {
            final LogContext logContext = new LogContext(String.format("topology [%s]", removedTopology));
            this.log = logContext.logger(this.getClass());

            this.resetOffsets = resetOffsets;
            this.removeTopologyFuture = removeTopologyFuture;
        }

        @Override
        public Void get() throws ExecutionException {
            final AtomicReference firstError = new AtomicReference<>(null);
            try {
                removeTopologyFuture.get();
            } catch (final InterruptedException | ExecutionException e) {
                final Throwable error = e.getCause() != null ? e.getCause() : e;
                log.error("Removing named topology failed. Offset reset will still be attempted.", error);
                firstError.compareAndSet(e, null);
            }
            try {
                resetOffsets.run();
            } catch (final Throwable e) {
                log.error("Failed to reset offsets, you should do so manually if you want to add new topologies"
                              + "in the future that consume from the same input topics");
                firstError.compareAndSet(e, null);
            }

            if (firstError.get() != null) {
                throw new ExecutionException(firstError.get());
            } else {
                return null;
            }
        }


    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy