ClusterAggregator::disaggregateDriver()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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