| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  | // This file is part of GNU social - https://www.gnu.org/software/social
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GNU social is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with GNU social.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-08-10 11:12:31 +03:00
										 |  |  |  * Plugin inplementing Redis based caching | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @category  Files | 
					
						
							|  |  |  |  * @package   GNUsocial | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |  * @author    Stéphane Bérubé <chimo@chromic.org> | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |  * @author    Miguel Dantas <biodantas@gmail.com> | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |  * @copyright 2018, 2019 Free Software Foundation, Inc http://www.fsf.org | 
					
						
							|  |  |  |  * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | defined('GNUSOCIAL') || die(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  | use Predis\Client; | 
					
						
							|  |  |  | use Predis\PredisException; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  | class RedisCachePlugin extends Plugin | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-11 02:20:54 +00:00
										 |  |  |     const PLUGIN_VERSION = '0.1.0'; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |     // settings which can be set in config.php with addPlugin('Embed', ['param'=>'value', ...]);
 | 
					
						
							|  |  |  |     public $server = null; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     public $defaultExpiry = 86400; // 24h
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |     protected $client = null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |     public function onInitializePlugin() | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->_ensureConn(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private function _ensureConn() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($this->client === null) { | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             $this->client = new Client($this->server); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |     public function onStartCacheGet($key, &$value) | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $this->_ensureConn(); | 
					
						
							| 
									
										
										
										
											2020-08-10 11:12:31 +03:00
										 |  |  |             $data = $this->client->get($key); | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         } catch (PredisException $e) { | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             common_log(LOG_ERR, 'RedisCache encountered exception ' . get_class($e) . ': ' . $e->getMessage()); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:12:31 +03:00
										 |  |  |         if (is_null($data)) { | 
					
						
							|  |  |  |             // Miss, let GS do its thing
 | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:12:31 +03:00
										 |  |  |         $ret = unserialize($data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($ret === false && $data !== 'b:0;') { | 
					
						
							|  |  |  |             common_log(LOG_ERR, 'RedisCache could not handle: ' . $data); | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Hit, overwrite "value" and return false
 | 
					
						
							|  |  |  |         // to indicate we took care of this
 | 
					
						
							|  |  |  |         $value = $ret; | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |     public function onStartCacheSet($key, $value, $flag, $expiry, &$success) | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         $success = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_null($expiry)) { | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |             $expiry = $this->defaultExpiry; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $this->_ensureConn(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $ret = $this->client->setex($key, $expiry, serialize($value)); | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         } catch (PredisException $e) { | 
					
						
							|  |  |  |             $ret = false; | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             common_log(LOG_ERR, 'RedisCache encountered exception ' . get_class($e) . ': ' . $e->getMessage()); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         if (is_bool($ret) | 
					
						
							|  |  |  |             || is_numeric($ret)) { | 
					
						
							|  |  |  |             $success = ($ret ? true : false); | 
					
						
							|  |  |  |         } elseif (is_object($ret) && method_exists($ret, 'getPayload')) { | 
					
						
							|  |  |  |             $success = ($ret->getPayload() === 'OK'); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         return !$success; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |     public function onStartCacheDelete($key) | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |         if ($key === null) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         try { | 
					
						
							|  |  |  |             $this->_ensureConn(); | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             $ret = $this->client->del($key); | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         } catch (PredisException $e) { | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             common_log(LOG_ERR, 'RedisCache encountered exception ' . get_class($e) . ': ' . $e->getMessage()); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |         // Let other caches delete stuff if we didn't succeed
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:53:57 +01:00
										 |  |  |         return isset($ret) && $ret === 1; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |     public function onStartCacheIncrement($key, $step, $value) | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $this->_ensureConn(); | 
					
						
							|  |  |  |             $this->client->incrby($key, $step); | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |         } catch (PredisException $e) { | 
					
						
							| 
									
										
										
										
											2019-08-13 02:52:35 +01:00
										 |  |  |             common_log(LOG_ERR, 'RedisCache encountered exception ' . get_class($e) . ': ' . $e->getMessage()); | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 15:03:30 +01:00
										 |  |  |     public function onPluginVersion(array &$versions): bool | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-12-11 02:20:54 +00:00
										 |  |  |         $versions[] = [ | 
					
						
							|  |  |  |             'name' => 'RedisCache', | 
					
						
							| 
									
										
										
										
											2020-07-06 20:10:12 +03:00
										 |  |  |             'version' => self::PLUGIN_VERSION, | 
					
						
							| 
									
										
										
										
											2019-12-11 02:20:54 +00:00
										 |  |  |             'author' => 'Stéphane Bérubé (chimo)', | 
					
						
							|  |  |  |             'homepage' => 'https://github.com/chimo/gs-rediscache', | 
					
						
							|  |  |  |             'description' => | 
					
						
							|  |  |  |             // TRANS: Plugin description.
 | 
					
						
							|  |  |  |             _m('Plugin implementing Redis as a backend for GNU social caching') | 
					
						
							|  |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2019-08-13 01:31:05 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |