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