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