Passed
Push — v9 ( 473b89...c87345 )
by Georges
02:33
created

ClusterPoolAbstract::getStats()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 37
rs 9.568
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 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\Driver as FullReplicationCluster;
19
use Phpfastcache\Cluster\Drivers\MasterSlaveReplication\Driver as MasterSlaveReplicationCluster;
20
use Phpfastcache\Cluster\Drivers\RandomReplication\Driver as RandomReplicationCluster;
21
use Phpfastcache\Cluster\Drivers\SemiReplication\Driver as SemiReplicationCluster;
22
use Phpfastcache\Config\ConfigurationOption;
23
use Phpfastcache\Core\Item\ExtendedCacheItemInterface;
24
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
25
use Phpfastcache\Core\Pool\TaggableCacheItemPoolTrait;
26
use Phpfastcache\Entities\DriverIO;
27
use Phpfastcache\Entities\DriverStatistic;
28
use Phpfastcache\Event\EventManagerInterface;
29
use Phpfastcache\EventManager;
30
use Phpfastcache\Exceptions\PhpfastcacheCoreException;
31
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
32
use Phpfastcache\Exceptions\PhpfastcacheDriverConnectException;
33
use Phpfastcache\Exceptions\PhpfastcacheDriverException;
34
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
35
use Phpfastcache\Exceptions\PhpfastcacheIOException;
36
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
37
use Psr\Cache\CacheItemInterface;
38
use Psr\Cache\InvalidArgumentException;
39
40
/**
41
 * @property ConfigurationOption $config
42
 */
43
abstract class ClusterPoolAbstract implements ClusterPoolInterface
44
{
45
    use TaggableCacheItemPoolTrait;
46
    use ClusterPoolTrait {
47
        TaggableCacheItemPoolTrait::__construct as private __parentConstruct;
48
    }
49
50
    public const STRATEGY = [
51
        AggregatorInterface::STRATEGY_FULL_REPLICATION => FullReplicationCluster::class,
52
        AggregatorInterface::STRATEGY_SEMI_REPLICATION => SemiReplicationCluster::class,
53
        AggregatorInterface::STRATEGY_MASTER_SLAVE => MasterSlaveReplicationCluster::class,
54
        AggregatorInterface::STRATEGY_RANDOM_REPLICATION => RandomReplicationCluster::class,
55
    ];
56
57
    /**
58
     * @var ExtendedCacheItemPoolInterface[]
59
     */
60
    protected array $clusterPools;
61
62
    /**
63
     * ClusterPoolAbstract constructor.
64
     * @param string $clusterName
65
     * @param EventManagerInterface $em
66
     * @param ExtendedCacheItemPoolInterface ...$driverPools
67
     * @throws PhpfastcacheDriverCheckException
68
     * @throws PhpfastcacheDriverConnectException
69
     * @throws PhpfastcacheInvalidArgumentException
70
     * @throws PhpfastcacheCoreException
71
     * @throws PhpfastcacheDriverException
72
     * @throws PhpfastcacheIOException
73
     */
74
    public function __construct(string $clusterName, EventManagerInterface $em, ExtendedCacheItemPoolInterface ...$driverPools)
75
    {
76
        if (count($driverPools) < 2) {
77
            throw new PhpfastcacheInvalidArgumentException('A cluster requires at least two pools to be working.');
78
        }
79
        $this->clusterPools = $driverPools;
80
        $this->__parentConstruct(new ConfigurationOption(), $clusterName, $em);
81
        $this->setEventManager(EventManager::getInstance());
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87
    public function getIO(): DriverIO
88
    {
89
        $io = new DriverIO();
90
        foreach ($this->clusterPools as $clusterPool) {
91
            $io->setReadHit($io->getReadHit() + $clusterPool->getIO()->getReadHit())
92
                ->setReadMiss($io->getReadMiss() + $clusterPool->getIO()->getReadMiss())
93
                ->setWriteHit($io->getWriteHit() + $clusterPool->getIO()->getWriteHit());
94
        }
95
        return $io;
96
    }
97
98
    /**
99
     * @inheritDoc
100
     */
101
    public function getClusterPools(): array
102
    {
103
        return $this->clusterPools;
104
    }
105
106
    /**
107
     * @inheritDoc
108
     */
109
    public function getConfigs() : array
110
    {
111
        $configs = [];
112
113
        foreach ($this->getClusterPools() as $clusterPool) {
114
            $configs[$clusterPool->getDriverName()] = $clusterPool->getConfig();
115
        }
116
117
        return $configs;
118
    }
119
120
    /**
121
     * @inheritDoc
122
     */
123
    public function getItems(array $keys = []): iterable
124
    {
125
        $items = [];
126
127
        foreach ($keys as $key) {
128
            $items[$key] = $this->getItem($key);
129
        }
130
131
        return $items;
132
    }
133
    /**
134
     * Shared method used by All Clusters
135
     */
136
137
    /**
138
     * @inheritDoc
139
     */
140
    public function deleteItems(array $keys): bool
141
    {
142
        $hasDeletedOnce = false;
143
        foreach ($this->clusterPools as $driverPool) {
144
            if ($result = $driverPool->deleteItems($keys)) {
145
                $hasDeletedOnce = $result;
146
            }
147
        }
148
        // Return true only if at least one backend confirmed the "clear" operation
149
        return $hasDeletedOnce;
150
    }
151
152
    /**
153
     * @param CacheItemInterface $item
154
     * @return bool
155
     * @throws InvalidArgumentException
156
     * @throws PhpfastcacheLogicException
157
     */
158
    public function saveDeferred(CacheItemInterface $item): bool
159
    {
160
        /** @var ExtendedCacheItemInterface $item */
161
        $hasSavedOnce = false;
162
        foreach ($this->clusterPools as $driverPool) {
163
            $poolItem = $this->getStandardizedItem($item, $driverPool);
164
            if ($result = $driverPool->saveDeferred($poolItem)) {
165
                $hasSavedOnce = $result;
166
            }
167
        }
168
        // Return true only if at least one backend confirmed the "commit" operation
169
        return $hasSavedOnce;
170
    }
171
172
    /**
173
     * @param ExtendedCacheItemInterface $item
174
     * @param ExtendedCacheItemPoolInterface $driverPool
175
     * @return ExtendedCacheItemInterface
176
     * @throws InvalidArgumentException
177
     * @throws PhpfastcacheLogicException
178
     */
179
    protected function getStandardizedItem(ExtendedCacheItemInterface $item, ExtendedCacheItemPoolInterface $driverPool): ExtendedCacheItemInterface
180
    {
181
        if (!$item->doesItemBelongToThatDriverBackend($driverPool)) {
182
            /**
183
             * Avoid infinite loop
184
             */
185
            if ($driverPool === $this) {
0 ignored issues
show
introduced by
The condition $driverPool === $this is always false.
Loading history...
186
                /** @var ExtendedCacheItemInterface $itemPool */
187
                $itemClass = $driverPool->getItemClass();
188
                $itemPool = new $itemClass($this, $item->getKey(), $this->getEventManager());
189
                $item->cloneInto($itemPool, $driverPool);
190
191
                return $itemPool;
192
            }
193
194
            $itemPool = $driverPool->getItem($item->getKey());
195
            $item->cloneInto($itemPool, $driverPool);
196
197
            return $itemPool;
198
        }
199
200
        return $item->setEventManager($this->getEventManager());
201
    }
202
203
    /**
204
     * @return DriverStatistic
205
     */
206
    public function getStats(): DriverStatistic
207
    {
208
        $stats = new DriverStatistic();
209
        $stats->setInfo(
210
            sprintf(
211
                'Using %d pool(s): %s',
212
                \count($this->clusterPools),
213
                \implode(
214
                    ', ',
215
                    \array_map(
216
                        static fn (ExtendedCacheItemPoolInterface $pool) => \get_class($pool),
217
                        $this->clusterPools
218
                    )
219
                )
220
            )
221
        );
222
223
        $stats->setSize(
224
            (int)\array_sum(
225
                \array_map(
226
                    static fn (ExtendedCacheItemPoolInterface $pool) => $pool->getStats()->getSize(),
227
                    $this->clusterPools
228
                )
229
            )
230
        );
231
232
        $stats->setData(
233
            \implode(
234
                ', ',
235
                \array_map(
236
                    static fn (ExtendedCacheItemPoolInterface $pool) => $pool->getStats()->getData(),
237
                    $this->clusterPools
238
                )
239
            )
240
        );
241
242
        return $stats;
243
    }
244
245
    public function getConfig() : ConfigurationOption
246
    {
247
        return $this->config;
248
    }
249
}
250