Skip to content

Commit 8480cf3

Browse files
committed
Handle (un)assign on consumer mock
1 parent 2034ce5 commit 8480cf3

File tree

4 files changed

+40
-42
lines changed

4 files changed

+40
-42
lines changed

mocking/include/cppkafka/mocking/consumer_mock.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class ConsumerMock : public HandleMock {
2828
~ConsumerMock();
2929

3030
void subscribe(const std::vector<std::string>& topics);
31+
void assign(const std::vector<TopicPartitionMock>& topic_partitions);
32+
void unassign();
3133
void set_opaque(void* opaque);
3234
private:
3335
static uint64_t make_consumer_id();
@@ -49,14 +51,14 @@ class ConsumerMock : public HandleMock {
4951
using TopicPartitionId = std::tuple<std::string, int>;
5052

5153
static TopicPartitionId make_id(const TopicPartitionMock& topic_partition);
52-
void on_assignment(std::vector<TopicPartitionMock>& topic_partitions);
53-
void on_revocation(const std::vector<TopicPartitionMock>& topic_partitions);
54+
void on_assignment(const std::vector<TopicPartitionMock>& topic_partitions);
55+
void on_revocation();
5456
void on_message(const std::string& topic_name, unsigned partition, uint64_t offset,
5557
const KafkaMessageMock* message);
56-
template <typename List>
57-
void handle_rebalance(rd_kafka_resp_err_t type, List& topic_partitions);
58+
void handle_rebalance(rd_kafka_resp_err_t type,
59+
const std::vector<TopicPartitionMock>& topic_partitions);
5860
void handle_assign(const TopicPartitionMock& topic_partition);
59-
void handle_unassign(const TopicPartitionMock& topic_partition);
61+
void handle_unassign();
6062
void fetch_existing_messages(unsigned partition, uint64_t next_offset,
6163
KafkaTopicMock& topic);
6264

mocking/include/cppkafka/mocking/kafka_cluster.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ namespace mocking {
1616

1717
class KafkaCluster {
1818
public:
19-
using AssignmentCallback = std::function<void(std::vector<TopicPartitionMock>&)>;
20-
using RevocationCallback = std::function<void(const std::vector<TopicPartitionMock>&)>;
19+
using AssignmentCallback = std::function<void(const std::vector<TopicPartitionMock>&)>;
20+
using RevocationCallback = std::function<void()>;
2121
using MessageCallback = std::function<void(std::string topic, unsigned partition,
2222
uint64_t offset, const KafkaMessageMock*)>;
2323

@@ -32,8 +32,6 @@ class KafkaCluster {
3232
void create_topic(const std::string& name, unsigned partitions);
3333
bool topic_exists(const std::string& name) const;
3434
void produce(const std::string& topic, unsigned partition, KafkaMessageMock message);
35-
template <typename Functor>
36-
void acquire_topic(const std::string& topic, const Functor& functor);
3735
KafkaTopicMock& get_topic(const std::string& name);
3836
const KafkaTopicMock& get_topic(const std::string& name) const;
3937
void subscribe(const std::string& group_id, uint64_t consumer_id,
@@ -72,19 +70,6 @@ class KafkaCluster {
7270
mutable std::mutex consumer_data_mutex_;
7371
};
7472

75-
template <typename Functor>
76-
void KafkaCluster::acquire_topic(const std::string& topic, const Functor& functor) {
77-
std::unique_lock<std::mutex> lock(topics_mutex_);
78-
auto iter = topics_.find(topic);
79-
if (iter == topics_.end()) {
80-
throw std::runtime_error("Topic " + topic + " doesn't exist");
81-
}
82-
// Unlock and execute callback. We won't remove topics so this is thread safe on a
83-
// cluster level
84-
lock.unlock();
85-
functor(iter->second);
86-
}
87-
8873
} // mocking
8974
} // cppkafka
9075

mocking/src/consumer_mock.cpp

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ using std::bind;
1313
using std::runtime_error;
1414
using std::make_tuple;
1515
using std::tie;
16+
using std::get;
1617
using std::lock_guard;
1718
using std::unique_lock;
1819
using std::mutex;
@@ -47,11 +48,22 @@ void ConsumerMock::subscribe(const vector<string>& topics) {
4748
consumer_id_,
4849
topics,
4950
bind(&ConsumerMock::on_assignment, this, _1),
50-
bind(&ConsumerMock::on_revocation, this, _1),
51+
bind(&ConsumerMock::on_revocation, this),
5152
bind(&ConsumerMock::on_message, this, _1, _2, _3, _4)
5253
);
5354
}
5455

56+
void ConsumerMock::assign(const vector<TopicPartitionMock>& topic_partitions) {
57+
for (const TopicPartitionMock& topic_partition : topic_partitions) {
58+
handle_assign(topic_partition);
59+
}
60+
}
61+
62+
void ConsumerMock::unassign() {
63+
lock_guard<mutex> _(assigned_partitions_mutex_);
64+
assigned_partitions_.clear();
65+
}
66+
5567
void ConsumerMock::set_opaque(void* opaque) {
5668
opaque_ = opaque;
5769
}
@@ -60,18 +72,23 @@ ConsumerMock::TopicPartitionId ConsumerMock::make_id(const TopicPartitionMock& t
6072
return make_tuple(topic_partition.get_topic(), topic_partition.get_partition());
6173
}
6274

63-
void ConsumerMock::on_assignment(vector<TopicPartitionMock>& topic_partitions) {
75+
void ConsumerMock::on_assignment(const vector<TopicPartitionMock>& topic_partitions) {
6476
handle_rebalance(RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS, topic_partitions);
65-
for (const TopicPartitionMock& topic_partition : topic_partitions) {
66-
handle_assign(topic_partition);
67-
}
6877
}
6978

70-
void ConsumerMock::on_revocation(const vector<TopicPartitionMock>& topic_partitions) {
79+
void ConsumerMock::on_revocation() {
80+
// Fetch and reset all assigned topic partitions
81+
vector<TopicPartitionMock> topic_partitions = [&]() {
82+
lock_guard<mutex> _(assigned_partitions_mutex_);
83+
vector<TopicPartitionMock> output;
84+
for (const auto& topic_partition_pair : assigned_partitions_) {
85+
const TopicPartitionId& id = topic_partition_pair.first;
86+
output.emplace_back(get<0>(id), get<1>(id));
87+
}
88+
assigned_partitions_.clear();
89+
return output;
90+
}();
7191
handle_rebalance(RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS, topic_partitions);
72-
for (const TopicPartitionMock& topic_partition : topic_partitions) {
73-
handle_unassign(topic_partition);
74-
}
7592
}
7693

7794
void ConsumerMock::on_message(const string& topic_name, unsigned partition, uint64_t offset,
@@ -91,8 +108,8 @@ void ConsumerMock::on_message(const string& topic_name, unsigned partition, uint
91108
message_queue_condition_.notify_one();
92109
}
93110

94-
template <typename List>
95-
void ConsumerMock::handle_rebalance(rd_kafka_resp_err_t type, List& topic_partitions) {
111+
void ConsumerMock::handle_rebalance(rd_kafka_resp_err_t type,
112+
const vector<TopicPartitionMock>& topic_partitions) {
96113
auto rebalance_callback = config_.get_rebalance_callback();
97114
if (rebalance_callback) {
98115
auto handle = to_rdkafka_handle(topic_partitions);
@@ -115,14 +132,8 @@ void ConsumerMock::handle_assign(const TopicPartitionMock& topic_partition) {
115132

116133
// Fetch any existing messages and push them to the available message queue
117134
auto& cluster = get_cluster();
118-
cluster.acquire_topic(topic_partition.get_topic(), [&](KafkaTopicMock& topic) {
119-
fetch_existing_messages(topic_partition.get_partition(), next_offset, topic);
120-
});
121-
}
122-
123-
void ConsumerMock::handle_unassign(const TopicPartitionMock& topic_partition) {
124-
lock_guard<mutex> _(assigned_partitions_mutex_);
125-
assigned_partitions_.erase(make_id(topic_partition));
135+
KafkaTopicMock& topic = cluster.get_topic(topic_partition.get_topic());
136+
fetch_existing_messages(topic_partition.get_partition(), next_offset, topic);
126137
}
127138

128139
void ConsumerMock::fetch_existing_messages(unsigned partition_index, uint64_t next_offset,

mocking/src/kafka_cluster.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void KafkaCluster::generate_revocations(const TopicConsumersMap& topic_consumers
163163
ConsumerMetadata& consumer = consumer_data_[consumer_id];
164164
// Execute revocation callback and unsubscribe from the partition object
165165
if (!consumer.partitions_assigned.empty()) {
166-
consumer.revocation_callback(consumer.partitions_assigned);
166+
consumer.revocation_callback();
167167
for (const auto& topic_subscription : consumer.subscriptions) {
168168
KafkaTopicMock& topic = *topic_subscription.first;
169169
for (const auto& partition_subscription : topic_subscription.second) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy