|
12 | 12 | #include <cassert> |
13 | 13 | #include <chrono> |
14 | 14 | #include <functional> |
| 15 | +#include <iterator> |
15 | 16 | #include <memory> |
16 | 17 |
|
17 | 18 |
|
@@ -173,6 +174,17 @@ class KafkaConsumer: public KafkaClient |
173 | 174 | */ |
174 | 175 | std::map<TopicPartition, Offset> endOffsets(const TopicPartitions& tps) const { return getOffsets(tps, false); } |
175 | 176 |
|
| 177 | + /** |
| 178 | + * Get the offsets for the given partitions by time-point. |
| 179 | + * Throws KafkaException with errors: |
| 180 | + * - RD_KAFKA_RESP_ERR__TIMED_OUT: Not all offsets could be fetched in time. |
| 181 | + * - RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION: All partitions are unknown. |
| 182 | + * - RD_KAFKA_RESP_ERR__LEADER_NOT_AVAILABLE: Unable to query leaders from the given partitions. |
| 183 | + */ |
| 184 | + std::map<TopicPartition, Offset> offsetsForTime(const TopicPartitions& tps, |
| 185 | + std::chrono::time_point<std::chrono::system_clock> timepoint, |
| 186 | + std::chrono::milliseconds timeout = std::chrono::milliseconds(DEFAULT_QUERY_TIMEOUT_MS)) const; |
| 187 | + |
176 | 188 | /** |
177 | 189 | * Get the last committed offset for the given partition (whether the commit happened by this process or another).This offset will be used as the position for the consumer in the event of a failure. |
178 | 190 | * This call will block to do a remote call to get the latest committed offsets from the server. |
@@ -229,8 +241,15 @@ class KafkaConsumer: public KafkaClient |
229 | 241 | static const constexpr char* ENABLE_AUTO_COMMIT = "enable.auto.commit"; |
230 | 242 | static const constexpr char* AUTO_COMMIT_INTERVAL_MS = "auto.commit.interval.ms"; |
231 | 243 |
|
232 | | - static constexpr int DEFAULT_SEEK_TIMEOUT_MS = 10000; |
233 | | - static constexpr int SEEK_RETRY_INTERVAL_MS = 5000; |
| 244 | +#if __cplusplus >= 201703L |
| 245 | + static constexpr int DEFAULT_QUERY_TIMEOUT_MS = 10000; |
| 246 | + static constexpr int DEFAULT_SEEK_TIMEOUT_MS = 10000; |
| 247 | + static constexpr int SEEK_RETRY_INTERVAL_MS = 5000; |
| 248 | +#else |
| 249 | + enum { DEFAULT_QUERY_TIMEOUT_MS = 10000 }; |
| 250 | + enum { DEFAULT_SEEK_TIMEOUT_MS = 10000 }; |
| 251 | + enum { SEEK_RETRY_INTERVAL_MS = 5000 }; |
| 252 | +#endif |
234 | 253 |
|
235 | 254 | const OffsetCommitOption _offsetCommitOption; |
236 | 255 |
|
@@ -512,6 +531,38 @@ KafkaConsumer::position(const TopicPartition& tp) const |
512 | 531 | return rk_tp->elems[0].offset; |
513 | 532 | } |
514 | 533 |
|
| 534 | +inline std::map<TopicPartition, Offset> |
| 535 | +KafkaConsumer::offsetsForTime(const TopicPartitions& tps, |
| 536 | + std::chrono::time_point<std::chrono::system_clock> timepoint, |
| 537 | + std::chrono::milliseconds timeout) const |
| 538 | +{ |
| 539 | + if (tps.empty()) return TopicPartitionOffsets(); |
| 540 | + |
| 541 | + auto msSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(timepoint.time_since_epoch()).count(); |
| 542 | + |
| 543 | + auto rk_tpos = rd_kafka_topic_partition_list_unique_ptr(createRkTopicPartitionList(tps)); |
| 544 | + |
| 545 | + for (int i = 0; i < rk_tpos->cnt; ++i) |
| 546 | + { |
| 547 | + rd_kafka_topic_partition_t& rk_tp = rk_tpos->elems[i]; |
| 548 | + // Here the `msSinceEpoch` would be overridden by the offset result (after called by `rd_kafka_offsets_for_times`) |
| 549 | + rk_tp.offset = msSinceEpoch; |
| 550 | + } |
| 551 | + |
| 552 | + rd_kafka_resp_err_t err = rd_kafka_offsets_for_times(getClientHandle(), rk_tpos.get(), timeout.count()); |
| 553 | + KAFKA_THROW_IF_WITH_ERROR(err); |
| 554 | + |
| 555 | + auto results = getTopicPartitionOffsets(rk_tpos.get()); |
| 556 | + |
| 557 | + // Remove invalid results (which are not updated with an valid offset) |
| 558 | + for (auto it = results.begin(); it != results.end(); ) |
| 559 | + { |
| 560 | + it = ((it->second == msSinceEpoch) ? results.erase(it) : std::next(it)); |
| 561 | + } |
| 562 | + |
| 563 | + return results; |
| 564 | +} |
| 565 | + |
515 | 566 | inline std::map<TopicPartition, Offset> |
516 | 567 | KafkaConsumer::getOffsets(const TopicPartitions& tps, bool atBeginning) const |
517 | 568 | { |
|
0 commit comments