Completed
Pull Request — master (#46)
by Klaus
09:50
created

AerospikeAdapter::__construct()   B

Complexity

Conditions 8
Paths 65

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 42
rs 8.0035
c 0
b 0
f 0
cc 8
nc 65
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Linio\Component\Cache\Adapter;
6
7
use Aerospike;
8
use Linio\Component\Cache\Exception\InvalidConfigurationException;
9
use Linio\Component\Cache\Exception\KeyNotFoundException;
10
11
class AerospikeAdapter extends AbstractAdapter implements AdapterInterface
12
{
13
    const BIN_KEY = 'v';
14
    const DEFAULT_AEROSPIKE_NAMESPACE = 'test';
15
16
    protected Aerospike $db;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
17
    protected string $aerospikeNamespace;
18
    protected int $ttl = 0;
19
20
    public function __construct(array $config)
21
    {
22
        $aerospikeConfig = [];
23
24
        if (!isset($config['hosts'])) {
25
            throw new InvalidConfigurationException('Missing configuration parameter: hosts');
26
        }
27
28
        // default options
29
        $persistent = true;
30
        $options = [];
31
        $this->ttl = 0;
32
33
        if (isset($config['persistent'])) {
34
            $persistent = (bool) $config['persistent'];
35
        }
36
37
        if (isset($config['options'])) {
38
            $options = $config['options'];
39
        }
40
41
        if (isset($config['ttl'])) {
42
            $this->ttl = (int) $config['ttl'];
43
        }
44
45
        if (isset($config['cache_not_found_keys'])) {
46
            $this->cacheNotFoundKeys = (bool) $config['cache_not_found_keys'];
47
        }
48
49
        if (isset($config['aerospike_namespace'])) {
50
            $this->aerospikeNamespace = $config['aerospike_namespace'];
51
        } else {
52
            $this->aerospikeNamespace = self::DEFAULT_AEROSPIKE_NAMESPACE;
53
        }
54
55
        $aerospikeConfig['hosts'] = $config['hosts'];
56
57
        $this->db = new \Aerospike($aerospikeConfig, $persistent, $options);
58
        if (!$this->db->isConnected()) {
59
            throw new \RuntimeException("Failed to connect to Aerospike Server [{$this->db->errorno()}]: {$this->db->error()}\n");
60
        }
61
    }
62
63
    /**
64
     * @return mixed
65
     */
66
    public function get(string $key)
67
    {
68
        $namespacedKey = $this->getNamespacedKey($key);
69
        $status = $this->db->get($namespacedKey, $metadata);
70
71
        if ($status != \Aerospike::OK) {
72
            throw new KeyNotFoundException();
73
        }
74
75
        return $this->removeBin($metadata);
76
    }
77
78
    public function getMulti(array $keys): array
79
    {
80
        $namespacedKeys = [];
81
        foreach ($keys as $key) {
82
            $namespacedKeys[] = $this->getNamespacedKey($key);
83
        }
84
85
        $status = $this->db->getMany($namespacedKeys, $result);
86
        if ($status != \Aerospike::OK) {
87
            return [];
88
        }
89
90
        $values = [];
91
        foreach ($result as $entry) {
92
            $key = $entry['key']['key'];
93
            $value = $this->removeBin($entry);
94
95
            if ($value === null) {
96
                continue;
97
            }
98
99
            $values[$key] = $value;
100
        }
101
102
        return $values;
103
    }
104
105
    /**
106
     * @param mixed $value
107
     */
108
    public function set(string $key, $value): bool
109
    {
110
        $status = $this->db->put($this->getNamespacedKey($key), $this->createBin($value), $this->ttl);
111
112
        return $status == \Aerospike::OK;
113
    }
114
115
    public function setMulti(array $data): bool
116
    {
117
        $success = true;
118
        foreach ($data as $key => $value) {
119
            $success = $success && $this->set($key, $value);
120
        }
121
122
        return $success;
123
    }
124
125
    public function contains(string $key): bool
126
    {
127
        $status = $this->db->exists($this->getNamespacedKey($key), $metadata);
128
129
        return $status == \Aerospike::OK;
130
    }
131
132
    public function delete(string $key): bool
133
    {
134
        $namespacedKey = $this->getNamespacedKey($key);
135
136
        $this->db->remove($namespacedKey);
137
138
        return true;
139
    }
140
141
    public function deleteMulti(array $keys): bool
142
    {
143
        foreach ($keys as $key) {
144
            $this->delete($key);
145
        }
146
147
        return true;
148
    }
149
150
    public function flush(): bool
151
    {
152
        $this->db->scan(
153
            $this->aerospikeNamespace,
154
            $this->namespace,
155
            function ($record): void {
156
                unset($record['key']['key']);
157
                $this->db->remove($record['key']);
158
            }
159
        );
160
161
        return true;
162
    }
163
164
    protected function getNamespacedKey(string $key): array
165
    {
166
        return $this->db->initKey($this->aerospikeNamespace, str_replace([':', '.'], '_', $this->namespace), $key);
167
    }
168
169
    /**
170
     * @param mixed $value
171
     */
172
    protected function createBin($value): array
173
    {
174
        return [self::BIN_KEY => $value];
175
    }
176
177
    /**
178
     * @param mixed $metadata
179
     */
180
    protected function removeBin($metadata): ?string
181
    {
182
        if (!is_array($metadata) || !array_key_exists('bins', $metadata) || !is_array($metadata['bins']) || !array_key_exists(static::BIN_KEY, $metadata['bins'])) {
183
            return null;
184
        }
185
186
        return $metadata['bins'][static::BIN_KEY];
187
    }
188
}
189