@@ -170,8 +170,22 @@ or refrain from preferring datacenters (which may ban all other datacenters, if
170170 // some alive local node.
171171 // If there was no preferred datacenter specified, all nodes are treated as local.
172172 let nodes = self . preferred_node_set ( cluster) ;
173- let picked = Self :: pick_node ( nodes, & self . pick_predicate ) ;
174- if let Some ( alive_local) = picked {
173+
174+ if let ReplicaLocationPreference :: DatacenterAndRack ( dc, rack) = & self . preferences {
175+ // Try to pick some alive local rack random node.
176+ let rack_predicate = Self :: make_rack_predicate (
177+ & self . pick_predicate ,
178+ ReplicaLocationCriteria :: DatacenterAndRack ( dc, rack) ,
179+ ) ;
180+ let local_rack_picked = Self :: pick_node ( nodes, rack_predicate) ;
181+
182+ if let Some ( alive_local_rack) = local_rack_picked {
183+ return Some ( alive_local_rack) ;
184+ }
185+ }
186+
187+ // Try to pick some alive local random node.
188+ if let Some ( alive_local) = Self :: pick_node ( nodes, & self . pick_predicate ) {
175189 return Some ( alive_local) ;
176190 }
177191
@@ -276,6 +290,17 @@ or refrain from preferring datacenters (which may ban all other datacenters, if
276290
277291 // Get a list of all local alive nodes, and apply a round robin to it
278292 let local_nodes = self . preferred_node_set ( cluster) ;
293+
294+ let maybe_local_rack_nodes =
295+ if let ReplicaLocationPreference :: DatacenterAndRack ( dc, rack) = & self . preferences {
296+ let rack_predicate = Self :: make_rack_predicate (
297+ & self . pick_predicate ,
298+ ReplicaLocationCriteria :: DatacenterAndRack ( dc, rack) ,
299+ ) ;
300+ Either :: Left ( Self :: round_robin_nodes ( local_nodes, rack_predicate) )
301+ } else {
302+ Either :: Right ( std:: iter:: empty :: < NodeRef < ' a > > ( ) )
303+ } ;
279304 let robined_local_nodes = Self :: round_robin_nodes ( local_nodes, Self :: is_alive) ;
280305
281306 let all_nodes = cluster. replica_locator ( ) . unique_nodes_in_global_ring ( ) ;
@@ -301,6 +326,7 @@ or refrain from preferring datacenters (which may ban all other datacenters, if
301326
302327 // Construct a fallback plan as a composition of replicas, local nodes and remote nodes.
303328 let plan = maybe_replicas
329+ . chain ( maybe_local_rack_nodes)
304330 . chain ( robined_local_nodes)
305331 . chain ( maybe_remote_nodes)
306332 . chain ( maybe_down_local_nodes)
@@ -1570,7 +1596,8 @@ mod tests {
15701596 expected_groups : ExpectedGroupsBuilder :: new ( )
15711597 . deterministic ( [ B ] ) // pick local rack replicas
15721598 . deterministic ( [ C ] ) // fallback replicas
1573- . group ( [ A , G ] ) // local nodes
1599+ . group ( [ A ] ) // local rack nodes
1600+ . group ( [ G ] ) // local DC nodes
15741601 . build ( ) ,
15751602 } ,
15761603 // Keyspace SS with RF=2 with enabled rack-awareness and no local-rack replica
@@ -1595,7 +1622,34 @@ mod tests {
15951622 // r2 r1 r1 r1 r2 r1 r1
15961623 expected_groups : ExpectedGroupsBuilder :: new ( )
15971624 . group ( [ A ] ) // pick local DC
1598- . group ( [ C , G , B ] ) // local nodes
1625+ . group ( [ G ] ) // local rack nodes
1626+ . group ( [ C , B ] ) // local DC nodes
1627+ . build ( ) ,
1628+ } ,
1629+ // Keyspace NTS with RF=3 with enabled DC failover and rack-awareness, no token provided
1630+ Test {
1631+ policy : DefaultPolicy {
1632+ preferences : NodeLocationPreference :: DatacenterAndRack (
1633+ "eu" . to_owned ( ) ,
1634+ "r1" . to_owned ( ) ,
1635+ ) ,
1636+ is_token_aware : true ,
1637+ permit_dc_failover : true ,
1638+ ..Default :: default ( )
1639+ } ,
1640+ routing_info : RoutingInfo {
1641+ token : None ,
1642+ keyspace : Some ( KEYSPACE_NTS_RF_3 ) ,
1643+ consistency : Consistency :: One ,
1644+ ..Default :: default ( )
1645+ } ,
1646+ // going through the ring, we get order: F , A , C , D , G , B , E
1647+ // us eu eu us eu eu us
1648+ // r2 r1 r1 r1 r2 r1 r1
1649+ expected_groups : ExpectedGroupsBuilder :: new ( )
1650+ . group ( [ A , C , B ] ) // local rack nodes
1651+ . group ( [ G ] ) // local DC nodes
1652+ . group ( [ F , D , E ] ) // remote nodes
15991653 . build ( ) ,
16001654 } ,
16011655 ] ;
0 commit comments