Passed
Push — master ( c82647...c877fa )
by Georges
11:01
created

Driver::driverReadAllKeys()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 3
nop 1
dl 0
loc 17
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/**
4
 *
5
 * This file is part of Phpfastcache.
6
 *
7
 * @license MIT License (MIT)
8
 *
9
 * For full copyright and license information, please see the docs/CREDITS.txt and LICENCE files.
10
 *
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 * @author Contributors  https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phpfastcache\Drivers\Rediscluster;
18
19
use DateTime;
20
use Phpfastcache\Cluster\AggregatablePoolInterface;
21
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
22
use Phpfastcache\Core\Pool\TaggableCacheItemPoolTrait;
23
use Phpfastcache\Drivers\Redis\RedisDriverTrait;
24
use Phpfastcache\Entities\DriverStatistic;
25
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
26
use RedisCluster;
27
28
/**
29
 * @property RedisCluster $instance
30
 * @method Config getConfig()
31
 */
32
class Driver implements AggregatablePoolInterface
33
{
34
    use RedisDriverTrait, TaggableCacheItemPoolTrait {
35
        RedisDriverTrait::driverReadMultiple insteadof TaggableCacheItemPoolTrait;
36
        RedisDriverTrait::driverDeleteMultiple insteadof TaggableCacheItemPoolTrait;
37
    }
38
39
    /**
40
     * @return bool
41
     */
42
    public function driverCheck(): bool
43
    {
44
        return extension_loaded('Redis') && class_exists(RedisCluster::class);
45
    }
46
47
    /**
48
     * @return DriverStatistic
49
     */
50
    public function getStats(): DriverStatistic
51
    {
52
        $masters = $this->instance->_masters();
53
        $infos = array_map(fn($cluster) => $this->instance->info($cluster), $masters);
54
        $date = (new DateTime())->setTimestamp(time() - min(array_column($infos, 'uptime_in_seconds')));
55
56
        return (new DriverStatistic())
57
            ->setData(implode(', ', array_keys($this->itemInstances)))
58
            ->setRawData($infos)
59
            ->setSize(array_sum(array_column($infos, 'used_memory_dataset')))
0 ignored issues
show
Bug introduced by
It seems like array_sum(array_column($...'used_memory_dataset')) can also be of type double; however, parameter $size of Phpfastcache\Entities\DriverStatistic::setSize() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

59
            ->setSize(/** @scrutinizer ignore-type */ array_sum(array_column($infos, 'used_memory_dataset')))
Loading history...
60
            ->setInfo(
61
                sprintf(
62
                    trim(<<<EOF
63
                        Redis Cluster version v%s, php-ext v%s with %d master nodes and %d slaves connected are up since %s.
64
                        For more information see RawData.
65
                    EOF),
66
                    implode(', ', array_unique(array_column($infos, 'redis_version'))),
67
                    \phpversion("redis"),
68
                    count($masters),
69
                    array_sum(array_column($infos, 'connected_slaves')),
70
                    $date->format(DATE_RFC2822)
71
                )
72
            );
73
    }
74
75
    /**
76
     * @return bool
77
     * @throws PhpfastcacheLogicException
78
     */
79
    protected function driverConnect(): bool
80
    {
81
        if (isset($this->instance) && $this->instance instanceof RedisCluster) {
82
            throw new PhpfastcacheLogicException('Already connected to Redis server');
83
        }
84
85
        /**
86
         * In case of a user-provided
87
         * Redis client just return here
88
         */
89
        if ($this->getConfig()->getRedisClusterClient() instanceof RedisCluster) {
90
            /**
91
             * Unlike Predis, we can't test if we're connected
92
             * or not, so let's just assume that we are
93
             */
94
            $this->instance = $this->getConfig()->getRedisClusterClient();
95
            return true;
96
        }
97
98
        $this->instance = $this->instance ?? new RedisCluster(
99
            null,
100
            $this->getConfig()->getClusters(),
101
            $this->getConfig()->getTimeout(),
102
            $this->getConfig()->getReadTimeout(),
103
            true,
104
            $this->getConfig()->getPassword()
105
        );
106
107
        $this->instance->setOption(RedisCluster::OPT_SCAN, RedisCluster::SCAN_RETRY);
108
109
        if ($this->getConfig()->getOptPrefix()) {
110
            $this->instance->setOption(RedisCluster::OPT_PREFIX, $this->getConfig()->getOptPrefix());
111
        }
112
113
        if ($this->getConfig()->getSlaveFailover()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getConfig()->getSlaveFailover() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
114
            $this->instance->setOption(RedisCluster::OPT_SLAVE_FAILOVER, $this->getConfig()->getSlaveFailover());
115
        }
116
117
118
        return true;
119
    }
120
121
    /**
122
     * @return array<int, string>
123
     */
124
    protected function driverReadAllKeys(string $pattern = '*'): iterable
125
    {
126
        $keys = [[]];
127
        foreach ($this->instance->_masters() as $master) {
128
            $i = -1;
129
            $result = $this->instance->scan(
130
                $i,
131
                $master,
132
                $pattern === '' ? '*' : $pattern,
133
                ExtendedCacheItemPoolInterface::MAX_ALL_KEYS_COUNT
134
            );
135
            if (is_array($result)) {
136
                $keys[] = $result;
137
            }
138
        }
139
140
        return array_unique(array_merge(...$keys));
141
    }
142
143
    /**
144
     * @return bool
145
     */
146
    protected function driverClear(): bool
147
    {
148
        foreach ($this->instance->_masters() as $nodeMaster) {
149
            $this->instance->flushDb($nodeMaster);
150
        }
151
        return true;
152
    }
153
}
154