@@ -236,16 +236,14 @@ Future<Result, bool> ConsumerImpl::connectionOpened(const ClientConnectionPtr& c
236
236
// sending the subscribe request.
237
237
cnx->registerConsumer (consumerId_, get_shared_this_ptr ());
238
238
239
- if (duringSeek_ ) {
239
+ if (duringSeek () ) {
240
240
ackGroupingTrackerPtr_->flushAndClean ();
241
241
}
242
242
243
243
Lock lockForMessageId (mutexForMessageId_);
244
- // Update startMessageId so that we can discard messages after delivery restarts
245
- const auto startMessageId = clearReceiveQueue ();
244
+ clearReceiveQueue ();
246
245
const auto subscribeMessageId =
247
- (subscriptionMode_ == Commands::SubscriptionModeNonDurable) ? startMessageId : boost::none;
248
- startMessageId_ = startMessageId;
246
+ (subscriptionMode_ == Commands::SubscriptionModeNonDurable) ? startMessageId_.get () : boost::none;
249
247
lockForMessageId.unlock ();
250
248
251
249
unAckedMessageTrackerPtr_->clear ();
@@ -1048,14 +1046,21 @@ void ConsumerImpl::messageProcessed(Message& msg, bool track) {
1048
1046
* Clear the internal receiver queue and returns the message id of what was the 1st message in the queue that
1049
1047
* was
1050
1048
* not seen by the application
1049
+ * `startMessageId_` is updated so that we can discard messages after delivery restarts.
1051
1050
*/
1052
- boost::optional<MessageId> ConsumerImpl::clearReceiveQueue () {
1053
- bool expectedDuringSeek = true ;
1054
- if (duringSeek_.compare_exchange_strong (expectedDuringSeek, false )) {
1055
- return seekMessageId_.get ();
1051
+ void ConsumerImpl::clearReceiveQueue () {
1052
+ if (duringSeek ()) {
1053
+ startMessageId_ = seekMessageId_.get ();
1054
+ SeekStatus expected = SeekStatus::COMPLETED;
1055
+ if (seekStatus_.compare_exchange_strong (expected, SeekStatus::NOT_STARTED)) {
1056
+ auto seekCallback = seekCallback_.release ();
1057
+ executor_->postWork ([seekCallback] { seekCallback (ResultOk); });
1058
+ }
1059
+ return ;
1056
1060
} else if (subscriptionMode_ == Commands::SubscriptionModeDurable) {
1057
- return startMessageId_. get () ;
1061
+ return ;
1058
1062
}
1063
+
1059
1064
Message nextMessageInQueue;
1060
1065
if (incomingMessages_.peekAndClear (nextMessageInQueue)) {
1061
1066
// There was at least one message pending in the queue
@@ -1071,16 +1076,12 @@ boost::optional<MessageId> ConsumerImpl::clearReceiveQueue() {
1071
1076
.ledgerId (nextMessageId.ledgerId ())
1072
1077
.entryId (nextMessageId.entryId () - 1 )
1073
1078
.build ();
1074
- return previousMessageId;
1079
+ startMessageId_ = previousMessageId;
1075
1080
} else if (lastDequedMessageId_ != MessageId::earliest ()) {
1076
1081
// If the queue was empty we need to restart from the message just after the last one that has been
1077
1082
// dequeued
1078
1083
// in the past
1079
- return lastDequedMessageId_;
1080
- } else {
1081
- // No message was received or dequeued by this consumer. Next message would still be the
1082
- // startMessageId
1083
- return startMessageId_.get ();
1084
+ startMessageId_ = lastDequedMessageId_;
1084
1085
}
1085
1086
}
1086
1087
@@ -1500,18 +1501,15 @@ void ConsumerImpl::seekAsync(uint64_t timestamp, ResultCallback callback) {
1500
1501
1501
1502
bool ConsumerImpl::isReadCompacted () { return readCompacted_; }
1502
1503
1503
- inline bool hasMoreMessages (const MessageId& lastMessageIdInBroker, const MessageId& messageId) {
1504
- return lastMessageIdInBroker > messageId && lastMessageIdInBroker.entryId () != -1 ;
1505
- }
1506
-
1507
1504
void ConsumerImpl::hasMessageAvailableAsync (HasMessageAvailableCallback callback) {
1508
- const auto startMessageId = startMessageId_.get ();
1509
- Lock lock (mutexForMessageId_);
1510
- const auto messageId =
1511
- (lastDequedMessageId_ == MessageId::earliest ()) ? startMessageId.value () : lastDequedMessageId_;
1512
-
1513
- if (messageId == MessageId::latest ()) {
1514
- lock.unlock ();
1505
+ bool compareMarkDeletePosition;
1506
+ {
1507
+ std::lock_guard<std::mutex> lock{mutexForMessageId_};
1508
+ compareMarkDeletePosition =
1509
+ (lastDequedMessageId_ == MessageId::earliest ()) &&
1510
+ (startMessageId_.get ().value_or (MessageId::earliest ()) == MessageId::latest ());
1511
+ }
1512
+ if (compareMarkDeletePosition) {
1515
1513
auto self = get_shared_this_ptr ();
1516
1514
getLastMessageIdAsync ([self, callback](Result result, const GetLastMessageIdResponse& response) {
1517
1515
if (result != ResultOk) {
@@ -1543,16 +1541,15 @@ void ConsumerImpl::hasMessageAvailableAsync(HasMessageAvailableCallback callback
1543
1541
}
1544
1542
});
1545
1543
} else {
1546
- if (hasMoreMessages (lastMessageIdInBroker_, messageId)) {
1547
- lock.unlock ();
1544
+ if (hasMoreMessages ()) {
1548
1545
callback (ResultOk, true );
1549
1546
return ;
1550
1547
}
1551
- lock. unlock ();
1552
-
1553
- getLastMessageIdAsync ([callback, messageId ](Result result, const GetLastMessageIdResponse& response) {
1554
- callback (result, (result == ResultOk) && hasMoreMessages (response. getLastMessageId (), messageId ));
1555
- });
1548
+ auto self = get_shared_this_ptr ();
1549
+ getLastMessageIdAsync (
1550
+ [ this , self, callback ](Result result, const GetLastMessageIdResponse& response) {
1551
+ callback (result, (result == ResultOk) && hasMoreMessages ());
1552
+ });
1556
1553
}
1557
1554
}
1558
1555
@@ -1656,9 +1653,18 @@ void ConsumerImpl::seekAsyncInternal(long requestId, SharedBuffer seek, const Me
1656
1653
return ;
1657
1654
}
1658
1655
1656
+ auto expected = SeekStatus::NOT_STARTED;
1657
+ if (!seekStatus_.compare_exchange_strong (expected, SeekStatus::IN_PROGRESS)) {
1658
+ LOG_ERROR (getName () << " attempted to seek (" << seekId << " , " << timestamp << " when the status is "
1659
+ << static_cast <int >(expected));
1660
+ callback (ResultNotAllowedError);
1661
+ return ;
1662
+ }
1663
+
1659
1664
const auto originalSeekMessageId = seekMessageId_.get ();
1660
1665
seekMessageId_ = seekId;
1661
- duringSeek_ = true ;
1666
+ seekStatus_ = SeekStatus::IN_PROGRESS;
1667
+ seekCallback_ = std::move (callback);
1662
1668
if (timestamp > 0 ) {
1663
1669
LOG_INFO (getName () << " Seeking subscription to " << timestamp);
1664
1670
} else {
@@ -1682,12 +1688,19 @@ void ConsumerImpl::seekAsyncInternal(long requestId, SharedBuffer seek, const Me
1682
1688
Lock lock (mutexForMessageId_);
1683
1689
lastDequedMessageId_ = MessageId::earliest ();
1684
1690
lock.unlock ();
1691
+ if (getCnx ().expired ()) {
1692
+ // It's during reconnection, complete the seek future after connection is established
1693
+ seekStatus_ = SeekStatus::COMPLETED;
1694
+ } else {
1695
+ startMessageId_ = seekMessageId_.get ();
1696
+ seekCallback_.release ()(result);
1697
+ }
1685
1698
} else {
1686
1699
LOG_ERROR (getName () << " Failed to seek: " << result);
1687
1700
seekMessageId_ = originalSeekMessageId;
1688
- duringSeek_ = false ;
1701
+ seekStatus_ = SeekStatus::NOT_STARTED;
1702
+ seekCallback_.release ()(result);
1689
1703
}
1690
- callback (result);
1691
1704
});
1692
1705
}
1693
1706
0 commit comments