]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/RedisCacheDriver.php
Fixing redis cachekey
[friendica.git] / src / Core / Cache / RedisCacheDriver.php
1 <?php
2
3 namespace Friendica\Core\Cache;
4
5 use Exception;
6 use Friendica\Core\Cache;
7 use Redis;
8
9 /**
10  * Redis Cache Driver. This driver is based on Memcache driver
11  *
12  * @author Hypolite Petovan <hypolite@mrpetovan.com>
13  * @author Roland Haeder <roland@mxchange.org>
14  */
15 class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
16 {
17         /**
18          * @var Redis
19          */
20         private $redis;
21
22         /**
23          * @param string $redis_host
24          * @param int    $redis_port
25          * @throws Exception
26          */
27         public function __construct($redis_host, $redis_port)
28         {
29                 if (!class_exists('Redis', false)) {
30                         throw new Exception('Redis class isn\'t available');
31                 }
32
33                 $this->redis = new Redis();
34
35                 if (!$this->redis->connect($redis_host, $redis_port)) {
36                         throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
37                 }
38         }
39
40         /**
41          * (@inheritdoc)
42          */
43         public function getAllKeys($prefix = null)
44         {
45                 if (empty($prefix)) {
46                         $search = '*';
47                 } else {
48                         $search = $prefix . '*';
49                 }
50
51                 $list = $this->redis->keys($this->getCacheKey($search));
52
53                 return $this->getOriginalKeys($list);
54         }
55
56         /**
57          * (@inheritdoc)
58          */
59         public function get($key)
60         {
61                 $return = null;
62                 $cachekey = $this->getCacheKey($key);
63
64                 $cached = $this->redis->get($cachekey);
65                 if ($cached === false && !$this->redis->exists($cachekey)) {
66                         return null;
67                 }
68
69                 $value = unserialize($cached);
70
71                 // Only return a value if the serialized value is valid.
72                 // We also check if the db entry is a serialized
73                 // boolean 'false' value (which we want to return).
74                 if ($cached === serialize(false) || $value !== false) {
75                         $return = $value;
76                 }
77
78                 return $return;
79         }
80
81         /**
82          * (@inheritdoc)
83          */
84         public function set($key, $value, $ttl = Cache::FIVE_MINUTES)
85         {
86                 $cachekey = $this->getCacheKey($key);
87
88                 $cached = serialize($value);
89
90                 if ($ttl > 0) {
91                         return $this->redis->setex(
92                                 $cachekey,
93                                 $ttl,
94                                 $cached
95                         );
96                 } else {
97                         return $this->redis->set(
98                                 $cachekey,
99                                 $cached
100                         );
101                 }
102         }
103
104         /**
105          * (@inheritdoc)
106          */
107         public function delete($key)
108         {
109                 $cachekey = $this->getCacheKey($key);
110                 return ($this->redis->delete($cachekey) > 0);
111         }
112
113         /**
114          * (@inheritdoc)
115          */
116         public function clear($outdated = true)
117         {
118                 if ($outdated) {
119                         return true;
120                 } else {
121                         return $this->redis->flushAll();
122                 }
123         }
124
125         /**
126          * (@inheritdoc)
127          */
128         public function add($key, $value, $ttl = Cache::FIVE_MINUTES)
129         {
130                 $cachekey = $this->getCacheKey($key);
131                 $cached = serialize($value);
132
133                 return $this->redis->setnx($cachekey, $cached);
134         }
135
136         /**
137          * (@inheritdoc)
138          */
139         public function compareSet($key, $oldValue, $newValue, $ttl = Cache::FIVE_MINUTES)
140         {
141                 $cachekey = $this->getCacheKey($key);
142
143                 $newCached = serialize($newValue);
144
145                 $this->redis->watch($cachekey);
146                 // If the old value isn't what we expected, somebody else changed the key meanwhile
147                 if ($this->get($cachekey) === $oldValue) {
148                         if ($ttl > 0) {
149                                 $result = $this->redis->multi()
150                                         ->setex($cachekey, $ttl, $newCached)
151                                         ->exec();
152                         } else {
153                                 $result = $this->redis->multi()
154                                         ->set($cachekey, $newValue)
155                                         ->exec();
156                         }
157                         return $result !== false;
158                 }
159                 $this->redis->unwatch();
160                 return false;
161         }
162
163         /**
164          * (@inheritdoc)
165          */
166         public function compareDelete($key, $value)
167         {
168                 $cachekey = $this->getCacheKey($key);
169
170                 $this->redis->watch($cachekey);
171                 // If the old value isn't what we expected, somebody else changed the key meanwhile
172                 if ($this->get($cachekey) === $value) {
173                         $result = $this->redis->multi()
174                                 ->del($cachekey)
175                                 ->exec();
176                         return $result !== false;
177                 }
178                 $this->redis->unwatch();
179                 return false;
180         }
181 }