Skip to content

Commit 650300e

Browse files
authored
Fix handle csl failure to assign queue (#821)
Signed-off-by: dorjesinpo <129227380+dorjesinpo@users.noreply.github.com>
1 parent c4c3bd8 commit 650300e

11 files changed

Lines changed: 136 additions & 193 deletions

src/groups/mqb/mqbblp/mqbblp_clusterqueuehelper.cpp

Lines changed: 48 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ namespace BloombergLP {
8989
namespace mqbblp {
9090

9191
namespace {
92-
const char k_MAXIMUM_NUMBER_OF_QUEUES_REACHED[] =
93-
"maximum number of queues reached";
92+
9493
const char k_SELF_NODE_IS_STOPPING[] = "self node is stopping";
9594

9695
const int k_MAX_INSTANT_MESSAGES = 10;
@@ -393,8 +392,7 @@ void ClusterQueueHelper::afterPartitionPrimaryAssignment(
393392
}
394393
}
395394

396-
mqbi::ClusterStateManager::QueueAssignmentResult::Enum
397-
ClusterQueueHelper::assignQueue(const QueueContextSp& queueContext)
395+
void ClusterQueueHelper::assignQueue(const QueueContextSp& queueContext)
398396
{
399397
// executed by the cluster *DISPATCHER* thread
400398

@@ -407,30 +405,31 @@ ClusterQueueHelper::assignQueue(const QueueContextSp& queueContext)
407405
// Assigning a queue in a remote, is simply giving it a new queueId.
408406
queueContext->d_liveQInfo.d_id = getNextQueueId();
409407
onQueueContextAssigned(queueContext);
410-
return QueueAssignmentResult::k_ASSIGNMENT_OK; // RETURN
411408
}
412-
413-
if (d_clusterData_p->electorInfo().hasActiveLeader()) {
409+
else if (d_clusterData_p->electorInfo().hasActiveLeader()) {
414410
if (d_clusterData_p->electorInfo().isSelfLeader()) {
415-
return d_clusterStateManager_p->assignQueue(queueContext->uri());
416-
// RETURN
411+
bmqp_ctrlmsg::Status status(d_allocator_p);
412+
413+
if (!d_clusterStateManager_p->assignQueue(queueContext->uri(),
414+
&status)) {
415+
processRejectedQueueAssignment(queueContext.get(), status);
416+
}
417+
// else, all other failure are transient. will retry.
417418
}
418419
else {
419420
requestQueueAssignment(queueContext->uri());
420-
return QueueAssignmentResult::k_ASSIGNMENT_OK; // RETURN
421421
}
422422
}
423+
else {
424+
// Queue not yet assigned, because we don't have a leader (or leader is
425+
// not active) at the moment, nothing to be done; the queue will
426+
// automatically be re-processed once we have an active leader.
423427

424-
// Queue not yet assigned, because we don't have a leader (or leader is not
425-
// active) at the moment, nothing to be done; the queue will automatically
426-
// be re-processed once we have an active leader.
427-
428-
BALL_LOG_INFO << d_cluster_p->description()
429-
<< " Cannot proceed with queueAssignment of "
430-
<< "'" << queueContext->uri()
431-
<< "' (waiting for an ACTIVE leader).";
432-
433-
return QueueAssignmentResult::k_ASSIGNMENT_OK;
428+
BALL_LOG_INFO << d_cluster_p->description()
429+
<< " Cannot proceed with queueAssignment of '"
430+
<< queueContext->uri()
431+
<< "' (waiting for an ACTIVE leader).";
432+
}
434433
}
435434

436435
void ClusterQueueHelper::requestQueueAssignment(const bmqt::Uri& uri)
@@ -564,6 +563,7 @@ void ClusterQueueHelper::onQueueAssignmentResponse(
564563
// exists and the queue is assigned, because the
565564
// 'queueAssignmentAdvisory' message may have been dropped due to
566565
// change of leader.
566+
567567
BALL_LOG_INFO << d_cluster_p->description()
568568
<< " Received queueAssignment response from '"
569569
<< responder->nodeDescription()
@@ -589,24 +589,22 @@ void ClusterQueueHelper::onQueueAssignmentResponse(
589589
// time.
590590
}
591591
else if (requestContext->result() == bmqt::GenericResult::e_REFUSED) {
592-
if (requestContext->response().choice().status().code() ==
593-
mqbi::ClusterErrorCode::e_NOT_LEADER) {
592+
if (status.code() == mqbi::ClusterErrorCode::e_NOT_LEADER) {
594593
// The leader changed by the time our request reached it; we
595594
// don't have to do anything here: since the leader changed, we
596595
// must have (or will shortly) received a notification about
597596
// the new leader, and in the 'onClusterLeader' one thing we do
598597
// is re-emit an assignmentRequest for any unassigned queue,
599598
// this current one being part of them.
600599
}
601-
else if (requestContext->response().choice().status().code() ==
602-
mqbi::ClusterErrorCode::e_LIMIT) {
600+
else if (status.code() == mqbi::ClusterErrorCode::e_LIMIT ||
601+
status.code() == mqbi::ClusterErrorCode::e_CSL_FAILURE ||
602+
status.code() == mqbi::ClusterErrorCode::e_UNKNOWN) {
603603
QueueContextMapIter qit = d_queues.find(uri);
604604
BSLS_ASSERT_SAFE(qit != d_queues.end());
605-
bdlma::LocalSequentialAllocator<256> localAllocator(
606-
d_allocator_p);
607-
bsl::vector<QueueContext*> rejected(1, &localAllocator);
608-
*rejected.begin() = qit->second.get();
609-
processRejectedQueueAssignments(rejected);
605+
const QueueContext* rejected = qit->second.get();
606+
607+
processRejectedQueueAssignment(rejected, status);
610608
}
611609
}
612610
else {
@@ -3399,35 +3397,27 @@ void ClusterQueueHelper::restoreState(int partitionId)
33993397
}
34003398
}
34013399

3402-
void ClusterQueueHelper::processRejectedQueueAssignments(
3403-
const bsl::vector<QueueContext*>& rejected)
3400+
void ClusterQueueHelper::processRejectedQueueAssignment(
3401+
const QueueContext* rejected,
3402+
const bmqp_ctrlmsg::Status& status)
34043403
{
34053404
// executed by the cluster *DISPATCHER* thread
34063405

34073406
// PRECONDITIONS
34083407
BSLS_ASSERT_SAFE(
34093408
d_cluster_p->dispatcher()->inDispatcherThread(d_cluster_p));
34103409

3411-
bmqp_ctrlmsg::Status failure;
3412-
failure.category() = bmqp_ctrlmsg::StatusCategory::E_REFUSED;
3413-
failure.code() = mqbi::ClusterErrorCode::e_LIMIT;
3414-
failure.message() = k_MAXIMUM_NUMBER_OF_QUEUES_REACHED;
3415-
3416-
for (bsl::vector<QueueContext*>::const_iterator sIt = rejected.begin();
3417-
sIt != rejected.end();
3418-
++sIt) {
3419-
for (bsl::vector<OpenQueueContextSp>::iterator
3420-
cIt = (*sIt)->d_liveQInfo.d_pending.begin(),
3421-
cLast = (*sIt)->d_liveQInfo.d_pending.end();
3422-
cIt != cLast;
3423-
++cIt) {
3424-
(*cIt)->d_callback(failure,
3425-
0,
3426-
bmqp_ctrlmsg::OpenQueueResponse(),
3427-
mqbi::Cluster::OpenQueueConfirmationCookie());
3428-
}
3429-
d_queues.erase((*sIt)->uri());
3430-
}
3410+
for (bsl::vector<OpenQueueContextSp>::const_iterator
3411+
cIt = rejected->d_liveQInfo.d_pending.begin(),
3412+
cLast = rejected->d_liveQInfo.d_pending.end();
3413+
cIt != cLast;
3414+
++cIt) {
3415+
(*cIt)->d_callback(status,
3416+
0,
3417+
bmqp_ctrlmsg::OpenQueueResponse(),
3418+
mqbi::Cluster::OpenQueueConfirmationCookie());
3419+
}
3420+
d_queues.erase(rejected->uri());
34313421
}
34323422

34333423
void ClusterQueueHelper::restoreStateRemote()
@@ -3450,9 +3440,6 @@ void ClusterQueueHelper::restoreStateRemote()
34503440
}
34513441

34523442
// Attempt to re-issue open-queue requests for all applicable queues.
3453-
bdlma::LocalSequentialAllocator<1024> localAllocator(d_allocator_p);
3454-
bsl::vector<QueueContext*> rejected(&localAllocator);
3455-
rejected.reserve(d_queues.size());
34563443

34573444
for (QueueContextMapConstIter cit = d_queues.cbegin();
34583445
cit != d_queues.cend();
@@ -3473,10 +3460,9 @@ void ClusterQueueHelper::restoreStateRemote()
34733460

34743461
if (!isQueueAssigned(*queueContext.get())) {
34753462
// Queue is not assigned to a partition; get it assigned.
3476-
if (QueueAssignmentResult::k_ASSIGNMENT_REJECTED ==
3477-
assignQueue(queueContext)) {
3478-
rejected.push_back(queueContext.get());
3479-
}
3463+
3464+
assignQueue(queueContext);
3465+
34803466
continue; // CONTINUE
34813467
}
34823468

@@ -3508,8 +3494,6 @@ void ClusterQueueHelper::restoreStateRemote()
35083494

35093495
onQueueContextAssigned(queueContext);
35103496
}
3511-
3512-
processRejectedQueueAssignments(rejected);
35133497
}
35143498

35153499
void ClusterQueueHelper::restoreStateCluster(int partitionId)
@@ -3595,10 +3579,6 @@ void ClusterQueueHelper::restoreStateCluster(int partitionId)
35953579
d_clusterData_p->membership().selfNode();
35963580
}
35973581

3598-
bdlma::LocalSequentialAllocator<1024> localAllocator(d_allocator_p);
3599-
bsl::vector<QueueContext*> rejected(&localAllocator);
3600-
rejected.reserve(d_queues.size());
3601-
36023582
for (QueueContextMapConstIter cit = d_queues.cbegin();
36033583
cit != d_queues.cend();
36043584
++cit) {
@@ -3626,10 +3606,9 @@ void ClusterQueueHelper::restoreStateCluster(int partitionId)
36263606
// Queue is not assigned to a partition; get it assigned. If
36273607
// self is leader, it will assign it locally, if not it will
36283608
// send a request to the leader, etc.
3629-
if (QueueAssignmentResult::k_ASSIGNMENT_REJECTED ==
3630-
assignQueue(queueContext)) {
3631-
rejected.push_back(queueContext.get());
3632-
}
3609+
3610+
assignQueue(queueContext);
3611+
36333612
continue; // CONTINUE
36343613
}
36353614
}
@@ -3757,8 +3736,6 @@ void ClusterQueueHelper::restoreStateCluster(int partitionId)
37573736
}
37583737
}
37593738
}
3760-
3761-
processRejectedQueueAssignments(rejected);
37623739
}
37633740

37643741
bmqt::GenericResult::Enum
@@ -4699,14 +4676,7 @@ void ClusterQueueHelper::openQueue(
46994676
queueContext->d_liveQInfo.d_pending.push_back(context);
47004677

47014678
// Initiate the assignment.
4702-
if (QueueAssignmentResult::k_ASSIGNMENT_REJECTED ==
4703-
assignQueue(queueContext)) {
4704-
bdlma::LocalSequentialAllocator<1024> localAllocator(
4705-
d_allocator_p);
4706-
bsl::vector<QueueContext*> rejected(&localAllocator);
4707-
rejected.push_back(queueContext.get());
4708-
processRejectedQueueAssignments(rejected);
4709-
}
4679+
assignQueue(queueContext);
47104680
}
47114681
}
47124682

src/groups/mqb/mqbblp/mqbblp_clusterqueuehelper.h

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,6 @@ class ClusterQueueHelper BSLS_KEYWORD_FINAL
292292
typedef mqbc::ClusterState::DomainStates DomainStates;
293293
typedef mqbc::ClusterState::DomainStatesCIter DomainStatesCIter;
294294

295-
typedef mqbi::ClusterStateManager::QueueAssignmentResult
296-
QueueAssignmentResult;
297-
298295
typedef mqbc::ClusterNodeSession::SubQueueInfo CNSSubQueueInfo;
299296
typedef mqbc::ClusterNodeSession::QueueState CNSQueueState;
300297
typedef mqbc::ClusterNodeSession::StreamsMap CNSStreamsMap;
@@ -483,15 +480,13 @@ class ClusterQueueHelper BSLS_KEYWORD_FINAL
483480
mqbnet::ClusterNode* primary,
484481
bmqp_ctrlmsg::PrimaryStatus::Value status);
485482

486-
/// Assign the queue represented by the specified `queueContext`, that
487-
/// is give it an id and eventually a partition id, by initiating
488-
/// assignment request communication with the leader. Return a value
489-
/// indicating whether the assignment was successful or was definitively
490-
/// rejected. This method is called regardless of proxy or member, and
491-
/// leader or replica and will initiate the proper sequence of operation
492-
/// based on the role of the current node within the cluster.
493-
QueueAssignmentResult::Enum
494-
assignQueue(const QueueContextSp& queueContext);
483+
/// Try to assign the queue represented by the specified `queueContext`,
484+
/// that is give it an id and eventually a partition id, by initiating
485+
/// assignment request communication with the leader. This method is
486+
/// called regardless of proxy or member, and leader or replica and will
487+
/// initiate the proper sequence of operation based on the role of the
488+
/// current node within the cluster.
489+
void assignQueue(const QueueContextSp& queueContext);
495490

496491
/// Send a queueAssignment request to the leader, requesting assignment
497492
/// of the queue with the specified `uri`. This method is called only
@@ -507,11 +502,11 @@ class ClusterQueueHelper BSLS_KEYWORD_FINAL
507502
const bmqt::Uri& uri,
508503
mqbnet::ClusterNode* responder);
509504

510-
/// Send a failure response for the pending contexts associated to the
511-
/// states in the specified `rejected` vector. Also remove the
512-
/// associated queues from `d_queues`.
513-
void processRejectedQueueAssignments(
514-
const bsl::vector<QueueContext*>& rejected);
505+
/// Send a failure response with the specified `status` for the pending
506+
/// context associated to the states in the specified `rejected`. Also
507+
/// remove the associated queue from `d_queues`.
508+
void processRejectedQueueAssignment(const QueueContext* rejected,
509+
const bmqp_ctrlmsg::Status& status);
515510

516511
/// Method invoked when the queue in the specified `queueContext` has
517512
/// been assigned; to resume the operation on any pending contexts.

src/groups/mqb/mqbblp/mqbblp_clusterstatemanager.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -843,9 +843,8 @@ void ClusterStateManager::assignPartitions(
843843
d_clusterConfig.clusterAttributes().isCSLModeEnabled());
844844
}
845845

846-
ClusterStateManager::QueueAssignmentResult::Enum
847-
ClusterStateManager::assignQueue(const bmqt::Uri& uri,
848-
bmqp_ctrlmsg::Status* status)
846+
bool ClusterStateManager::assignQueue(const bmqt::Uri& uri,
847+
bmqp_ctrlmsg::Status* status)
849848
{
850849
// executed by the cluster *DISPATCHER* thread
851850
// PRECONDITIONS

src/groups/mqb/mqbblp/mqbblp_clusterstatemanager.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,17 +337,15 @@ class ClusterStateManager BSLS_KEYWORD_FINAL
337337
/// Perform the actual assignment of the queue represented by the
338338
/// specified `uri` for a cluster member queue, that is assign it a
339339
/// queue key, a partition id, and some appIds; and applying the
340-
/// corresponding queue assignment advisory to CSL. Return a value
341-
/// indicating whether the assignment was successful or was definitively
342-
/// rejected, and populate the optionally specified `status` with a
343-
/// human readable error code and string in case of failure. This
344-
/// method is called only on the leader node.
340+
/// corresponding queue assignment advisory to CSL. Return `false` in the
341+
/// case of permanent failure when need to reject the assignment. Return
342+
/// `true` if the assignment is successful or can be retried.
343+
/// This method is called only on the leader node.
345344
///
346345
/// THREAD: This method is invoked in the associated cluster's
347346
/// dispatcher thread.
348-
QueueAssignmentResult::Enum
349-
assignQueue(const bmqt::Uri& uri,
350-
bmqp_ctrlmsg::Status* status = 0) BSLS_KEYWORD_OVERRIDE;
347+
bool assignQueue(const bmqt::Uri& uri,
348+
bmqp_ctrlmsg::Status* status) BSLS_KEYWORD_OVERRIDE;
351349

352350
/// Register a queue info for the queue with the specified `advisory`.
353351
/// If the specified `forceUpdate` flag is true, update queue info even if

src/groups/mqb/mqbc/mqbc_clusterstatemanager.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,9 +1489,8 @@ void ClusterStateManager::assignPartitions(
14891489
true); // isCSLMode
14901490
}
14911491

1492-
ClusterStateManager::QueueAssignmentResult::Enum
1493-
ClusterStateManager::assignQueue(const bmqt::Uri& uri,
1494-
bmqp_ctrlmsg::Status* status)
1492+
bool ClusterStateManager::assignQueue(const bmqt::Uri& uri,
1493+
bmqp_ctrlmsg::Status* status)
14951494
{
14961495
// executed by the cluster *DISPATCHER* thread
14971496
// PRECONDITIONS

src/groups/mqb/mqbc/mqbc_clusterstatemanager.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -435,15 +435,15 @@ class ClusterStateManager BSLS_KEYWORD_FINAL
435435
/// Perform the actual assignment of the queue represented by the
436436
/// specified `uri` for a cluster member queue, that is assign it a
437437
/// queue key, a partition id, and some appIds; and applying the
438-
/// corresponding queue assignment advisory to CSL. Return a value
439-
/// indicating whether the assignment was successful or was definitively
440-
/// rejected. This method is called only on the leader node.
438+
/// corresponding queue assignment advisory to CSL. Return `false` in the
439+
/// case of permanent failure when need to reject the assignment. Return
440+
/// `true` if the assignment is successful or can be retried.
441+
/// This method is called only on the leader node.
441442
///
442443
/// THREAD: This method is invoked in the associated cluster's
443444
/// dispatcher thread.
444-
QueueAssignmentResult::Enum
445-
assignQueue(const bmqt::Uri& uri,
446-
bmqp_ctrlmsg::Status* status = 0) BSLS_KEYWORD_OVERRIDE;
445+
bool assignQueue(const bmqt::Uri& uri,
446+
bmqp_ctrlmsg::Status* status) BSLS_KEYWORD_OVERRIDE;
447447

448448
/// Register a queue info for the queue with the specified `advisory`.
449449
/// If the specified `forceUpdate` flag is true, update queue info even if

0 commit comments

Comments
 (0)