Allow getting config options and add multiple overloads for set

This commit is contained in:
Matias Fontanini
2016-06-05 15:08:40 -07:00
parent efd2321828
commit 65a60f1690
11 changed files with 120 additions and 5 deletions

View File

@@ -10,6 +10,7 @@
#include "topic_partition_list.h" #include "topic_partition_list.h"
#include "topic_configuration.h" #include "topic_configuration.h"
#include "clonable_ptr.h" #include "clonable_ptr.h"
#include "configuration_base.h"
namespace cppkafka { namespace cppkafka {
@@ -18,7 +19,7 @@ class Producer;
class Consumer; class Consumer;
class KafkaHandleBase; class KafkaHandleBase;
class Configuration { class Configuration : public ConfigurationBase<Configuration> {
public: public:
using DeliveryReportCallback = std::function<void(Producer& producer, const Message&)>; using DeliveryReportCallback = std::function<void(Producer& producer, const Message&)>;
using OffsetCommitCallback = std::function<void(Consumer& consumer, rd_kafka_resp_err_t, using OffsetCommitCallback = std::function<void(Consumer& consumer, rd_kafka_resp_err_t,
@@ -35,6 +36,8 @@ public:
using StatsCallback = std::function<void(KafkaHandleBase& handle, const std::string& json)>; using StatsCallback = std::function<void(KafkaHandleBase& handle, const std::string& json)>;
using SocketCallback = std::function<int(int domain, int type, int protoco)>; using SocketCallback = std::function<int(int domain, int type, int protoco)>;
using ConfigurationBase<Configuration>::set;
Configuration(); Configuration();
void set(const std::string& name, const std::string& value); void set(const std::string& name, const std::string& value);
@@ -48,6 +51,7 @@ public:
void set_default_topic_configuration(boost::optional<TopicConfiguration> config); void set_default_topic_configuration(boost::optional<TopicConfiguration> config);
rd_kafka_conf_t* get_handle() const; rd_kafka_conf_t* get_handle() const;
std::string get(const std::string& name) const;
const DeliveryReportCallback& get_delivery_report_callback() const; const DeliveryReportCallback& get_delivery_report_callback() const;
const OffsetCommitCallback& get_offset_commit_callback() const; const OffsetCommitCallback& get_offset_commit_callback() const;
const ErrorCallback& get_error_callback() const; const ErrorCallback& get_error_callback() const;

View File

@@ -0,0 +1,33 @@
#ifndef CPPKAFKA_CONFIGURATION_BASE_H
#define CPPKAFKA_CONFIGURATION_BASE_H
#include <string>
namespace cppkafka {
template <typename Concrete>
class ConfigurationBase {
public:
void set(const std::string& name, bool value) {
proxy_set(name, value ? "true" : "false");
}
// Overload for any integral value
template <typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
void set(const std::string& name, T value) {
proxy_set(name, std::to_string(value));
}
void set(const std::string& name, const char* value) {
proxy_set(name, value);
}
private:
void proxy_set(const std::string& name, const std::string& value) {
static_cast<Concrete&>(*this).set(name, value);
}
};
} // cppkafka
#endif // CPPKAFKA_CONFIGURATION_BASE_H

View File

@@ -21,6 +21,11 @@ public:
ConfigException(const std::string& config_name, const std::string& error); ConfigException(const std::string& config_name, const std::string& error);
}; };
class ConfigOptionNotFound : public Exception {
public:
ConfigOptionNotFound(const std::string& config_name);
};
class HandleException : public Exception { class HandleException : public Exception {
public: public:
HandleException(rd_kafka_resp_err_t error_code); HandleException(rd_kafka_resp_err_t error_code);

View File

@@ -5,17 +5,20 @@
#include <functional> #include <functional>
#include <librdkafka/rdkafka.h> #include <librdkafka/rdkafka.h>
#include "clonable_ptr.h" #include "clonable_ptr.h"
#include "configuration_base.h"
namespace cppkafka { namespace cppkafka {
class Topic; class Topic;
class Buffer; class Buffer;
class TopicConfiguration { class TopicConfiguration : public ConfigurationBase<TopicConfiguration> {
public: public:
using PartitionerCallback = std::function<int32_t(const Topic&, const Buffer& key, using PartitionerCallback = std::function<int32_t(const Topic&, const Buffer& key,
int32_t partition_count)>; int32_t partition_count)>;
using ConfigurationBase<TopicConfiguration>::set;
TopicConfiguration(); TopicConfiguration();
void set(const std::string& name, const std::string& value); void set(const std::string& name, const std::string& value);
@@ -26,6 +29,7 @@ public:
const PartitionerCallback& get_partitioner_callback() const; const PartitionerCallback& get_partitioner_callback() const;
rd_kafka_topic_conf_t* get_handle() const; rd_kafka_topic_conf_t* get_handle() const;
std::string get(const std::string& name) const;
private: private:
using HandlePtr = ClonablePtr<rd_kafka_topic_conf_t, using HandlePtr = ClonablePtr<rd_kafka_topic_conf_t,
decltype(&rd_kafka_topic_conf_destroy), decltype(&rd_kafka_topic_conf_destroy),

View File

@@ -1,4 +1,5 @@
#include "configuration.h" #include "configuration.h"
#include <vector>
#include <librdkafka/rdkafka.h> #include <librdkafka/rdkafka.h>
#include "exceptions.h" #include "exceptions.h"
#include "message.h" #include "message.h"
@@ -7,6 +8,7 @@
using std::string; using std::string;
using std::move; using std::move;
using std::vector;
using boost::optional; using boost::optional;
@@ -146,6 +148,17 @@ rd_kafka_conf_t* Configuration::get_handle() const {
return handle_.get(); return handle_.get();
} }
string Configuration::get(const string& name) const {
size_t size = 0;
auto result = rd_kafka_conf_get(handle_.get(), name.data(), nullptr, &size);
if (result != RD_KAFKA_CONF_OK) {
throw ConfigOptionNotFound(name);
}
vector<char> buffer(size);
rd_kafka_conf_get(handle_.get(), name.data(), buffer.data(), &size);
return string(buffer.data());
}
const Configuration::DeliveryReportCallback& Configuration::get_delivery_report_callback() const { const Configuration::DeliveryReportCallback& Configuration::get_delivery_report_callback() const {
return delivery_report_callback_; return delivery_report_callback_;
} }

View File

@@ -22,6 +22,13 @@ ConfigException::ConfigException(const string& config_name, const string& error)
} }
// ConfigOptionNotFound
ConfigOptionNotFound::ConfigOptionNotFound(const string& config_name)
: Exception(config_name + " not found") {
}
// HandleException // HandleException
HandleException::HandleException(rd_kafka_resp_err_t error_code) HandleException::HandleException(rd_kafka_resp_err_t error_code)

View File

@@ -1,10 +1,12 @@
#include "topic_configuration.h" #include "topic_configuration.h"
#include <vector>
#include <librdkafka/rdkafka.h> #include <librdkafka/rdkafka.h>
#include "exceptions.h" #include "exceptions.h"
#include "topic.h" #include "topic.h"
#include "buffer.h" #include "buffer.h"
using std::string; using std::string;
using std::vector;
namespace cppkafka { namespace cppkafka {
@@ -63,6 +65,17 @@ rd_kafka_topic_conf_t* TopicConfiguration::get_handle() const {
return handle_.get(); return handle_.get();
} }
string TopicConfiguration::get(const string& name) const {
size_t size = 0;
auto result = rd_kafka_topic_conf_get(handle_.get(), name.data(), nullptr, &size);
if (result != RD_KAFKA_CONF_OK) {
throw ConfigOptionNotFound(name);
}
vector<char> buffer(size);
rd_kafka_topic_conf_get(handle_.get(), name.data(), buffer.data(), &size);
return string(buffer.data());
}
TopicConfiguration::HandlePtr TopicConfiguration::make_handle(rd_kafka_topic_conf_t* ptr) { TopicConfiguration::HandlePtr TopicConfiguration::make_handle(rd_kafka_topic_conf_t* ptr) {
return HandlePtr(ptr, &rd_kafka_topic_conf_destroy, &rd_kafka_topic_conf_dup); return HandlePtr(ptr, &rd_kafka_topic_conf_destroy, &rd_kafka_topic_conf_dup);
} }

View File

@@ -18,3 +18,4 @@ create_test(consumer)
create_test(producer) create_test(producer)
create_test(kafka_handle_base) create_test(kafka_handle_base)
create_test(topic_partition_list) create_test(topic_partition_list)
create_test(configuration)

View File

@@ -0,0 +1,35 @@
#include <gtest/gtest.h>
#include "cppkafka/configuration.h"
#include "cppkafka/exceptions.h"
using namespace cppkafka;
class ConfigurationTest : public testing::Test {
public:
};
TEST_F(ConfigurationTest, GetSetConfig) {
Configuration config;
config.set("group.id", "foo");
EXPECT_EQ("foo", config.get("group.id"));
EXPECT_THROW(config.get("asd"), ConfigOptionNotFound);
}
TEST_F(ConfigurationTest, GetSetTopicConfig) {
TopicConfiguration config;
config.set("auto.commit.enable", "true");
EXPECT_EQ("true", config.get("auto.commit.enable"));
EXPECT_THROW(config.get("asd"), ConfigOptionNotFound);
}
TEST_F(ConfigurationTest, SetOverloads) {
Configuration config;
config.set("enable.auto.commit", true);
config.set("auto.commit.interval.ms", 100);
EXPECT_EQ("true", config.get("enable.auto.commit"));
EXPECT_EQ("100", config.get("auto.commit.interval.ms"));
}

View File

@@ -93,7 +93,7 @@ public:
Configuration make_consumer_config(const string& group_id = "consumer_test") { Configuration make_consumer_config(const string& group_id = "consumer_test") {
Configuration config; Configuration config;
config.set("metadata.broker.list", KAFKA_TEST_INSTANCE); config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
config.set("enable.auto.commit", "false"); config.set("enable.auto.commit", false);
config.set("group.id", group_id); config.set("group.id", group_id);
return config; return config;
} }

View File

@@ -93,7 +93,7 @@ public:
Configuration make_consumer_config() { Configuration make_consumer_config() {
Configuration config; Configuration config;
config.set("metadata.broker.list", KAFKA_TEST_INSTANCE); config.set("metadata.broker.list", KAFKA_TEST_INSTANCE);
config.set("enable.auto.commit", "false"); config.set("enable.auto.commit", false);
config.set("group.id", "producer_test"); config.set("group.id", "producer_test");
return config; return config;
} }
@@ -268,5 +268,5 @@ TEST_F(ProducerTest, PartitionerCallbackOnDefaultTopicConfig) {
ASSERT_EQ(1, messages.size()); ASSERT_EQ(1, messages.size());
const auto& message = messages[0]; const auto& message = messages[0];
EXPECT_EQ(partition, message.get_partition()); EXPECT_EQ(partition, message.get_partition());
EXPECT_TRUE(callback_called); EXPECT_TRUE(callback_called);
} }