Passed
Push — v9 ( 555fde...51468f )
by Georges
01:56
created

ClusterAggregator::getCluster()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 22
rs 9.9332
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 Exception;
19
use Phpfastcache\CacheManager;
20
use Phpfastcache\Config\ConfigurationOption;
21
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
22
use Phpfastcache\Exceptions\PhpfastcacheDriverException;
23
use Phpfastcache\Exceptions\PhpfastcacheDriverNotFoundException;
24
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
25
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
26
use stdClass;
27
28
class ClusterAggregator implements AggregatorInterface
29
{
30
    /**
31
     * @var array<string, AggregatablePoolInterface>
32
     */
33
    protected array $driverPools;
34
35
    protected ClusterPoolInterface $cluster;
36
37
    protected string $clusterAggregatorName;
38
39
    /**
40
     * ClusterAggregator constructor.
41
     * @param string $clusterAggregatorName
42
     * @param array<AggregatablePoolInterface> $driverPools
43
     * @throws PhpfastcacheLogicException
44
     */
45
    public function __construct(string $clusterAggregatorName = '', AggregatablePoolInterface ...$driverPools)
46
    {
47
        $clusterAggregatorName = trim($clusterAggregatorName);
48
        if (empty($clusterAggregatorName)) {
49
            try {
50
                $clusterAggregatorName = 'cluster_' . \bin2hex(\random_bytes(15));
51
            } catch (Exception) {
52
                $clusterAggregatorName = 'cluster_' . \str_shuffle(\spl_object_hash(new stdClass()));
53
            }
54
        }
55
56
        $this->clusterAggregatorName = $clusterAggregatorName;
57
58
        foreach ($driverPools as $driverPool) {
59
            $this->aggregateDriver($driverPool);
60
        }
61
    }
62
63
    /**
64
     * @param AggregatablePoolInterface $driverPool
65
     *
66
     * @throws PhpfastcacheLogicException
67
     */
68
    public function aggregateDriver(AggregatablePoolInterface $driverPool): void
69
    {
70
        if (isset($this->cluster)) {
71
            throw new PhpfastcacheLogicException('The cluster has been already build, cannot aggregate more pools.');
72
        }
73
74
        $splHash = \spl_object_hash($driverPool);
75
        if (!isset($this->driverPools[$splHash])) {
76
            if ($driverPool instanceof ClusterPoolInterface) {
77
                throw new PhpfastcacheLogicException('Recursive cluster aggregation is not allowed !');
78
            }
79
80
            $this->driverPools[$splHash] = $driverPool;
81
        } else {
82
            throw new PhpfastcacheLogicException('This pool has been already aggregated !');
83
        }
84
    }
85
86
    /**
87
     * @param string $driverName
88
     * @param ConfigurationOption|null $driverConfig
89
     * @throws PhpfastcacheDriverCheckException
90
     * @throws PhpfastcacheDriverException
91
     * @throws PhpfastcacheDriverNotFoundException
92
     * @throws PhpfastcacheLogicException
93
     */
94
    public function aggregateDriverByName(string $driverName, ConfigurationOption $driverConfig = null): void
95
    {
96
        if (isset($this->cluster)) {
97
            throw new PhpfastcacheLogicException('The cluster has been already build, cannot aggregate more pools.');
98
        }
99
100
        $driverInstance = CacheManager::getInstance($driverName, $driverConfig);
101
102
        if ($driverInstance instanceof AggregatablePoolInterface) {
103
            $this->aggregateDriver($driverInstance);
104
        }
105
106
        throw new PhpfastcacheDriverException(
107
            \sprintf(
108
                'Driver "%s" does not implements "%s"',
109
                $driverInstance::class,
110
                AggregatablePoolInterface::class
111
            )
112
        );
113
    }
114
115
    /**
116
     * @param AggregatablePoolInterface $driverPool
117
     *
118
     * @throws PhpfastcacheLogicException
119
     */
120
    public function disaggregateDriver(AggregatablePoolInterface $driverPool): void
121
    {
122
        if (isset($this->cluster)) {
123
            throw new PhpfastcacheLogicException('The cluster has been already build, cannot disaggregate pools.');
124
        }
125
126
        $splHash = \spl_object_hash($driverPool);
127
        if (isset($this->driverPools[$splHash])) {
128
            unset($this->driverPools[$splHash]);
129
        } else {
130
            throw new PhpfastcacheLogicException('This pool was not aggregated !');
131
        }
132
    }
133
134
    /**
135
     * @param int $strategy
136
     *
137
     * @return ClusterPoolInterface
138
     * @throws PhpfastcacheInvalidArgumentException
139
     */
140
    public function getCluster(int $strategy = AggregatorInterface::STRATEGY_FULL_REPLICATION): ClusterPoolInterface
141
    {
142
        if (isset(ClusterPoolAbstract::STRATEGY[$strategy])) {
143
            if (!isset($this->cluster)) {
144
                $clusterClass = ClusterPoolAbstract::STRATEGY[$strategy];
145
                $this->cluster = new $clusterClass(
146
                    $this->getClusterAggregatorName(),
147
                    ...\array_values($this->driverPools)
148
                );
149
150
                /**
151
                 * @eventName CacheClusterBuilt
152
                 * @param $clusterAggregator AggregatorInterface
153
                 * @param $cluster ClusterPoolInterface
154
                 */
155
                $this->cluster->getEventManager()->dispatch('CacheClusterBuilt', $this, $this->cluster);
156
            }
157
        } else {
158
            throw new PhpfastcacheInvalidArgumentException('Unknown cluster strategy');
159
        }
160
161
        return $this->cluster;
162
    }
163
164
    /**
165
     * @return string
166
     */
167
    public function getClusterAggregatorName(): string
168
    {
169
        return $this->clusterAggregatorName;
170
    }
171
}
172