
com.zaradai.gluon.kafka.AbstractKafkaEventAdaptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gluon-core Show documentation
Show all versions of gluon-core Show documentation
Gluon - Core micro services implementation.
The newest version!
/**
* Copyright 2017 Zaradai
*
* Licensed 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 com.zaradai.gluon.kafka;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.AbstractExecutionThreadService;
import com.zaradai.gluon.codecs.Codec;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.WakeupException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
abstract class AbstractKafkaEventAdaptor extends AbstractExecutionThreadService {
static final String REQUEST_TOPIC = "gluon-req";
static final String REPLY_TOPIC = "gluon-rep";
private static final Logger LOG = LoggerFactory.getLogger(AbstractKafkaEventAdaptor.class);
private final EventBus eventBus;
private final Codec codec;
private final KafkaConfig config;
private final KafkaProducer producer;
private final KafkaConsumer consumer;
AbstractKafkaEventAdaptor(EventBus eventBus, Codec codec, KafkaConfig config, ProducerFactory producerFactory, ConsumerFactory consumerFactory) {
checkNotNull(eventBus, "Invalid event bus");
checkNotNull(codec, "Invalid Codec");
checkNotNull(config, "Invalid Kafka config");
checkNotNull(config.getProducerConfig(), "Invalid Kafka producer config");
checkNotNull(config.getConsumerConfig(), "Invalid Kafka consumer config");
checkNotNull(producerFactory, "Invalid producer factory");
checkNotNull(consumerFactory, "Invalid consumer factory");
this.eventBus = eventBus;
this.codec = codec;
this.config = config;
producer = producerFactory.create(config.getProducerConfig());
consumer = consumerFactory.create(config.getConsumerConfig());
}
protected abstract Collection getSubscriptionTopics();
protected abstract String getSendTopic();
void handleSendError(Throwable t) {
LOG.warn("Error sending message", t);
}
void handleDecodeError(Throwable t) {
LOG.warn("Unable to decode message", t);
}
@Override
protected void startUp() throws Exception {
eventBus.register(this);
setupConsumer();
}
private void setupConsumer() {
consumer.subscribe(getSubscriptionTopics());
// try and connect
consumer.poll(0);
for (TopicPartition topicPartition : consumer.assignment()) {
LOG.info("Assigned: {}", topicPartition);
}
}
@Override
protected void shutDown() throws Exception {
eventBus.unregister(this);
producer.close();
}
void send(Object msg) {
checkNotNull(msg, "Invalid msg");
ProducerRecord record = new ProducerRecord<>(getSendTopic(), codec.encode(msg));
producer.send(record, this::onSent);
}
void onSent(RecordMetadata recordMetadata, Exception e) {
if (e != null) {
handleSendError(e);
} else {
LOG.debug("Sent: {}", recordMetadata);
}
}
@Override
protected void run() throws Exception {
long poll = config.getConsumerConfig().getPollPeriod();
while (isRunning()) {
ConsumerRecords records = read(poll);
for (ConsumerRecord record : records) {
try {
Object received = codec.decode(record.value());
eventBus.post(received);
LOG.debug("Published: {}", received);
} catch (Throwable t) {
handleDecodeError(t);
}
}
}
}
private ConsumerRecords read(long poll) {
ConsumerRecords res = ConsumerRecords.empty();
try {
res = consumer.poll(poll);
} catch (WakeupException we) {
// expected we are being shutdown.
} catch (Exception e) {
LOG.error("Unable to poll kafka", e);
stopAsync();
}
return res;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy