Completed
Push — master ( 4e7427...4a94bb )
by Georges
12s
created

Driver::driverWrite()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 6
nop 1
dl 0
loc 45
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> https://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
declare(strict_types=1);
15
16
namespace Phpfastcache\Drivers\Cassandra;
17
18
use Cassandra;
0 ignored issues
show
Bug introduced by
The type Cassandra was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use Cassandra\Session as CassandraSession;
0 ignored issues
show
Bug introduced by
The type Cassandra\Session was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use Phpfastcache\Core\Pool\{
21
    DriverBaseTrait, ExtendedCacheItemPoolInterface
22
};
23
use Phpfastcache\Entities\DriverStatistic;
24
use Phpfastcache\Exceptions\{
25
    PhpfastcacheInvalidArgumentException, PhpfastcacheLogicException
26
};
27
use Psr\Cache\CacheItemInterface;
28
29
/**
30
 * Class Driver
31
 * @package phpFastCache\Drivers
32
 * @property CassandraSession $instance Instance of driver service
33
 * @property Config $config Config object
34
 * @method Config getConfig() Return the config object
35
 */
36
class Driver implements ExtendedCacheItemPoolInterface
37
{
38
    const CASSANDRA_KEY_SPACE = 'phpfastcache';
39
    const CASSANDRA_TABLE = 'cacheItems';
40
41
    use DriverBaseTrait;
42
43
    /**
44
     * @return bool
45
     */
46
    public function driverCheck(): bool
47
    {
48
        return \extension_loaded('Cassandra') && \class_exists(\Cassandra::class);
49
    }
50
51
    /**
52
     * @return bool
53
     * @throws PhpfastcacheLogicException
54
     * @throws \Cassandra\Exception
55
     */
56
    protected function driverConnect(): bool
57
    {
58
        if ($this->instance instanceof CassandraSession) {
59
            throw new PhpfastcacheLogicException('Already connected to Couchbase server');
60
        }
61
62
        $clientConfig = $this->getConfig();
63
64
        $clusterBuilder = Cassandra::cluster()
65
            ->withContactPoints($clientConfig->getHost())
66
            ->withPort($clientConfig->getPort());
67
68
        if (!empty($clientConfig->isSslEnabled())) {
69
            if (!empty($clientConfig->isSslVerify())) {
70
                $sslBuilder = Cassandra::ssl()->withVerifyFlags(Cassandra::VERIFY_PEER_CERT);
71
            } else {
72
                $sslBuilder = Cassandra::ssl()->withVerifyFlags(Cassandra::VERIFY_NONE);
73
            }
74
75
            $clusterBuilder->withSSL($sslBuilder->build());
76
        }
77
78
        $clusterBuilder->withConnectTimeout($clientConfig->getTimeout());
79
80
        if ($clientConfig->getUsername()) {
81
            $clusterBuilder->withCredentials($clientConfig->getUsername(), $clientConfig->getPassword());
82
        }
83
84
        $this->instance = $clusterBuilder->build()->connect();
85
86
        /**
87
         * In case of emergency:
88
         * $this->instance->execute(
89
         *      new Cassandra\SimpleStatement(\sprintf("DROP KEYSPACE %s;", self::CASSANDRA_KEY_SPACE))
90
         * );
91
         */
92
93
        $this->instance->execute(new Cassandra\SimpleStatement(\sprintf(
0 ignored issues
show
Bug introduced by
The type Cassandra\SimpleStatement was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
94
            "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };",
95
            self::CASSANDRA_KEY_SPACE
96
        )));
97
        $this->instance->execute(new Cassandra\SimpleStatement(\sprintf('USE %s;', self::CASSANDRA_KEY_SPACE)));
98
        $this->instance->execute(new Cassandra\SimpleStatement(\sprintf('
99
                CREATE TABLE IF NOT EXISTS %s (
100
                    cache_uuid uuid,
101
                    cache_id varchar,
102
                    cache_data text,
103
                    cache_creation_date timestamp,
104
                    cache_expiration_date timestamp,
105
                    cache_length int,
106
                    PRIMARY KEY (cache_id)
107
                );', self::CASSANDRA_TABLE
108
        )));
109
110
        return true;
111
    }
112
113
    /**
114
     * @param \Psr\Cache\CacheItemInterface $item
115
     * @return null|array
116
     */
117
    protected function driverRead(CacheItemInterface $item)
118
    {
119
        try {
120
            $options = new Cassandra\ExecutionOptions([
0 ignored issues
show
Bug introduced by
The type Cassandra\ExecutionOptions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
121
                'arguments' => ['cache_id' => $item->getKey()],
122
                'page_size' => 1,
123
            ]);
124
            $query = \sprintf(
125
                'SELECT cache_data FROM %s.%s WHERE cache_id = :cache_id;',
126
                self::CASSANDRA_KEY_SPACE,
127
                self::CASSANDRA_TABLE
128
            );
129
            $results = $this->instance->execute(new Cassandra\SimpleStatement($query), $options);
130
131
            if ($results instanceof Cassandra\Rows && $results->count() === 1) {
0 ignored issues
show
Bug introduced by
The type Cassandra\Rows was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
132
                return $this->decode($results->first()['cache_data']);
133
            }
134
135
            return null;
136
        } catch (Cassandra\Exception $e) {
0 ignored issues
show
Bug introduced by
The type Cassandra\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
137
            return null;
138
        }
139
    }
140
141
    /**
142
     * @param \Psr\Cache\CacheItemInterface $item
143
     * @return bool
144
     * @throws PhpfastcacheInvalidArgumentException
145
     */
146
    protected function driverWrite(CacheItemInterface $item): bool
147
    {
148
        /**
149
         * Check for Cross-Driver type confusion
150
         */
151
        if ($item instanceof Item) {
152
            try {
153
                $cacheData = $this->encode($this->driverPreWrap($item));
154
                $options = new Cassandra\ExecutionOptions([
155
                    'arguments' => [
156
                        'cache_uuid' => new Cassandra\Uuid(),
0 ignored issues
show
Bug introduced by
The type Cassandra\Uuid was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
157
                        'cache_id' => $item->getKey(),
158
                        'cache_data' => $cacheData,
159
                        'cache_creation_date' => new Cassandra\Timestamp((new \DateTime())->getTimestamp()),
0 ignored issues
show
Bug introduced by
The type Cassandra\Timestamp was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
160
                        'cache_expiration_date' => new Cassandra\Timestamp($item->getExpirationDate()->getTimestamp()),
161
                        'cache_length' => strlen($cacheData),
162
                    ],
163
                    'consistency' => Cassandra::CONSISTENCY_ALL,
164
                    'serial_consistency' => Cassandra::CONSISTENCY_SERIAL,
165
                ]);
166
167
                $query = \sprintf('INSERT INTO %s.%s
168
                    (
169
                      cache_uuid, 
170
                      cache_id, 
171
                      cache_data, 
172
                      cache_creation_date, 
173
                      cache_expiration_date,
174
                      cache_length
175
                    )
176
                  VALUES (:cache_uuid, :cache_id, :cache_data, :cache_creation_date, :cache_expiration_date, :cache_length);
177
            ', self::CASSANDRA_KEY_SPACE, self::CASSANDRA_TABLE);
178
179
                $result = $this->instance->execute(new Cassandra\SimpleStatement($query), $options);
180
                /**
181
                 * There's no real way atm
182
                 * to know if the item has
183
                 * been really upserted
184
                 */
185
                return $result instanceof Cassandra\Rows;
186
            } catch (\Cassandra\Exception\InvalidArgumentException $e) {
0 ignored issues
show
Bug introduced by
The type Cassandra\Exception\InvalidArgumentException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
187
                throw new PhpfastcacheInvalidArgumentException($e, 0, $e);
188
            }
189
        } else {
190
            throw new PhpfastcacheInvalidArgumentException('Cross-Driver type confusion detected');
191
        }
192
    }
193
194
    /**
195
     * @param \Psr\Cache\CacheItemInterface $item
196
     * @return bool
197
     * @throws PhpfastcacheInvalidArgumentException
198
     */
199
    protected function driverDelete(CacheItemInterface $item): bool
200
    {
201
        /**
202
         * Check for Cross-Driver type confusion
203
         */
204
        if ($item instanceof Item) {
205
            try {
206
                $options = new Cassandra\ExecutionOptions([
207
                    'arguments' => [
208
                        'cache_id' => $item->getKey(),
209
                    ],
210
                ]);
211
                $result = $this->instance->execute(new Cassandra\SimpleStatement(\sprintf(
212
                    'DELETE FROM %s.%s WHERE cache_id = :cache_id;',
213
                    self::CASSANDRA_KEY_SPACE,
214
                    self::CASSANDRA_TABLE
215
                )), $options);
216
217
                /**
218
                 * There's no real way atm
219
                 * to know if the item has
220
                 * been really deleted
221
                 */
222
                return $result instanceof Cassandra\Rows;
223
            } catch (Cassandra\Exception $e) {
224
                return false;
225
            }
226
        } else {
227
            throw new PhpfastcacheInvalidArgumentException('Cross-Driver type confusion detected');
228
        }
229
    }
230
231
    /**
232
     * @return bool
233
     */
234
    protected function driverClear(): bool
235
    {
236
        try {
237
            $this->instance->execute(new Cassandra\SimpleStatement(\sprintf(
238
                'TRUNCATE %s.%s;',
239
                self::CASSANDRA_KEY_SPACE, self::CASSANDRA_TABLE
240
            )));
241
242
            return true;
243
        } catch (Cassandra\Exception $e) {
244
            return false;
245
        }
246
    }
247
248
    /********************
249
     *
250
     * PSR-6 Extended Methods
251
     *
252
     *******************/
253
254
    /**
255
     * @return string
256
     */
257
    public function getHelp(): string
258
    {
259
        return <<<HELP
260
<p>
261
To install the php Cassandra extension via Pecl:
262
<code>sudo pecl install cassandra</code>
263
More information on: https://github.com/datastax/php-driver
264
Please not that this repository only provide php stubs and C/C++ sources, it does NOT provide php client.
265
</p>
266
HELP;
267
    }
268
269
    /**
270
     * @return DriverStatistic
271
     * @throws \Cassandra\Exception
272
     */
273
    public function getStats(): DriverStatistic
274
    {
275
        $result = $this->instance->execute(new Cassandra\SimpleStatement(\sprintf(
276
            'SELECT SUM(cache_length) as cache_size FROM %s.%s',
277
            self::CASSANDRA_KEY_SPACE,
278
            self::CASSANDRA_TABLE
279
        )));
280
281
        return (new DriverStatistic())
282
            ->setSize($result->first()['cache_size'])
283
            ->setRawData([])
284
            ->setData(\implode(', ', \array_keys($this->itemInstances)))
285
            ->setInfo('The cache size represents only the cache data itself without counting data structures associated to the cache entries.');
286
    }
287
}