A :class:`.LoadBalancingPolicy` wrapper that adds token awareness to a child policy. This alters the child policy's behavior so that it first attempts to send queries to :attr:`~.HostDistance.LOCAL` replicas (as determined by the child policy) based on the :class:`.Statement`'s
| 319 | |
| 320 | |
| 321 | class TokenAwarePolicy(LoadBalancingPolicy): |
| 322 | """ |
| 323 | A :class:`.LoadBalancingPolicy` wrapper that adds token awareness to |
| 324 | a child policy. |
| 325 | |
| 326 | This alters the child policy's behavior so that it first attempts to |
| 327 | send queries to :attr:`~.HostDistance.LOCAL` replicas (as determined |
| 328 | by the child policy) based on the :class:`.Statement`'s |
| 329 | :attr:`~.Statement.routing_key`. If :attr:`.shuffle_replicas` is |
| 330 | truthy, these replicas will be yielded in a random order. Once those |
| 331 | hosts are exhausted, the remaining hosts in the child policy's query |
| 332 | plan will be used in the order provided by the child policy. |
| 333 | |
| 334 | If no :attr:`~.Statement.routing_key` is set on the query, the child |
| 335 | policy's query plan will be used as is. |
| 336 | """ |
| 337 | |
| 338 | _child_policy = None |
| 339 | _cluster_metadata = None |
| 340 | shuffle_replicas = False |
| 341 | """ |
| 342 | Yield local replicas in a random order. |
| 343 | """ |
| 344 | |
| 345 | def __init__(self, child_policy, shuffle_replicas=False): |
| 346 | self._child_policy = child_policy |
| 347 | self.shuffle_replicas = shuffle_replicas |
| 348 | |
| 349 | def populate(self, cluster, hosts): |
| 350 | self._cluster_metadata = cluster.metadata |
| 351 | self._child_policy.populate(cluster, hosts) |
| 352 | |
| 353 | def check_supported(self): |
| 354 | if not self._cluster_metadata.can_support_partitioner(): |
| 355 | raise RuntimeError( |
| 356 | '%s cannot be used with the cluster partitioner (%s) because ' |
| 357 | 'the relevant C extension for this driver was not compiled. ' |
| 358 | 'See the installation instructions for details on building ' |
| 359 | 'and installing the C extensions.' % |
| 360 | (self.__class__.__name__, self._cluster_metadata.partitioner)) |
| 361 | |
| 362 | def distance(self, *args, **kwargs): |
| 363 | return self._child_policy.distance(*args, **kwargs) |
| 364 | |
| 365 | def make_query_plan(self, working_keyspace=None, query=None): |
| 366 | if query and query.keyspace: |
| 367 | keyspace = query.keyspace |
| 368 | else: |
| 369 | keyspace = working_keyspace |
| 370 | |
| 371 | child = self._child_policy |
| 372 | if query is None: |
| 373 | for host in child.make_query_plan(keyspace, query): |
| 374 | yield host |
| 375 | else: |
| 376 | routing_key = query.routing_key |
| 377 | if routing_key is None or keyspace is None: |
| 378 | for host in child.make_query_plan(keyspace, query): |
no outgoing calls