package core.framework.api.module;
import core.framework.api.kafka.BulkMessageHandler;
import core.framework.api.kafka.MessageHandler;
import core.framework.api.kafka.MessagePublisher;
import core.framework.api.util.Exceptions;
import core.framework.api.util.Types;
import core.framework.impl.kafka.Kafka;
import core.framework.impl.kafka.KafkaMessagePublisher;
import core.framework.impl.module.ModuleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
/**
* @author neo
*/
public final class KafkaConfig {
private final Logger logger = LoggerFactory.getLogger(KafkaConfig.class);
private final ModuleContext context;
private final String name;
private final State state;
public KafkaConfig(ModuleContext context, String name) {
this.context = context;
this.name = name;
state = context.config.kafka(name);
if (state.kafka == null) {
state.kafka = createKafka(context, name);
}
}
private Kafka createKafka(ModuleContext context, String name) {
if (context.isTest()) {
return context.mockFactory.create(Kafka.class);
} else {
Kafka kafka = new Kafka(name, context.logManager);
context.metrics.add(kafka.producerMetrics);
context.metrics.add(kafka.consumerMetrics);
context.startupHook.add(kafka::initialize);
context.shutdownHook.add(kafka::close);
return kafka;
}
}
public <T> MessagePublisher<T> publish(String topic, Class<T> messageClass) {
if (state.kafka.uri == null) throw Exceptions.error("kafka({}).uri() must be configured first", name == null ? "" : name);
logger.info("create message publisher, topic={}, messageClass={}, beanName={}", topic, messageClass.getTypeName(), name);
state.kafka.validator.register(messageClass);
MessagePublisher<T> publisher = new KafkaMessagePublisher<>(state.kafka.producer(), state.kafka.validator, topic, messageClass, context.logManager);
context.beanFactory.bind(Types.generic(MessagePublisher.class, messageClass), name, publisher);
state.handlerAdded = true;
return publisher;
}
public <T> KafkaConfig subscribe(String topic, Class<T> messageClass, MessageHandler<T> handler) {
return subscribe(topic, messageClass, handler, null);
}
public <T> KafkaConfig subscribe(String topic, Class<T> messageClass, BulkMessageHandler<T> handler) {
return subscribe(topic, messageClass, null, handler);
}
private <T> KafkaConfig subscribe(String topic, Class<T> messageClass, MessageHandler<T> handler, BulkMessageHandler<T> bulkHandler) {
if (state.kafka.uri == null) throw Exceptions.error("kafka({}).uri() must be configured first", name == null ? "" : name);
state.kafka.validator.register(messageClass);
state.kafka.listener().subscribe(topic, messageClass, handler, bulkHandler);
state.handlerAdded = true;
return this;
}
public void poolSize(int poolSize) {
state.kafka.listener().poolSize = poolSize;
}
public void uri(String uri) {
if (state.kafka.uri != null)
throw Exceptions.error("kafka({}).uri() is already configured, uri={}, previous={}", name == null ? "" : name, uri, state.kafka.uri);
state.kafka.uri = uri;
}
public void maxProcessTime(Duration maxProcessTime) {
state.kafka.maxProcessTime = maxProcessTime;
}
public void maxPoll(int maxRecords, int maxBytes) {
if (maxRecords <= 0) throw Exceptions.error("max poll records must be greater than 0, value={}", maxRecords);
if (maxBytes <= 0) throw Exceptions.error("max poll bytes must be greater than 0, value={}", maxBytes);
state.kafka.maxPollRecords = maxRecords;
state.kafka.maxPollBytes = maxBytes;
}
public void minPoll(int minBytes, Duration maxWaitTime) {
if (minBytes <= 0) throw Exceptions.error("min poll bytes must be greater than 0, value={}", minBytes);
if (maxWaitTime == null || maxWaitTime.toMillis() <= 0) throw Exceptions.error("max wait time must be greater than 0, value={}", maxWaitTime);
state.kafka.minPollBytes = minBytes;
state.kafka.minPollMaxWaitTime = maxWaitTime;
}
public static class State {
final String name;
Kafka kafka;
boolean handlerAdded;
public State(String name) {
this.name = name;
}
public void validate() {
if (kafka.uri == null) throw Exceptions.error("kafka({}).uri() must be configured", name == null ? "" : name);
if (!handlerAdded)
throw Exceptions.error("kafka({}) is configured, but no producer/consumer added, please remove unnecessary config", name == null ? "" : name);
}
}
}