]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/RedisCacheDriver.php
Merge pull request #5813 from MrPetovan/task/update-composer
[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()
45         {
46                 return null;
47         }
48
49         /**
50          * (@inheritdoc)
51          */
52         public function get($key)
53         {
54                 $return = null;
55                 $cachekey = $this->getCacheKey($key);
56
57                 $cached = $this->redis->get($cachekey);
58                 if ($cached === false && !$this->redis->exists($cachekey)) {
59                         return null;
60                 }
61
62                 $value = unserialize($cached);
63
64                 // Only return a value if the serialized value is valid.
65                 // We also check if the db entry is a serialized
66                 // boolean 'false' value (which we want to return).
67                 if ($cached === serialize(false) || $value !== false) {
68                         $return = $value;
69                 }
70
71                 return $return;
72         }
73
74         /**
75          * (@inheritdoc)
76          */
77         public function set($key, $value, $ttl = Cache::FIVE_MINUTES)
78         {
79                 $cachekey = $this->getCacheKey($key);
80
81                 $cached = serialize($value);
82
83                 if ($ttl > 0) {
84                         return $this->redis->setex(
85                                 $cachekey,
86                                 $ttl,
87                                 $cached
88                         );
89                 } else {
90                         return $this->redis->set(
91                                 $cachekey,
92                                 $cached
93                         );
94                 }
95         }
96
97         /**
98          * (@inheritdoc)
99          */
100         public function delete($key)
101         {
102                 $cachekey = $this->getCacheKey($key);
103                 return ($this->redis->delete($cachekey) > 0);
104         }
105
106         /**
107          * (@inheritdoc)
108          */
109         public function clear($outdated = true)
110         {
111                 if ($outdated) {
112                         return true;
113                 } else {
114                         return $this->redis->flushAll();
115                 }
116         }
117
118         /**
119          * (@inheritdoc)
120          */
121         public function add($key, $value, $ttl = Cache::FIVE_MINUTES)
122         {
123                 $cachekey = $this->getCacheKey($key);
124                 $cached = serialize($value);
125
126                 return $this->redis->setnx($cachekey, $cached);
127         }
128
129         /**
130          * (@inheritdoc)
131          */
132         public function compareSet($key, $oldValue, $newValue, $ttl = Cache::FIVE_MINUTES)
133         {
134                 $cachekey = $this->getCacheKey($key);
135
136                 $newCached = serialize($newValue);
137
138                 $this->redis->watch($cachekey);
139                 // If the old value isn't what we expected, somebody else changed the key meanwhile
140                 if ($this->get($key) === $oldValue) {
141                         if ($ttl > 0) {
142                                 $result = $this->redis->multi()
143                                         ->setex($cachekey, $ttl, $newCached)
144                                         ->exec();
145                         } else {
146                                 $result = $this->redis->multi()
147                                         ->set($cachekey, $newValue)
148                                         ->exec();
149                         }
150                         return $result !== false;
151                 }
152                 $this->redis->unwatch();
153                 return false;
154         }
155
156         /**
157          * (@inheritdoc)
158          */
159         public function compareDelete($key, $value)
160         {
161                 $cachekey = $this->getCacheKey($key);
162
163                 $this->redis->watch($cachekey);
164                 // If the old value isn't what we expected, somebody else changed the key meanwhile
165                 if ($this->get($key) === $value) {
166                         $result = $this->redis->multi()
167                                 ->del($cachekey)
168                                 ->exec();
169                         return $result !== false;
170                 }
171                 $this->redis->unwatch();
172                 return false;
173         }
174 }