/**
* Copyright 2016-2017 Sixt GmbH & Co. Autovermietung KG
* 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.sixt.service.framework.kafka.messaging;
import com.google.inject.Inject;
import com.sixt.service.framework.ServiceProperties;
import com.sixt.service.framework.metrics.MetricBuilderFactory;
import io.opentracing.Tracer;
import java.util.Properties;
public class ConsumerFactory {
private final ServiceProperties serviceProperties;
private final TypeDictionary typeDictionary;
private final Tracer tracer;
private final MetricBuilderFactory metricBuilderFactory;
// Stand-alone use without tracing and metrics.
public ConsumerFactory(ServiceProperties serviceProperties, TypeDictionary typeDictionary) {
this(serviceProperties, typeDictionary, null, null);
}
@Inject
public ConsumerFactory(ServiceProperties serviceProperties, TypeDictionary typeDictionary, Tracer tracer, MetricBuilderFactory metricBuilderFactory) {
this.serviceProperties = serviceProperties;
this.typeDictionary = typeDictionary;
this.tracer = tracer;
this.metricBuilderFactory = metricBuilderFactory;
}
// Design note: There is no default for the FailedMessageProcessor because I want users to explicitly think about error handling.
public Consumer defaultInboxConsumer(FailedMessageProcessor failedMessageStrategy) {
String serviceName = serviceProperties.getServiceName();
Topic defaultInbox = Topic.defaultServiceInbox(serviceName);
String consumerGroupId = defaultConsumerGroupId(defaultInbox);
return new Consumer(defaultInbox, consumerGroupId, defaultKafkaConfig(), defaultPartitionProcessorFactory(failedMessageStrategy));
}
public Consumer consumerForTopic(Topic topic, DiscardFailedMessages failedMessageStrategy) {
String consumerGroupId = defaultConsumerGroupId(topic);
return new Consumer(topic, consumerGroupId, defaultKafkaConfig(), defaultPartitionProcessorFactory(failedMessageStrategy));
}
private String defaultConsumerGroupId(Topic topic) {
// default consumer group id consists of topic and service name
return topic + "-" + serviceProperties.getServiceName();
}
private Properties defaultKafkaConfig() {
String kafkaBootstrapServers = serviceProperties.getKafkaServer();
Properties kafkaConfig = new Properties();
kafkaConfig.put("bootstrap.servers", kafkaBootstrapServers);
// The heartbeat is send in the background by the client library itself
kafkaConfig.put("heartbeat.interval.ms", "10000");
kafkaConfig.put("session.timeout.ms", "30000");
// Require explicit commit handling.
kafkaConfig.put("enable.auto.commit", "false");
// If this is a new group, start reading the topic from the beginning.
kafkaConfig.put("auto.offset.reset", "earliest");
// This is the actual timeout for the consumer loop thread calling poll() before Kafka rebalances the group.
kafkaConfig.put("max.poll.interval.ms", 10000);
return kafkaConfig;
}
private PartitionProcessorFactory defaultPartitionProcessorFactory(FailedMessageProcessor failedMessageStrategy) {
PartitionProcessorFactory partitionProcessorFactory = new PartitionProcessorFactory(typeDictionary, failedMessageStrategy, tracer, metricBuilderFactory);
return partitionProcessorFactory;
}
}