1[[selectors]]
2== Selectors
3
4The connection pool maintains the list of connections, and decides when nodes should transition from alive to dead (and
5vice versa).  It has no logic to choose connections, however.  That job belongs to the Selector class.
6
7The selector's job is to return a single connection from a provided array of connections.  Like the Connection Pool,
8there are several implementations to choose from.
9
10=== RoundRobinSelector (Default)
11
12This selector returns connections in a round-robin fashion.  Node #1 is selected on the first request, Node #2 on
13the second request, etc.  This ensures an even load of traffic across your cluster.  Round-robin'ing happens on a
14per-request basis (e.g. sequential requests go to different nodes).
15
16The `RoundRobinSelector` is default, but if you wish to explicitily configure it you can do:
17
18[source,php]
19----
20$client = ClientBuilder::create()
21            ->setSelector('\Elasticsearch\ConnectionPool\Selectors\RoundRobinSelector')
22            ->build();
23----
24
25Note that the implementation is specified via a namespace path to the class.
26
27=== StickyRoundRobinSelector
28
29This selector is "sticky", in that it prefers to reuse the same connection repeatedly.  For example, Node #1 is chosen
30on the first request.  Node #1 will continue to be re-used for each subsequent request until that node fails.  Upon failure,
31the selector will round-robin to the next available node, then "stick" to that node.
32
33This is an ideal strategy for many PHP scripts.  Since PHP scripts are shared-nothing and tend to exit quickly, creating
34new connections for each request is often a sub-optimal strategy and introduces a lot of overhead.  Instead, it is
35better to "stick" to a single connection for the duration of the script.
36
37By default, this selector will randomize the hosts upon initialization, which will still guarantee an even distribution
38of load across the cluster.  It changes the round-robin dynamics from per-request to per-script.
39
40If you are using <<future_mode>>, the "sticky" behavior of this selector will be non-ideal, since all parallel requests
41will go to the same node instead of multiple nodes in your cluster.  When using future mode, the default `RoundRobinSelector`
42should be preferred.
43
44If you wish to use this selector, you may do so with:
45
46[source,php]
47----
48$client = ClientBuilder::create()
49            ->setSelector('\Elasticsearch\ConnectionPool\Selectors\StickyRoundRobinSelector')
50            ->build();
51----
52
53Note that the implementation is specified via a namespace path to the class.
54
55=== RandomSelector
56
57This selector simply returns a random node, regardless of state.  It is generally just for testing.
58
59If you wish to use this selector, you may do so with:
60
61[source,php]
62----
63$client = ClientBuilder::create()
64            ->setSelector('\Elasticsearch\ConnectionPool\Selectors\RandomSelector')
65            ->build();
66----
67
68Note that the implementation is specified via a namespace path to the class.
69
70=== Custom Selector
71
72You can implement your own custom selector.  Custom selectors must implement `SelectorInterface`
73
74[source,php]
75----
76namespace MyProject\Selectors;
77
78use Elasticsearch\Connections\ConnectionInterface;
79use Elasticsearch\ConnectionPool\Selectors\SelectorInterface
80
81class MyCustomSelector implements SelectorInterface
82{
83
84    /**
85     * Selects the first connection
86     *
87     * @param array $connections Array of Connection objects
88     *
89     * @return ConnectionInterface
90     */
91    public function select($connections)
92    {
93        // code here
94    }
95
96}
97----
98{zwsp} +
99
100You can then use your custom selector either via object injection or namespace instantiation:
101
102[source,php]
103----
104$mySelector = new MyCustomSelector();
105
106$client = ClientBuilder::create()
107            ->setSelector($mySelector)                             // object injection
108            ->setSelector('\MyProject\Selectors\FirstSelector')    // or namespace
109            ->build();
110----
111