Completed
Push — master ( a1d5de...08298b )
by Cy
01:46
created

RedisSentinelDatabase::createSingleClients()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
3
namespace Monospice\LaravelRedisSentinel;
4
5
use Illuminate\Redis\Database as RedisDatabase;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Str;
8
use Predis\Client;
9
10
/**
11
 * Enables Laravel's Redis database driver to accept configuration options for
12
 * Redis Sentinel connections independently.
13
 *
14
 * By default, Laravel's Redis service permits a single set of configuration
15
 * options for all of the Redis connections passed to the Predis client. This
16
 * prevents us from declaring separate parameters for individual Redis services
17
 * managed by Sentinel. For example, we may wish to connect to a separate Redis
18
 * Sentinel service cluster set, or use a separate Redis database, for caching
19
 * queues, and sessions. This wrapper class enables us to declare parameters
20
 * for each connection in the "redis-sentinel" block of the database
21
 * configuration which it will use to configure individual clients.
22
 *
23
 * @category Package
24
 * @package  Monospice\LaravelRedisSentinel
25
 * @author   Cy Rossignol <[email protected]>
26
 * @license  See LICENSE file
27
 * @link     http://github.com/monospice/laravel-redis-sentinel-driver
28
 */
29
class RedisSentinelDatabase extends RedisDatabase
30
{
31
    /**
32
     * Configuration options specific to Sentinel connection operation
33
     *
34
     * We cannot pass these options as an array to the Predis client.
35
     * Instead, we'll set them on the connection directly using methods
36
     * provided by the SentinelReplication class of the Predis package.
37
     *
38
     * @var array
39
     */
40
    protected $sentinelConnectionOptionKeys = [
41
        'sentinel_timeout',
42
        'retry_wait',
43
        'retry_limit',
44
        'update_sentinels',
45
    ];
46
47
    /**
48
     * Create an array of single connection clients.
49
     *
50
     * @param array $servers The set of options for each Sentinel connection
51
     * @param array $options The global options shared by all Sentinel clients
52
     *
53
     * @return array Each element contains a Predis client that represents a
54
     * connection defined in the 'redis-sentinel' block in config/database.php
55
     */
56
    protected function createSingleClients(array $servers, array $options = [])
57
    {
58
        $clients = [];
59
60
        // Automatically set "replication" to "sentinel". This is the Sentinel
61
        // driver, after all.
62
        $options['replication'] = 'sentinel';
63
64
        foreach ($servers as $key => $server) {
65
            $clients[$key] = $this->createSingleClient($server, $options);
66
        }
67
68
        return $clients;
69
    }
70
71
    /**
72
     * Create a Predis client instance for a Redis Sentinel connection
73
     *
74
     * @param array $server  The configuration options for the connection
75
     * @param array $options The global options shared by all Sentinel clients
76
     *
77
     * @return Client The Predis Client instance
78
     */
79
    protected function createSingleClient(array $server, array $options)
80
    {
81
        // Merge the global options shared by all Sentinel connections with
82
        // connection-specific options
83
        $clientOpts = (array) Arr::pull($server, 'options');
84
        $clientOpts = array_merge($options, $clientOpts);
85
86
        $sentinelKeys = array_flip($this->sentinelConnectionOptionKeys);
87
88
        // Extract the array of Sentinel connection options from the rest of
89
        // the client options
90
        $sentinelOpts = array_intersect_key($clientOpts, $sentinelKeys);
91
92
        // Filter the Sentinel connection options elements from the client
93
        // options array
94
        $clientOpts = array_diff_key($clientOpts, $sentinelKeys);
95
96
        $client = new Client($server, $clientOpts);
97
        $this->setSentinelConnectionOptions($client, $sentinelOpts);
98
99
        return $client;
100
    }
101
102
    /**
103
     * Sets the Sentinel-specific connection options on a Predis Client
104
     * connection
105
     *
106
     * @param Client $client       The Predis Client to set options for
107
     * @param array  $sentinelOpts The options supported by Predis for
108
     * Sentinel-specific connections
109
     *
110
     * @return void
111
     */
112
    protected function setSentinelConnectionOptions(
113
        Client $client,
114
        array $sentinelOpts
115
    ) {
116
        $connection = $client->getConnection();
117
118
        foreach ($sentinelOpts as $option => $value) {
119
            $connection->{'set' . Str::studly($option)}($value);
120
        }
121
    }
122
}
123