|
21 | 21 |
|
22 | 22 | #include "BitSet.h" |
23 | 23 | #include "ClientConnection.h" |
| 24 | +#include "ClientImpl.h" |
24 | 25 | #include "Commands.h" |
| 26 | +#include "HandlerBase.h" |
25 | 27 | #include "LogUtils.h" |
26 | 28 | #include "MessageIdImpl.h" |
27 | 29 |
|
28 | 30 | namespace pulsar { |
29 | 31 |
|
30 | 32 | DECLARE_LOG_OBJECT(); |
31 | 33 |
|
32 | | -inline void sendAck(ClientConnectionPtr cnx, uint64_t consumerId, const MessageId& msgId, |
33 | | - CommandAck_AckType ackType) { |
34 | | - const auto& bitSet = Commands::getMessageIdImpl(msgId)->getBitSet(); |
35 | | - auto cmd = Commands::newAck(consumerId, msgId.ledgerId(), msgId.entryId(), bitSet, ackType, -1); |
36 | | - cnx->sendCommand(cmd); |
37 | | - LOG_DEBUG("ACK request is sent for message - [" << msgId.ledgerId() << ", " << msgId.entryId() << "]"); |
38 | | -} |
39 | | - |
40 | | -bool AckGroupingTracker::doImmediateAck(ClientConnectionWeakPtr connWeakPtr, uint64_t consumerId, |
41 | | - const MessageId& msgId, CommandAck_AckType ackType) { |
42 | | - auto cnx = connWeakPtr.lock(); |
43 | | - if (cnx == nullptr) { |
44 | | - LOG_DEBUG("Connection is not ready, ACK failed for message - [" << msgId.ledgerId() << ", " |
45 | | - << msgId.entryId() << "]"); |
46 | | - return false; |
| 34 | +std::pair<std::shared_ptr<ClientConnection>, uint64_t> AckGroupingTracker::generateAckInfo() const { |
| 35 | + auto handler = handler_.lock(); |
| 36 | + if (!handler) { |
| 37 | + LOG_DEBUG("Reference to the HandlerBase is not valid in generateAckInfo"); |
| 38 | + return std::make_pair(nullptr, 0); |
47 | 39 | } |
48 | | - sendAck(cnx, consumerId, msgId, ackType); |
49 | | - return true; |
50 | | -} |
51 | | - |
52 | | -static std::ostream& operator<<(std::ostream& os, const std::set<MessageId>& msgIds) { |
53 | | - bool first = true; |
54 | | - for (auto&& msgId : msgIds) { |
55 | | - if (first) { |
56 | | - first = false; |
57 | | - } else { |
58 | | - os << ", "; |
| 40 | + auto cnx = handler->getCnx().lock(); |
| 41 | + if (!cnx) { |
| 42 | + LOG_DEBUG("Connection is not ready in generateAckInfo"); |
| 43 | + return std::make_pair(nullptr, 0); |
| 44 | + } |
| 45 | + if (waitResponse_) { |
| 46 | + auto client = client_.lock(); |
| 47 | + if (!client) { |
| 48 | + LOG_DEBUG("Reference to the ClientImpl is not valid in generateAckInfo"); |
| 49 | + return std::make_pair(nullptr, 0); |
59 | 50 | } |
60 | | - os << "[" << msgId << "]"; |
| 51 | + return std::make_pair(cnx, client->newRequestId()); |
| 52 | + } else { |
| 53 | + return std::make_pair(cnx, 0); |
61 | 54 | } |
62 | | - return os; |
63 | 55 | } |
64 | 56 |
|
65 | | -bool AckGroupingTracker::doImmediateAck(ClientConnectionWeakPtr connWeakPtr, uint64_t consumerId, |
66 | | - const std::set<MessageId>& msgIds) { |
67 | | - auto cnx = connWeakPtr.lock(); |
68 | | - if (cnx == nullptr) { |
69 | | - LOG_DEBUG("Connection is not ready, ACK failed."); |
70 | | - return false; |
| 57 | +void AckGroupingTracker::doImmediateAck(ClientConnection& cnx, uint64_t requestId, const MessageId& msgId, |
| 58 | + ResultCallback callback, CommandAck_AckType ackType) { |
| 59 | + const auto& bitSet = Commands::getMessageIdImpl(msgId)->getBitSet(); |
| 60 | + auto cmd = Commands::newAck(consumerId_, msgId.ledgerId(), msgId.entryId(), bitSet, ackType, -1); |
| 61 | + if (waitResponse_) { |
| 62 | + cnx.sendRequestWithId(cmd, requestId).addListener([callback](Result result, const ResponseData&) { |
| 63 | + if (callback) { |
| 64 | + callback(result); |
| 65 | + } |
| 66 | + }); |
| 67 | + } else { |
| 68 | + cnx.sendCommand(cmd); |
| 69 | + callback(ResultOk); |
71 | 70 | } |
| 71 | +} |
| 72 | + |
| 73 | +void AckGroupingTracker::doImmediateAck(ClientConnection& cnx, uint64_t requestId, |
| 74 | + const std::map<MessageId, ResultCallback>& msgIdToCallback) { |
| 75 | + using Callbacks = std::vector<ResultCallback>; |
| 76 | + if (Commands::peerSupportsActiveConsumerListener(cnx.getServerProtocolVersion())) { |
| 77 | + std::set<MessageId> msgIds; |
| 78 | + std::unique_ptr<Callbacks> callbacks{new Callbacks}; |
72 | 79 |
|
73 | | - if (Commands::peerSupportsMultiMessageAcknowledgement(cnx->getServerProtocolVersion())) { |
74 | | - auto cmd = Commands::newMultiMessageAck(consumerId, msgIds); |
75 | | - cnx->sendCommand(cmd); |
76 | | - LOG_DEBUG("ACK request is sent for " << msgIds.size() << " messages: " << msgIds); |
| 80 | + for (auto&& kv : msgIdToCallback) { |
| 81 | + msgIds.emplace(kv.first); |
| 82 | + if (kv.second) { |
| 83 | + callbacks->emplace_back(kv.second); |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + auto cmd = Commands::newMultiMessageAck(consumerId_, msgIds); |
| 88 | + if (waitResponse_) { |
| 89 | + auto rawPtr = callbacks.release(); |
| 90 | + cnx.sendRequestWithId(cmd, requestId).addListener([rawPtr](Result result, const ResponseData&) { |
| 91 | + std::unique_ptr<Callbacks> callbacks{rawPtr}; |
| 92 | + for (auto&& callback : *callbacks) { |
| 93 | + callback(result); |
| 94 | + } |
| 95 | + }); |
| 96 | + } else { |
| 97 | + cnx.sendCommand(cmd); |
| 98 | + for (auto&& callback : *callbacks) { |
| 99 | + callback(ResultOk); |
| 100 | + } |
| 101 | + } |
77 | 102 | } else { |
78 | | - // Broker does not support multi-message ACK, use multiple individual ACKs instead. |
79 | | - for (const auto& msgId : msgIds) { |
80 | | - sendAck(cnx, consumerId, msgId, CommandAck_AckType_Individual); |
| 103 | + for (auto&& kv : msgIdToCallback) { |
| 104 | + doImmediateAck(cnx, requestId, kv.first, kv.second, CommandAck_AckType_Individual); |
81 | 105 | } |
82 | 106 | } |
83 | | - return true; |
84 | 107 | } |
85 | 108 |
|
86 | 109 | } // namespace pulsar |
0 commit comments