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

org.redkalex.mq.pulsar.PulsarMessageConsumer Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkalex.mq.pulsar;

import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import org.apache.pulsar.client.api.*;
import org.redkale.mq.*;

/**
 *
 * @author zhangjx
 */
public class PulsarMessageConsumer extends MessageConsumer implements Runnable {

    protected Properties config;

    protected Thread thread;

    protected CompletableFuture startFuture;

    protected CompletableFuture closeFuture;

    protected Consumer consumer;

    protected boolean reconnecting;

    protected final Object resumeLock = new Object();

    public PulsarMessageConsumer(MessageAgent agent, String[] topics, String group,
        MessageProcessor processor, String servers, Properties consumerConfig) {
        super(agent, topics, group, processor);
        final Properties props = new Properties();
//        props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerid);
//        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.StringDeserializer.class);
//        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, MessageRecordDeserializer.class);
//        props.putAll(consumerConfig);
//        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
//        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
        this.config = props;
    }

    public void retryConnect() {
        if (!this.reconnecting) return;
        try {
            ConsumerBuilder cb = ((PulsarMessageAgent) messageAgent).client.newConsumer(PulsarMessageAgent.MessageRecordSchema.INSTANCE);
            this.consumer = cb.topic(this.topics).subscribe();
        } catch (Exception e) {
            return;
        }
        synchronized (this.resumeLock) {
            this.resumeLock.notifyAll();
        }
    }

    @Override
    public void run() {
        final PulsarMessageAgent agent = (PulsarMessageAgent) messageAgent;
        ConsumerBuilder cb = agent.client.newConsumer(PulsarMessageAgent.MessageRecordSchema.INSTANCE);
        try {
            this.consumer = cb.topic(this.topics).subscribe();
            this.startFuture.complete(null);
            if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, MessageConsumer.class.getSimpleName() + " [" + Arrays.toString(this.topics) + "] startuped");

            Messages pulsarmsgs;
            while (!this.closed) {
                try {
                    pulsarmsgs = this.consumer.batchReceive();
                } catch (Exception ex) {
                    logger.log(Level.WARNING, getClass().getSimpleName() + " poll error", ex);
                    this.consumer.close();
                    this.consumer = null;
                    if (!this.closed) {
                        this.reconnecting = true;
                        ((PulsarMessageAgent) messageAgent).startReconnect();
                        synchronized (resumeLock) {
                            resumeLock.wait();
                        }
                    }
                    continue;
                }
                if (this.reconnecting) this.reconnecting = false;
                if (pulsarmsgs == null || pulsarmsgs.size() < 1) continue;
                final Messages localmsg = pulsarmsgs;
                this.consumer.acknowledgeAsync(pulsarmsgs).whenComplete((r, exp) -> {
                    if (exp != null) logger.log(Level.SEVERE, Arrays.toString(this.topics) + " consumer error: " + localmsg, exp);
                });
                MessageRecord msg = null;
                try {
                    processor.begin(pulsarmsgs.size());
                    for (Message mmr : pulsarmsgs) {
                        msg = mmr.getValue();
                        processor.process(msg, null);
                    }
                    processor.commit();
                } catch (Throwable e) {
                    logger.log(Level.SEVERE, MessageProcessor.class.getSimpleName() + " process " + msg + " error", e);
                }
            }
            if (this.consumer != null) this.consumer.close();
            if (this.closeFuture != null) {
                this.closeFuture.complete(null);
                if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, MessageConsumer.class.getSimpleName() + " [" + Arrays.toString(this.topics) + "] shutdowned");
            }
        } catch (Throwable t) {
            if (this.closeFuture != null && !this.closeFuture.isDone()) {
                this.closeFuture.complete(null);
                if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, MessageConsumer.class.getSimpleName() + " [" + Arrays.toString(this.topics) + "] shutdowned");
            }
            logger.log(Level.SEVERE, MessageConsumer.class.getSimpleName() + "(" + Arrays.toString(this.topics) + ") occur error", t);
        }
    }

    @Override
    public synchronized CompletableFuture startup() {
        if (this.startFuture != null) return this.startFuture;
        this.thread = new Thread(this);
        this.thread.setName("MQ-" + consumerid + "-Thread");
        this.startFuture = new CompletableFuture<>();
        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, MessageConsumer.class.getSimpleName() + " [" + Arrays.toString(this.topics) + "] startuping");
        this.thread.start();
        return this.startFuture;
    }

    @Override
    public synchronized CompletableFuture shutdown() {
        if (this.consumer == null) return CompletableFuture.completedFuture(null);
        if (this.closeFuture != null) return this.closeFuture;
        this.closeFuture = new CompletableFuture<>();
        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, MessageConsumer.class.getSimpleName() + " [" + Arrays.toString(this.topics) + "] shutdownling");
        this.closed = true;
        synchronized (resumeLock) {
            resumeLock.notifyAll();
        }
        return this.closeFuture;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy