Completed
Push — master ( be9660...707803 )
by Georges
16s queued 13s
created

ClusterPoolAbstract   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 193
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 79
c 1
b 0
f 0
dl 0
loc 193
rs 10
wmc 17

8 Methods

Rating   Name   Duplication   Size   Complexity  
A deleteItems() 0 10 3
A getItems() 0 9 2
A getStandardizedItem() 0 28 3
A getStats() 0 40 1
A getIO() 0 9 2
A saveDeferred() 0 12 3
A __construct() 0 8 2
A getClusterPools() 0 3 1
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 file.
10
 *
11
 * @author  Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
declare(strict_types=1);
15
16
namespace Phpfastcache\Cluster;
17
18
use Phpfastcache\Cluster\Drivers\{FullReplication\FullReplicationCluster,
19
    MasterSlaveReplication\MasterSlaveReplicationCluster,
20
    RandomReplication\RandomReplicationCluster,
21
    SemiReplication\SemiReplicationCluster
22
};
23
use Phpfastcache\Config\ConfigurationOption;
24
use Phpfastcache\Core\{Item\ExtendedCacheItemInterface, Pool\DriverBaseTrait, Pool\ExtendedCacheItemPoolInterface};
25
use Phpfastcache\Entities\DriverIO;
26
use Phpfastcache\Entities\DriverStatistic;
27
use Phpfastcache\EventManager;
28
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
29
use Phpfastcache\Exceptions\PhpfastcacheDriverConnectException;
30
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
31
use Phpfastcache\Exceptions\PhpfastcacheInvalidConfigurationException;
32
use Psr\Cache\{CacheItemInterface, InvalidArgumentException};
33
use ReflectionException;
34
35
/**
36
 * Class ClusterAbstract
37
 *
38
 * @package Phpfastcache\Cluster
39
 */
40
abstract class ClusterPoolAbstract implements ClusterPoolInterface
41
{
42
    use DriverBaseTrait;
43
    use ClusterPoolTrait {
44
        DriverBaseTrait::__construct as private __parentConstruct;
45
    }
46
47
    public const STRATEGY = [
48
        AggregatorInterface::STRATEGY_FULL_REPLICATION => FullReplicationCluster::class,
49
        AggregatorInterface::STRATEGY_SEMI_REPLICATION => SemiReplicationCluster::class,
50
        AggregatorInterface::STRATEGY_MASTER_SLAVE => MasterSlaveReplicationCluster::class,
51
        AggregatorInterface::STRATEGY_RANDOM_REPLICATION => RandomReplicationCluster::class,
52
    ];
53
54
    /**
55
     * @var ExtendedCacheItemPoolInterface[]
56
     */
57
    protected $clusterPools;
58
59
    /**
60
     * ClusterPoolAbstract constructor.
61
     * @param string $clusterName
62
     * @param ExtendedCacheItemPoolInterface ...$driverPools
63
     * @throws PhpfastcacheInvalidArgumentException
64
     * @throws PhpfastcacheDriverCheckException
65
     * @throws PhpfastcacheDriverConnectException
66
     * @throws PhpfastcacheInvalidConfigurationException
67
     * @throws ReflectionException
68
     */
69
    public function __construct(string $clusterName, ExtendedCacheItemPoolInterface ...$driverPools)
70
    {
71
        if (count($driverPools) < 2) {
72
            throw new PhpfastcacheInvalidArgumentException('A cluster requires at least two pools to be working.');
73
        }
74
        $this->clusterPools = $driverPools;
75
        $this->__parentConstruct(new ConfigurationOption(), $clusterName);
76
        $this->setEventManager(EventManager::getInstance());
77
    }
78
79
    /**
80
     * @inheritDoc
81
     */
82
    public function getIO(): DriverIO
83
    {
84
        $IO = new DriverIO();
85
        foreach ($this->clusterPools as $clusterPool) {
86
            $IO->setReadHit($IO->getReadHit() + $clusterPool->getIO()->getReadHit())
87
                ->setReadMiss($IO->getReadMiss() + $clusterPool->getIO()->getReadMiss())
88
                ->setWriteHit($IO->getWriteHit() + $clusterPool->getIO()->getWriteHit());
89
        }
90
        return $IO;
91
    }
92
93
    /**
94
     * @inheritDoc
95
     */
96
    public function getClusterPools(): array
97
    {
98
        return $this->clusterPools;
99
    }
100
101
    /**
102
     * @inheritDoc
103
     */
104
    public function getItems(array $keys = [])
105
    {
106
        $items = [];
107
108
        foreach ($keys as $key) {
109
            $items[$key] = $this->getItem($key);
110
        }
111
112
        return $items;
113
    }
114
    /**
115
     * Shared method used by All Clusters
116
     */
117
118
    /**
119
     * @inheritDoc
120
     */
121
    public function deleteItems(array $keys)
122
    {
123
        $hasDeletedOnce = false;
124
        foreach ($this->clusterPools as $driverPool) {
125
            if ($result = $driverPool->deleteItems($keys)) {
126
                $hasDeletedOnce = $result;
127
            }
128
        }
129
        // Return true only if at least one backend confirmed the "clear" operation
130
        return $hasDeletedOnce;
131
    }
132
133
    /**
134
     * @inheritDoc
135
     */
136
    public function saveDeferred(CacheItemInterface $item)
137
    {
138
        /** @var ExtendedCacheItemInterface $item */
139
        $hasSavedOnce = false;
140
        foreach ($this->clusterPools as $driverPool) {
141
            $poolItem = $this->getStandardizedItem($item, $driverPool);
142
            if ($result = $driverPool->saveDeferred($poolItem)) {
143
                $hasSavedOnce = $result;
144
            }
145
        }
146
        // Return true only if at least one backend confirmed the "commit" operation
147
        return $hasSavedOnce;
148
    }
149
150
    /**
151
     * @param ExtendedCacheItemInterface $item
152
     * @param ExtendedCacheItemPoolInterface $driverPool
153
     * @return CacheItemInterface
154
     * @throws InvalidArgumentException
155
     */
156
    protected function getStandardizedItem(ExtendedCacheItemInterface $item, ExtendedCacheItemPoolInterface $driverPool): CacheItemInterface
157
    {
158
        if (!$item->doesItemBelongToThatDriverBackend($driverPool)) {
159
            /**
160
             * Avoid infinite loop
161
             */
162
            if ($driverPool === $this) {
0 ignored issues
show
introduced by
The condition $driverPool === $this is always false.
Loading history...
163
                /** @var ExtendedCacheItemInterface $itemPool */
164
                $itemClass = $driverPool->getClassNamespace() . '\\' . 'Item';
165
                $itemPool = new $itemClass($this, $item->getKey());
166
                $itemPool->setEventManager($this->getEventManager())
167
                    ->set($item->get())
168
                    ->setHit($item->isHit())
169
                    ->setTags($item->getTags())
170
                    ->expiresAt($item->getExpirationDate())
171
                    ->setDriver($driverPool);
172
                return $itemPool;
173
            }
174
            return $driverPool->getItem($item->getKey())
175
                ->setEventManager($this->getEventManager())
176
                ->set($item->get())
0 ignored issues
show
Bug introduced by
The method set() does not exist on Phpfastcache\Event\EventManagerDispatcherInterface. It seems like you code against a sub-type of Phpfastcache\Event\EventManagerDispatcherInterface such as Phpfastcache\Core\Item\ExtendedCacheItemInterface. ( Ignorable by Annotation )

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

176
                ->/** @scrutinizer ignore-call */ set($item->get())
Loading history...
177
                ->setHit($item->isHit())
178
                ->setTags($item->getTags())
179
                ->expiresAt($item->getExpirationDate())
180
                ->setDriver($driverPool);
181
        }
182
183
        return $item->setEventManager($this->getEventManager());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $item->setEventMa...his->getEventManager()) returns the type Phpfastcache\Event\EventManagerDispatcherInterface which is incompatible with the type-hinted return Psr\Cache\CacheItemInterface.
Loading history...
184
    }
185
186
    /**
187
     * Interfaced methods that needs to be faked
188
     */
189
190
    /**
191
     * @return DriverStatistic
192
     */
193
    public function getStats(): DriverStatistic
194
    {
195
        $stats = new DriverStatistic();
196
        $stats->setInfo(
197
            sprintf(
198
                'Using %d pool(s): %s',
199
                \count($this->clusterPools),
200
                \implode(
201
                    ', ',
202
                    \array_map(
203
                        static function (ExtendedCacheItemPoolInterface $pool) {
204
                            return \get_class($pool);
205
                        },
206
                        $this->clusterPools
207
                    )
208
                )
209
            )
210
        );
211
212
        $stats->setSize(
213
            (int)\array_sum(
214
                \array_map(
215
                    static function (ExtendedCacheItemPoolInterface $pool) {
216
                        return $pool->getStats()->getSize();
217
                    },
218
                    $this->clusterPools
219
                )
220
            )
221
        );
222
223
        $stats->setData(
224
            (int)\array_map(
225
                static function (ExtendedCacheItemPoolInterface $pool) {
226
                    return $pool->getStats()->getData();
227
                },
228
                $this->clusterPools
229
            )
230
        );
231
232
        return $stats;
233
    }
234
}
235