| Execution Profiles |
| ================== |
| |
| Execution profiles aim at making it easier to execute requests in different ways within |
| a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of |
| configuration options, especially as the database platform evolves more complex workloads. |
| |
| The legacy configuration remains intact, but legacy and Execution Profile APIs |
| cannot be used simultaneously on the same client ``Cluster``. Legacy configuration |
| will be removed in the next major release (4.0). |
| |
| An execution profile and its parameters should be unique across ``Cluster`` instances. |
| For example, an execution profile and its ``LoadBalancingPolicy`` should |
| not be applied to more than one ``Cluster`` instance. |
| |
| This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for |
| request execution. |
| |
| Mapping Legacy Parameters to Profiles |
| ------------------------------------- |
| |
| Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, |
| previously input from the noted attributes: |
| |
| - load_balancing_policy - :attr:`.Cluster.load_balancing_policy` |
| - request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter |
| - retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute |
| - consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute |
| - serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute |
| - row_factory - :attr:`.Session.row_factory` attribute |
| |
| When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. |
| |
| Using Execution Profiles |
| ------------------------ |
| Default |
| ~~~~~~~ |
| |
| .. code:: python |
| |
| from cassandra.cluster import Cluster |
| cluster = Cluster() |
| session = cluster.connect() |
| local_query = 'SELECT rpc_address FROM system.local' |
| for _ in cluster.metadata.all_hosts(): |
| print(session.execute(local_query)[0]) |
| |
| |
| .. parsed-literal:: |
| |
| Row(rpc_address='127.0.0.2') |
| Row(rpc_address='127.0.0.1') |
| |
| |
| The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default |
| parameters. |
| |
| Initializing cluster with profiles |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. code:: python |
| |
| from cassandra.cluster import ExecutionProfile |
| from cassandra.policies import WhiteListRoundRobinPolicy |
| |
| node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) |
| node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) |
| |
| profiles = {'node1': node1_profile, 'node2': node2_profile} |
| session = Cluster(execution_profiles=profiles).connect() |
| for _ in cluster.metadata.all_hosts(): |
| print(session.execute(local_query, execution_profile='node1')[0]) |
| |
| |
| .. parsed-literal:: |
| |
| Row(rpc_address='127.0.0.1') |
| Row(rpc_address='127.0.0.1') |
| |
| |
| .. code:: python |
| |
| for _ in cluster.metadata.all_hosts(): |
| print(session.execute(local_query, execution_profile='node2')[0]) |
| |
| |
| .. parsed-literal:: |
| |
| Row(rpc_address='127.0.0.2') |
| Row(rpc_address='127.0.0.2') |
| |
| |
| .. code:: python |
| |
| for _ in cluster.metadata.all_hosts(): |
| print(session.execute(local_query)[0]) |
| |
| |
| .. parsed-literal:: |
| |
| Row(rpc_address='127.0.0.2') |
| Row(rpc_address='127.0.0.1') |
| |
| Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still |
| present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. |
| |
| .. code:: python |
| |
| from cassandra.cluster import EXEC_PROFILE_DEFAULT |
| profile = ExecutionProfile(request_timeout=30) |
| cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) |
| |
| |
| Adding named profiles |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| New profiles can be added constructing from scratch, or deriving from default: |
| |
| .. code:: python |
| |
| locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) |
| node1_profile = 'node1_whitelist' |
| cluster.add_execution_profile(node1_profile, locked_execution) |
| |
| for _ in cluster.metadata.all_hosts(): |
| print(session.execute(local_query, execution_profile=node1_profile)[0]) |
| |
| |
| .. parsed-literal:: |
| |
| Row(rpc_address='127.0.0.1') |
| Row(rpc_address='127.0.0.1') |
| |
| See :meth:`.Cluster.add_execution_profile` for details and optional parameters. |
| |
| Passing a profile instance without mapping |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| We also have the ability to pass profile instances to be used for execution, but not added to the mapping: |
| |
| .. code:: python |
| |
| from cassandra.query import tuple_factory |
| |
| tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) |
| |
| print(session.execute(local_query, execution_profile=tmp)[0]) |
| print(session.execute(local_query, execution_profile='node1')[0]) |
| |
| .. parsed-literal:: |
| |
| ('127.0.0.1',) |
| Row(rpc_address='127.0.0.1') |
| |
| The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. |
| If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. |