package cgl.iotcloud.transport.kafka;
import cgl.iotcloud.core.api.thrift.TSensorMessage;
import cgl.iotcloud.core.msg.MessageContext;
import cgl.iotcloud.core.transport.Manageable;
import cgl.iotcloud.core.utils.SerializationUtils;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
public class KafkaProducer implements Manageable {
private static Logger LOG = LoggerFactory.getLogger(KafkaProducer.class);
private Producer<byte[], byte []> producer;
private BlockingQueue outQueue;
private String topic;
private String brokerList;
private String serializerClass;
private String partitionClass;
private String requestRequiredAcks;
private boolean run = true;
private String siteId;
public KafkaProducer(BlockingQueue outQueue,
String topic, String brokerList, String serializerClass,
String partitionClass, String requestRequiredAcks, String siteId) {
this.outQueue = outQueue;
this.topic = topic;
this.brokerList = brokerList;
this.serializerClass = serializerClass;
this.partitionClass = partitionClass;
this.requestRequiredAcks = requestRequiredAcks;
this.siteId = siteId;
}
public void start() {
Properties props = new Properties();
props.put("metadata.broker.list", brokerList);
if (serializerClass != null) {
props.put("serializer.class", serializerClass);
}
if (partitionClass != null) {
props.put("partitioner.class", partitionClass);
}
if (requestRequiredAcks != null) {
props.put("request.required.acks", requestRequiredAcks);
}
ProducerConfig config = new ProducerConfig(props);
producer = new Producer<byte[], byte []>(config);
Thread t = new Thread(new Worker());
t.start();
}
public void stop() {
run = false;
}
private class Worker implements Runnable {
@Override
public void run() {
int errorCount = 0;
while (run) {
try {
try {
Object input = outQueue.take();
if (input instanceof MessageContext) {
MessageContext messageContext = (MessageContext) input;
String sensorId = messageContext.getSensorId();
ByteBuffer buffer = ByteBuffer.wrap(messageContext.getBody());
TSensorMessage message = new TSensorMessage(sensorId, siteId, buffer);
for (Map.Entry<String, Object> e : messageContext.getProperties().entrySet()) {
message.putToProperties(e.getKey(), e.getValue().toString());
}
byte body[] = SerializationUtils.serializeThriftObject(message);
KeyedMessage<byte[], byte []> data = new KeyedMessage<byte[], byte []>(topic,
sensorId.getBytes(), body);
producer.send(data);
} else {
LOG.error("Unexpected message type");
}
} catch (InterruptedException e) {
LOG.error("Exception occurred in the worker listening for consumer changes", e);
}
} catch (Throwable t) {
errorCount++;
if (errorCount <= 3) {
LOG.error("Error occurred " + errorCount + " times.. trying to continue the worker", t);
} else {
LOG.error("Error occurred " + errorCount + " times.. terminating the worker", t);
run = false;
}
}
}
}
}
}