|
14 | 14 |
|
15 | 15 | from itertools import islice, cycle, groupby, repeat |
16 | 16 | import logging |
17 | | -from random import randint |
| 17 | +from random import randint, shuffle |
18 | 18 | from threading import Lock |
19 | 19 | import socket |
20 | 20 |
|
@@ -320,13 +320,18 @@ class TokenAwarePolicy(LoadBalancingPolicy): |
320 | 320 |
|
321 | 321 | If no :attr:`~.Statement.routing_key` is set on the query, the child |
322 | 322 | policy's query plan will be used as is. |
| 323 | +
|
| 324 | + If :attr:`.shuffle_replicas` is truthy, :attr:`~.HostDistance.LOCAL` |
| 325 | + replicas will be yielded in a random order, followed by the remaining |
| 326 | + hosts in the order provided child policy's query plan. |
323 | 327 | """ |
324 | 328 |
|
325 | 329 | _child_policy = None |
326 | 330 | _cluster_metadata = None |
327 | 331 |
|
328 | | - def __init__(self, child_policy): |
| 332 | + def __init__(self, child_policy, shuffle_replicas=False): |
329 | 333 | self._child_policy = child_policy |
| 334 | + self.shuffle_replicas = shuffle_replicas |
330 | 335 |
|
331 | 336 | def populate(self, cluster, hosts): |
332 | 337 | self._cluster_metadata = cluster.metadata |
@@ -361,6 +366,8 @@ def make_query_plan(self, working_keyspace=None, query=None): |
361 | 366 | yield host |
362 | 367 | else: |
363 | 368 | replicas = self._cluster_metadata.get_replicas(keyspace, routing_key) |
| 369 | + if self.shuffle_replicas: |
| 370 | + shuffle(replicas) |
364 | 371 | for replica in replicas: |
365 | 372 | if replica.is_up and \ |
366 | 373 | child.distance(replica) == HostDistance.LOCAL: |
|
0 commit comments