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

io.debezium.connector.spanner.task.leader.LowWatermarkStampPublisher Maven / Gradle / Ivy

There is a newer version: 3.0.0.CR1
Show newest version
/*
 * Copyright Debezium Authors.
 *
 * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
 */
package io.debezium.connector.spanner.task.leader;

import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.debezium.connector.spanner.SpannerConnectorConfig;
import io.debezium.connector.spanner.processor.SpannerEventDispatcher;
import io.debezium.connector.spanner.task.TaskSyncContextHolder;

/**
 * Generates watermark update messages to output topics with the latest
 * watermark value
 */
public class LowWatermarkStampPublisher {

    private static final Logger LOGGER = LoggerFactory.getLogger(LowWatermarkStampPublisher.class);

    private final Duration publishInterval;

    private volatile Thread publisherThread;

    private final SpannerEventDispatcher spannerEventDispatcher;
    private final boolean lowWatermarkEnabled;

    private final AtomicBoolean suspendFlag = new AtomicBoolean(false);

    private final Consumer errorHandler;

    private final TaskSyncContextHolder taskSyncContextHolder;

    public LowWatermarkStampPublisher(SpannerConnectorConfig spannerConnectorConfig,
                                      SpannerEventDispatcher spannerEventDispatcher,
                                      Consumer errorHandler,
                                      TaskSyncContextHolder taskSyncContextHolder) {
        this.publishInterval = spannerConnectorConfig.getLowWatermarkStampInterval();
        this.spannerEventDispatcher = spannerEventDispatcher;
        this.lowWatermarkEnabled = spannerConnectorConfig.isLowWatermarkEnabled();
        this.errorHandler = errorHandler;
        this.taskSyncContextHolder = taskSyncContextHolder;
    }

    public void init() {
        if (!lowWatermarkEnabled || this.publisherThread != null) {
            return;
        }
        this.publisherThread = createPublisherThread();
    }

    public void start() {
        if (!lowWatermarkEnabled) {
            return;
        }

        if (publisherThread.getState().equals(Thread.State.NEW)) {
            LOGGER.info("task {}, started publisher thread ", taskSyncContextHolder.get().getTaskUid());
            this.publisherThread.start();
        }

        this.suspendFlag.compareAndSet(true, false);
    }

    public void suspend() {
        this.suspendFlag.set(true);
    }

    public void destroy() throws InterruptedException {
        LOGGER.info("Task {}, Attempting to destroy LowWatermarkStampPublisher", taskSyncContextHolder.get().getTaskUid());
        if (this.publisherThread == null || publisherThread.getState().equals(Thread.State.NEW)) {
            return;
        }
        this.suspendFlag.set(true);

        this.publisherThread.interrupt();

        LOGGER.info("Task {}, Attempting to destroy LowWatermarkStampPublisher with state {}", taskSyncContextHolder.get().getTaskUid(), publisherThread.getState());
        while (this.publisherThread != null) {
        }

        LOGGER.info("Task {}, Successfully destroyed LowWatermarkStampPublisher", taskSyncContextHolder.get().getTaskUid());
    }

    private Thread createPublisherThread() {
        Thread thread = new Thread(() -> {
            try {
                while (!taskSyncContextHolder.get().isInitialized() && !Thread.currentThread().isInterrupted()) {
                }

                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        if (!suspendFlag.get()) {
                            spannerEventDispatcher.publishLowWatermarkStampEvent();
                        }

                        Thread.sleep(publishInterval.toMillis());
                    }
                    catch (InterruptedException e) {
                        LOGGER.info("Task {}, LowWatermarkStampPublisher caught exception", taskSyncContextHolder.get().getTaskUid(), e);
                        Thread.currentThread().interrupt();
                    }
                }
            }
            finally {
                this.publisherThread = null;
            }
        }, "SpannerConnector-LowWatermarkStampPublisher");

        thread.setUncaughtExceptionHandler((t, ex) -> {
            LOGGER.error("LowWatermarkStampPublisher execution error", ex);
            this.publisherThread = null;

            this.errorHandler.accept(ex);
        });

        return thread;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy