Version Description
- Added graceful Redis failures and
WP_REDIS_GRACEFUL
constant- Improved cluster support
- Added
redis_cache_expiration
filter - Renamed
redis_object_cache_get
filter toredis_object_cache_get_value
Download this release
Release Info
Developer | tillkruess |
Plugin | Redis Object Cache |
Version | 1.4.2 |
Comparing to | |
See all releases |
Code changes from version 1.4.1 to 1.4.2
- includes/admin-page.php +7 -1
- includes/diagnostics.php +1 -1
- includes/object-cache.php +201 -82
- includes/servers-list.php +9 -5
- includes/wp-cli-commands.php +6 -6
- readme.txt +17 -2
- redis-cache.php +1 -1
includes/admin-page.php
CHANGED
@@ -5,7 +5,13 @@
|
|
5 |
|
6 |
<h1><?php _e( 'Redis Object Cache', 'redis-cache' ); ?></h1>
|
7 |
|
8 |
-
<?php if (
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
<div class="card">
|
10 |
<h2 class="title">
|
11 |
<?php _e( 'Are your email addresses protected?', 'redis-cache' ); ?>
|
5 |
|
6 |
<h1><?php _e( 'Redis Object Cache', 'redis-cache' ); ?></h1>
|
7 |
|
8 |
+
<?php if (
|
9 |
+
defined( 'EAE_DISABLE_NOTICES' ) ||
|
10 |
+
! is_plugin_active( 'email-address-encoder' ) &&
|
11 |
+
! is_plugin_active( 'email-encoder-premium' ) &&
|
12 |
+
! is_plugin_inactive( 'email-address-encoder' ) &&
|
13 |
+
! is_plugin_inactive( 'email-encoder-premium' )
|
14 |
+
) : ?>
|
15 |
<div class="card">
|
16 |
<h2 class="title">
|
17 |
<?php _e( 'Are your email addresses protected?', 'redis-cache' ); ?>
|
includes/diagnostics.php
CHANGED
@@ -13,7 +13,7 @@ $info[ 'Drop-in' ] = $dropin ? 'Valid' : 'Invalid';
|
|
13 |
if ( $dropin ) {
|
14 |
try {
|
15 |
$cache = new WP_Object_Cache( false );
|
16 |
-
$info[ 'Ping' ] = $cache->redis_instance()->ping();
|
17 |
} catch ( Exception $exception ) {
|
18 |
$info[ 'Connection Exception' ] = sprintf( '%s (%s)', $exception->getMessage(), get_class( $exception ) );
|
19 |
}
|
13 |
if ( $dropin ) {
|
14 |
try {
|
15 |
$cache = new WP_Object_Cache( false );
|
16 |
+
$info[ 'Ping' ] = defined( 'WP_REDIS_CLUSTER' ) ? 'Not supported' : $cache->redis_instance()->ping();
|
17 |
} catch ( Exception $exception ) {
|
18 |
$info[ 'Connection Exception' ] = sprintf( '%s (%s)', $exception->getMessage(), get_class( $exception ) );
|
19 |
}
|
includes/object-cache.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Redis Object Cache Drop-In
|
4 |
Plugin URI: http://wordpress.org/plugins/redis-cache/
|
5 |
Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, HHVM, replication, clustering and WP-CLI.
|
6 |
-
Version: 1.4.
|
7 |
Author: Till Krüss
|
8 |
Author URI: https://till.im/
|
9 |
License: GPLv3
|
@@ -180,10 +180,15 @@ function wp_cache_init()
|
|
180 |
global $wp_object_cache;
|
181 |
|
182 |
if (! ($wp_object_cache instanceof WP_Object_Cache)) {
|
183 |
-
$
|
|
|
|
|
184 |
}
|
185 |
}
|
186 |
|
|
|
|
|
|
|
187 |
/**
|
188 |
* Replaces a value in cache.
|
189 |
*
|
@@ -279,7 +284,6 @@ function wp_cache_add_non_persistent_groups($groups)
|
|
279 |
|
280 |
class WP_Object_Cache
|
281 |
{
|
282 |
-
|
283 |
/**
|
284 |
* The Redis client.
|
285 |
*
|
@@ -294,6 +298,13 @@ class WP_Object_Cache
|
|
294 |
*/
|
295 |
private $redis_connected = false;
|
296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
/**
|
298 |
* Holds the non-Redis objects.
|
299 |
*
|
@@ -338,7 +349,7 @@ class WP_Object_Cache
|
|
338 |
*
|
339 |
* @var array
|
340 |
*/
|
341 |
-
public $ignored_groups = array(
|
342 |
|
343 |
/**
|
344 |
* Prefix used for global groups.
|
@@ -377,16 +388,19 @@ class WP_Object_Cache
|
|
377 |
{
|
378 |
global $blog_id, $table_prefix;
|
379 |
|
|
|
|
|
380 |
$parameters = array(
|
381 |
'scheme' => 'tcp',
|
382 |
'host' => '127.0.0.1',
|
383 |
'port' => 6379
|
384 |
);
|
385 |
|
386 |
-
foreach (array(
|
387 |
$constant = sprintf('WP_REDIS_%s', strtoupper($setting));
|
|
|
388 |
if (defined($constant)) {
|
389 |
-
$parameters[
|
390 |
}
|
391 |
}
|
392 |
|
@@ -412,12 +426,12 @@ class WP_Object_Cache
|
|
412 |
$this->redis = new Redis();
|
413 |
|
414 |
// Adjust host and port, if the scheme is `unix`
|
415 |
-
if (strcasecmp('unix', $parameters[
|
416 |
-
$parameters[
|
417 |
-
$parameters[
|
418 |
}
|
419 |
|
420 |
-
$this->redis->connect($parameters[
|
421 |
}
|
422 |
|
423 |
if (strcasecmp('pecl', $client) === 0) {
|
@@ -430,21 +444,21 @@ class WP_Object_Cache
|
|
430 |
} else {
|
431 |
$this->redis = new Redis();
|
432 |
|
433 |
-
if (strcasecmp('unix', $parameters[
|
434 |
-
$this->redis->connect($parameters[
|
435 |
} else {
|
436 |
-
$this->redis->connect($parameters[
|
437 |
}
|
438 |
}
|
439 |
}
|
440 |
|
441 |
if (strcasecmp('pecl', $client) === 0 || strcasecmp('hhvm', $client) === 0) {
|
442 |
-
if (isset($parameters[
|
443 |
-
$this->redis->auth($parameters[
|
444 |
}
|
445 |
|
446 |
-
if (isset($parameters[
|
447 |
-
$this->redis->select($parameters[
|
448 |
}
|
449 |
}
|
450 |
|
@@ -453,7 +467,7 @@ class WP_Object_Cache
|
|
453 |
|
454 |
// Require PHP 5.4 or greater
|
455 |
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
456 |
-
throw new Exception;
|
457 |
}
|
458 |
|
459 |
// Load bundled Predis library
|
@@ -468,19 +482,19 @@ class WP_Object_Cache
|
|
468 |
$parameters = WP_REDIS_SHARDS;
|
469 |
} elseif (defined('WP_REDIS_SENTINEL')) {
|
470 |
$parameters = WP_REDIS_SERVERS;
|
471 |
-
$options[
|
472 |
-
$options[
|
473 |
} elseif (defined('WP_REDIS_SERVERS')) {
|
474 |
$parameters = WP_REDIS_SERVERS;
|
475 |
-
$options[
|
476 |
} elseif (defined('WP_REDIS_CLUSTER')) {
|
477 |
$parameters = WP_REDIS_CLUSTER;
|
478 |
-
$options[
|
479 |
}
|
480 |
|
481 |
-
foreach (array(
|
482 |
if (defined('WP_REDIS_PASSWORD') && defined($constant)) {
|
483 |
-
$options[
|
484 |
}
|
485 |
}
|
486 |
|
@@ -490,20 +504,15 @@ class WP_Object_Cache
|
|
490 |
$this->redis_client .= sprintf(' (v%s)', Predis\Client::VERSION);
|
491 |
}
|
492 |
|
493 |
-
|
494 |
-
|
|
|
|
|
|
|
495 |
|
496 |
$this->redis_connected = true;
|
497 |
} catch (Exception $exception) {
|
498 |
-
|
499 |
-
// When Redis is unavailable, fall back to the internal back by forcing all groups to be "no redis" groups
|
500 |
-
$this->ignored_groups = array_unique(array_merge($this->ignored_groups, $this->global_groups));
|
501 |
-
|
502 |
-
$this->redis_connected = false;
|
503 |
-
|
504 |
-
if (! $fail_gracefully) {
|
505 |
-
throw $exception;
|
506 |
-
}
|
507 |
}
|
508 |
|
509 |
// Assign global and blog prefixes for use with keys
|
@@ -585,7 +594,7 @@ class WP_Object_Cache
|
|
585 |
? wp_suspend_cache_addition()
|
586 |
: false;
|
587 |
|
588 |
-
if (
|
589 |
return false;
|
590 |
}
|
591 |
|
@@ -594,22 +603,28 @@ class WP_Object_Cache
|
|
594 |
|
595 |
// save if group not excluded and redis is up
|
596 |
if (! in_array($group, $this->ignored_groups) && $this->redis_status()) {
|
597 |
-
|
|
|
598 |
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
|
603 |
-
|
604 |
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
|
|
|
|
|
|
|
|
|
|
609 |
}
|
610 |
}
|
611 |
|
612 |
-
$exists = isset($this->cache[
|
613 |
|
614 |
if ($add == $exists) {
|
615 |
return false;
|
@@ -634,13 +649,19 @@ class WP_Object_Cache
|
|
634 |
$result = false;
|
635 |
$derived_key = $this->build_key($key, $group);
|
636 |
|
637 |
-
if (isset($this->cache[
|
638 |
-
unset($this->cache[
|
639 |
$result = true;
|
640 |
}
|
641 |
|
642 |
if ($this->redis_status() && ! in_array($group, $this->ignored_groups)) {
|
643 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
644 |
}
|
645 |
|
646 |
if (function_exists('do_action')) {
|
@@ -665,7 +686,7 @@ class WP_Object_Cache
|
|
665 |
sleep($delay);
|
666 |
}
|
667 |
|
668 |
-
$
|
669 |
$this->cache = array();
|
670 |
|
671 |
if ($this->redis_status()) {
|
@@ -682,20 +703,71 @@ class WP_Object_Cache
|
|
682 |
return i
|
683 |
";
|
684 |
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
689 |
} else {
|
690 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
691 |
}
|
692 |
|
693 |
if (function_exists('do_action')) {
|
694 |
-
do_action('redis_object_cache_flush', $
|
695 |
}
|
696 |
}
|
697 |
|
698 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
699 |
}
|
700 |
|
701 |
/**
|
@@ -715,11 +787,11 @@ class WP_Object_Cache
|
|
715 |
{
|
716 |
$derived_key = $this->build_key($key, $group);
|
717 |
|
718 |
-
if (isset($this->cache[
|
719 |
$found = true;
|
720 |
$this->cache_hits++;
|
721 |
|
722 |
-
return is_object($this->cache[
|
723 |
} elseif (in_array($group, $this->ignored_groups) || ! $this->redis_status()) {
|
724 |
$found = false;
|
725 |
$this->cache_misses++;
|
@@ -727,7 +799,13 @@ class WP_Object_Cache
|
|
727 |
return false;
|
728 |
}
|
729 |
|
730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
731 |
|
732 |
if ($result === null || $result === false) {
|
733 |
$found = false;
|
@@ -749,8 +827,8 @@ class WP_Object_Cache
|
|
749 |
}
|
750 |
|
751 |
if (function_exists('apply_filters') && function_exists('has_filter')) {
|
752 |
-
if (has_filter('
|
753 |
-
return apply_filters('
|
754 |
}
|
755 |
}
|
756 |
|
@@ -781,7 +859,7 @@ class WP_Object_Cache
|
|
781 |
foreach ($groups as $group => $keys) {
|
782 |
if (in_array($group, $this->ignored_groups) || ! $this->redis_status()) {
|
783 |
foreach ($keys as $key) {
|
784 |
-
$cache[
|
785 |
}
|
786 |
} else {
|
787 |
// Reformat arguments as expected by Redis
|
@@ -792,16 +870,21 @@ class WP_Object_Cache
|
|
792 |
}
|
793 |
|
794 |
// Retrieve from cache in a single request
|
795 |
-
|
|
|
|
|
|
|
|
|
|
|
796 |
|
797 |
// Build an array of values looked up, keyed by the derived cache key
|
798 |
$group_cache = array_combine($derived_keys, $group_cache);
|
799 |
|
800 |
// Restores cached data to its original data type
|
801 |
-
$group_cache = array_map(array(
|
802 |
|
803 |
// Redis returns null for values not found in cache, but expected return value is false in this instance
|
804 |
-
$group_cache = array_map(array(
|
805 |
|
806 |
$cache = array_merge($cache, $group_cache);
|
807 |
}
|
@@ -838,12 +921,18 @@ class WP_Object_Cache
|
|
838 |
|
839 |
// save if group not excluded from redis and redis is up
|
840 |
if (! in_array($group, $this->ignored_groups) && $this->redis_status()) {
|
841 |
-
$expiration = $this->validate_expiration($expiration);
|
842 |
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
}
|
848 |
}
|
849 |
|
@@ -882,9 +971,15 @@ class WP_Object_Cache
|
|
882 |
}
|
883 |
|
884 |
// Save to Redis
|
885 |
-
|
|
|
|
|
|
|
|
|
|
|
886 |
|
887 |
-
|
|
|
888 |
|
889 |
return $result;
|
890 |
}
|
@@ -924,10 +1019,16 @@ class WP_Object_Cache
|
|
924 |
return $value;
|
925 |
}
|
926 |
|
927 |
-
|
928 |
-
|
|
|
929 |
|
930 |
-
|
|
|
|
|
|
|
|
|
|
|
931 |
|
932 |
return $result;
|
933 |
}
|
@@ -972,7 +1073,7 @@ class WP_Object_Cache
|
|
972 |
$salt = defined('WP_CACHE_KEY_SALT') ? trim(WP_CACHE_KEY_SALT) : '';
|
973 |
$prefix = in_array($group, $this->global_groups) ? $this->global_prefix : $this->blog_prefix;
|
974 |
|
975 |
-
return "{$salt}{$prefix}:{$group}:{$key}";
|
976 |
}
|
977 |
|
978 |
/**
|
@@ -1024,7 +1125,7 @@ class WP_Object_Cache
|
|
1024 |
*/
|
1025 |
public function add_to_internal_cache($derived_key, $value)
|
1026 |
{
|
1027 |
-
$this->cache[
|
1028 |
}
|
1029 |
|
1030 |
/**
|
@@ -1039,8 +1140,8 @@ class WP_Object_Cache
|
|
1039 |
{
|
1040 |
$derived_key = $this->build_key($key, $group);
|
1041 |
|
1042 |
-
if (isset($this->cache[
|
1043 |
-
return $this->cache[
|
1044 |
}
|
1045 |
|
1046 |
return false;
|
@@ -1119,7 +1220,7 @@ class WP_Object_Cache
|
|
1119 |
*/
|
1120 |
protected function maybe_unserialize($original)
|
1121 |
{
|
1122 |
-
if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY) {
|
1123 |
return igbinary_unserialize($original);
|
1124 |
}
|
1125 |
|
@@ -1138,7 +1239,7 @@ class WP_Object_Cache
|
|
1138 |
*/
|
1139 |
protected function maybe_serialize($data)
|
1140 |
{
|
1141 |
-
if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY) {
|
1142 |
return igbinary_serialize($data);
|
1143 |
}
|
1144 |
|
@@ -1234,6 +1335,24 @@ class WP_Object_Cache
|
|
1234 |
|
1235 |
return false;
|
1236 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1237 |
}
|
1238 |
|
1239 |
endif;
|
3 |
Plugin Name: Redis Object Cache Drop-In
|
4 |
Plugin URI: http://wordpress.org/plugins/redis-cache/
|
5 |
Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, HHVM, replication, clustering and WP-CLI.
|
6 |
+
Version: 1.4.2
|
7 |
Author: Till Krüss
|
8 |
Author URI: https://till.im/
|
9 |
License: GPLv3
|
180 |
global $wp_object_cache;
|
181 |
|
182 |
if (! ($wp_object_cache instanceof WP_Object_Cache)) {
|
183 |
+
$fail_gracefully = ! defined('WP_REDIS_GRACEFUL') || WP_REDIS_GRACEFUL;
|
184 |
+
|
185 |
+
$wp_object_cache = new WP_Object_Cache($fail_gracefully);
|
186 |
}
|
187 |
}
|
188 |
|
189 |
+
// wp_cache_switch_to_blog
|
190 |
+
// wp_cache_switch_to_blog( get_current_blog_id() );
|
191 |
+
|
192 |
/**
|
193 |
* Replaces a value in cache.
|
194 |
*
|
284 |
|
285 |
class WP_Object_Cache
|
286 |
{
|
|
|
287 |
/**
|
288 |
* The Redis client.
|
289 |
*
|
298 |
*/
|
299 |
private $redis_connected = false;
|
300 |
|
301 |
+
/**
|
302 |
+
* Check to fail gracefully or throw an exception.
|
303 |
+
*
|
304 |
+
* @var bool
|
305 |
+
*/
|
306 |
+
private $fail_gracefully = true;
|
307 |
+
|
308 |
/**
|
309 |
* Holds the non-Redis objects.
|
310 |
*
|
349 |
*
|
350 |
* @var array
|
351 |
*/
|
352 |
+
public $ignored_groups = array('counts', 'plugins');
|
353 |
|
354 |
/**
|
355 |
* Prefix used for global groups.
|
388 |
{
|
389 |
global $blog_id, $table_prefix;
|
390 |
|
391 |
+
$this->fail_gracefully = $fail_gracefully;
|
392 |
+
|
393 |
$parameters = array(
|
394 |
'scheme' => 'tcp',
|
395 |
'host' => '127.0.0.1',
|
396 |
'port' => 6379
|
397 |
);
|
398 |
|
399 |
+
foreach (array('scheme', 'host', 'port', 'path', 'password', 'database') as $setting) {
|
400 |
$constant = sprintf('WP_REDIS_%s', strtoupper($setting));
|
401 |
+
|
402 |
if (defined($constant)) {
|
403 |
+
$parameters[$setting] = constant($constant);
|
404 |
}
|
405 |
}
|
406 |
|
426 |
$this->redis = new Redis();
|
427 |
|
428 |
// Adjust host and port, if the scheme is `unix`
|
429 |
+
if (strcasecmp('unix', $parameters['scheme']) === 0) {
|
430 |
+
$parameters['host'] = 'unix://' . $parameters['path'];
|
431 |
+
$parameters['port'] = 0;
|
432 |
}
|
433 |
|
434 |
+
$this->redis->connect($parameters['host'], $parameters['port']);
|
435 |
}
|
436 |
|
437 |
if (strcasecmp('pecl', $client) === 0) {
|
444 |
} else {
|
445 |
$this->redis = new Redis();
|
446 |
|
447 |
+
if (strcasecmp('unix', $parameters['scheme']) === 0) {
|
448 |
+
$this->redis->connect($parameters['path']);
|
449 |
} else {
|
450 |
+
$this->redis->connect($parameters['host'], $parameters['port']);
|
451 |
}
|
452 |
}
|
453 |
}
|
454 |
|
455 |
if (strcasecmp('pecl', $client) === 0 || strcasecmp('hhvm', $client) === 0) {
|
456 |
+
if (isset($parameters['password'])) {
|
457 |
+
$this->redis->auth($parameters['password']);
|
458 |
}
|
459 |
|
460 |
+
if (isset($parameters['database'])) {
|
461 |
+
$this->redis->select($parameters['database']);
|
462 |
}
|
463 |
}
|
464 |
|
467 |
|
468 |
// Require PHP 5.4 or greater
|
469 |
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
470 |
+
throw new Exception('Predis required PHP 5.4 or newer.');
|
471 |
}
|
472 |
|
473 |
// Load bundled Predis library
|
482 |
$parameters = WP_REDIS_SHARDS;
|
483 |
} elseif (defined('WP_REDIS_SENTINEL')) {
|
484 |
$parameters = WP_REDIS_SERVERS;
|
485 |
+
$options['replication'] = 'sentinel';
|
486 |
+
$options['service'] = WP_REDIS_SENTINEL;
|
487 |
} elseif (defined('WP_REDIS_SERVERS')) {
|
488 |
$parameters = WP_REDIS_SERVERS;
|
489 |
+
$options['replication'] = true;
|
490 |
} elseif (defined('WP_REDIS_CLUSTER')) {
|
491 |
$parameters = WP_REDIS_CLUSTER;
|
492 |
+
$options['cluster'] = 'redis';
|
493 |
}
|
494 |
|
495 |
+
foreach (array('WP_REDIS_SERVERS', 'WP_REDIS_SHARDS', 'WP_REDIS_CLUSTER') as $constant) {
|
496 |
if (defined('WP_REDIS_PASSWORD') && defined($constant)) {
|
497 |
+
$options['parameters']['password'] = WP_REDIS_PASSWORD;
|
498 |
}
|
499 |
}
|
500 |
|
504 |
$this->redis_client .= sprintf(' (v%s)', Predis\Client::VERSION);
|
505 |
}
|
506 |
|
507 |
+
if (defined('WP_REDIS_CLUSTER')) {
|
508 |
+
$this->redis->ping(current(array_values(WP_REDIS_CLUSTER)));
|
509 |
+
} else {
|
510 |
+
$this->redis->ping();
|
511 |
+
}
|
512 |
|
513 |
$this->redis_connected = true;
|
514 |
} catch (Exception $exception) {
|
515 |
+
$this->handle_exception($exception);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
516 |
}
|
517 |
|
518 |
// Assign global and blog prefixes for use with keys
|
594 |
? wp_suspend_cache_addition()
|
595 |
: false;
|
596 |
|
597 |
+
if ($add && $cache_addition_suspended) {
|
598 |
return false;
|
599 |
}
|
600 |
|
603 |
|
604 |
// save if group not excluded and redis is up
|
605 |
if (! in_array($group, $this->ignored_groups) && $this->redis_status()) {
|
606 |
+
try {
|
607 |
+
$exists = $this->redis->exists($derived_key);
|
608 |
|
609 |
+
if ($add == $exists) {
|
610 |
+
return false;
|
611 |
+
}
|
612 |
|
613 |
+
$expiration = apply_filters('redis_cache_expiration', $this->validate_expiration($expiration), $key, $group);
|
614 |
|
615 |
+
if ($expiration) {
|
616 |
+
$result = $this->parse_redis_response($this->redis->setex($derived_key, $expiration, $this->maybe_serialize($value)));
|
617 |
+
} else {
|
618 |
+
$result = $this->parse_redis_response($this->redis->set($derived_key, $this->maybe_serialize($value)));
|
619 |
+
}
|
620 |
+
} catch (Exception $exception) {
|
621 |
+
$this->handle_exception($exception);
|
622 |
+
|
623 |
+
return false;
|
624 |
}
|
625 |
}
|
626 |
|
627 |
+
$exists = isset($this->cache[$derived_key]);
|
628 |
|
629 |
if ($add == $exists) {
|
630 |
return false;
|
649 |
$result = false;
|
650 |
$derived_key = $this->build_key($key, $group);
|
651 |
|
652 |
+
if (isset($this->cache[$derived_key])) {
|
653 |
+
unset($this->cache[$derived_key]);
|
654 |
$result = true;
|
655 |
}
|
656 |
|
657 |
if ($this->redis_status() && ! in_array($group, $this->ignored_groups)) {
|
658 |
+
try {
|
659 |
+
$result = $this->parse_redis_response($this->redis->del($derived_key));
|
660 |
+
} catch (Exception $exception) {
|
661 |
+
$this->handle_exception($exception);
|
662 |
+
|
663 |
+
return false;
|
664 |
+
}
|
665 |
}
|
666 |
|
667 |
if (function_exists('do_action')) {
|
686 |
sleep($delay);
|
687 |
}
|
688 |
|
689 |
+
$results = [];
|
690 |
$this->cache = array();
|
691 |
|
692 |
if ($this->redis_status()) {
|
703 |
return i
|
704 |
";
|
705 |
|
706 |
+
if (defined('WP_REDIS_CLUSTER')) {
|
707 |
+
try {
|
708 |
+
foreach ($this->redis->_masters() as $master) {
|
709 |
+
$redis = new Redis;
|
710 |
+
$redis->connect($master[0], $master[1]);
|
711 |
+
$results[] = $this->parse_redis_response($this->redis->eval($script));
|
712 |
+
unset($redis);
|
713 |
+
}
|
714 |
+
} catch (Exception $exception) {
|
715 |
+
$this->handle_exception($exception);
|
716 |
+
|
717 |
+
return false;
|
718 |
+
}
|
719 |
+
} else {
|
720 |
+
try {
|
721 |
+
$results[] = $this->parse_redis_response(
|
722 |
+
$this->redis->eval(
|
723 |
+
$script,
|
724 |
+
$this->redis instanceof Predis\Client ? 0 : []
|
725 |
+
)
|
726 |
+
);
|
727 |
+
} catch (Exception $exception) {
|
728 |
+
$this->handle_exception($exception);
|
729 |
+
|
730 |
+
return false;
|
731 |
+
}
|
732 |
+
}
|
733 |
} else {
|
734 |
+
if (defined('WP_REDIS_CLUSTER')) {
|
735 |
+
try {
|
736 |
+
foreach ($this->redis->_masters() as $master) {
|
737 |
+
$results[] = $this->parse_redis_response($this->redis->flushdb($master));
|
738 |
+
}
|
739 |
+
} catch (Exception $exception) {
|
740 |
+
$this->handle_exception($exception);
|
741 |
+
|
742 |
+
return false;
|
743 |
+
}
|
744 |
+
} else {
|
745 |
+
try {
|
746 |
+
$results[] = $this->parse_redis_response($this->redis->flushdb());
|
747 |
+
} catch (Exception $exception) {
|
748 |
+
$this->handle_exception($exception);
|
749 |
+
|
750 |
+
return false;
|
751 |
+
}
|
752 |
+
}
|
753 |
}
|
754 |
|
755 |
if (function_exists('do_action')) {
|
756 |
+
do_action('redis_object_cache_flush', $results, $delay, $selective, $salt);
|
757 |
}
|
758 |
}
|
759 |
|
760 |
+
if (empty($results)) {
|
761 |
+
return false;
|
762 |
+
}
|
763 |
+
|
764 |
+
foreach ($results as $result) {
|
765 |
+
if (! $result) {
|
766 |
+
return false;
|
767 |
+
}
|
768 |
+
}
|
769 |
+
|
770 |
+
return true;
|
771 |
}
|
772 |
|
773 |
/**
|
787 |
{
|
788 |
$derived_key = $this->build_key($key, $group);
|
789 |
|
790 |
+
if (isset($this->cache[$derived_key]) && ! $force) {
|
791 |
$found = true;
|
792 |
$this->cache_hits++;
|
793 |
|
794 |
+
return is_object($this->cache[$derived_key]) ? clone $this->cache[$derived_key] : $this->cache[$derived_key];
|
795 |
} elseif (in_array($group, $this->ignored_groups) || ! $this->redis_status()) {
|
796 |
$found = false;
|
797 |
$this->cache_misses++;
|
799 |
return false;
|
800 |
}
|
801 |
|
802 |
+
try {
|
803 |
+
$result = $this->redis->get($derived_key);
|
804 |
+
} catch (Exception $exception) {
|
805 |
+
$this->handle_exception($exception);
|
806 |
+
|
807 |
+
return false;
|
808 |
+
}
|
809 |
|
810 |
if ($result === null || $result === false) {
|
811 |
$found = false;
|
827 |
}
|
828 |
|
829 |
if (function_exists('apply_filters') && function_exists('has_filter')) {
|
830 |
+
if (has_filter('redis_object_cache_get_value')) {
|
831 |
+
return apply_filters('redis_object_cache_get_value', $value, $key, $group, $force, $found);
|
832 |
}
|
833 |
}
|
834 |
|
859 |
foreach ($groups as $group => $keys) {
|
860 |
if (in_array($group, $this->ignored_groups) || ! $this->redis_status()) {
|
861 |
foreach ($keys as $key) {
|
862 |
+
$cache[$this->build_key($key, $group)] = $this->get($key, $group);
|
863 |
}
|
864 |
} else {
|
865 |
// Reformat arguments as expected by Redis
|
870 |
}
|
871 |
|
872 |
// Retrieve from cache in a single request
|
873 |
+
try {
|
874 |
+
$group_cache = $this->redis->mget($derived_keys);
|
875 |
+
} catch (Exception $exception) {
|
876 |
+
$this->handle_exception($exception);
|
877 |
+
$group_cache = array_fill(0, count($derived_keys) - 1, false);
|
878 |
+
}
|
879 |
|
880 |
// Build an array of values looked up, keyed by the derived cache key
|
881 |
$group_cache = array_combine($derived_keys, $group_cache);
|
882 |
|
883 |
// Restores cached data to its original data type
|
884 |
+
$group_cache = array_map(array($this, 'maybe_unserialize'), $group_cache);
|
885 |
|
886 |
// Redis returns null for values not found in cache, but expected return value is false in this instance
|
887 |
+
$group_cache = array_map(array($this, 'filter_redis_get_multi'), $group_cache);
|
888 |
|
889 |
$cache = array_merge($cache, $group_cache);
|
890 |
}
|
921 |
|
922 |
// save if group not excluded from redis and redis is up
|
923 |
if (! in_array($group, $this->ignored_groups) && $this->redis_status()) {
|
924 |
+
$expiration = apply_filters('redis_cache_expiration', $this->validate_expiration($expiration), $key, $group);
|
925 |
|
926 |
+
try {
|
927 |
+
if ($expiration) {
|
928 |
+
$result = $this->parse_redis_response($this->redis->setex($derived_key, $expiration, $this->maybe_serialize($value)));
|
929 |
+
} else {
|
930 |
+
$result = $this->parse_redis_response($this->redis->set($derived_key, $this->maybe_serialize($value)));
|
931 |
+
}
|
932 |
+
} catch (Exception $exception) {
|
933 |
+
$this->handle_exception($exception);
|
934 |
+
|
935 |
+
return false;
|
936 |
}
|
937 |
}
|
938 |
|
971 |
}
|
972 |
|
973 |
// Save to Redis
|
974 |
+
try {
|
975 |
+
$result = $this->parse_redis_response($this->redis->incrBy($derived_key, $offset));
|
976 |
+
|
977 |
+
$this->add_to_internal_cache($derived_key, (int) $this->redis->get($derived_key));
|
978 |
+
} catch (Exception $exception) {
|
979 |
+
$this->handle_exception($exception);
|
980 |
|
981 |
+
return false;
|
982 |
+
}
|
983 |
|
984 |
return $result;
|
985 |
}
|
1019 |
return $value;
|
1020 |
}
|
1021 |
|
1022 |
+
try {
|
1023 |
+
// Save to Redis
|
1024 |
+
$result = $this->parse_redis_response($this->redis->decrBy($derived_key, $offset));
|
1025 |
|
1026 |
+
$this->add_to_internal_cache($derived_key, (int) $this->redis->get($derived_key));
|
1027 |
+
} catch (Exception $exception) {
|
1028 |
+
$this->handle_exception($exception);
|
1029 |
+
|
1030 |
+
return false;
|
1031 |
+
}
|
1032 |
|
1033 |
return $result;
|
1034 |
}
|
1073 |
$salt = defined('WP_CACHE_KEY_SALT') ? trim(WP_CACHE_KEY_SALT) : '';
|
1074 |
$prefix = in_array($group, $this->global_groups) ? $this->global_prefix : $this->blog_prefix;
|
1075 |
|
1076 |
+
return "{{$salt}{$prefix}}:{$group}:{$key}";
|
1077 |
}
|
1078 |
|
1079 |
/**
|
1125 |
*/
|
1126 |
public function add_to_internal_cache($derived_key, $value)
|
1127 |
{
|
1128 |
+
$this->cache[$derived_key] = $value;
|
1129 |
}
|
1130 |
|
1131 |
/**
|
1140 |
{
|
1141 |
$derived_key = $this->build_key($key, $group);
|
1142 |
|
1143 |
+
if (isset($this->cache[$derived_key])) {
|
1144 |
+
return $this->cache[$derived_key];
|
1145 |
}
|
1146 |
|
1147 |
return false;
|
1220 |
*/
|
1221 |
protected function maybe_unserialize($original)
|
1222 |
{
|
1223 |
+
if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_unserialize')) {
|
1224 |
return igbinary_unserialize($original);
|
1225 |
}
|
1226 |
|
1239 |
*/
|
1240 |
protected function maybe_serialize($data)
|
1241 |
{
|
1242 |
+
if (defined('WP_REDIS_IGBINARY') && WP_REDIS_IGBINARY && function_exists('igbinary_serialize')) {
|
1243 |
return igbinary_serialize($data);
|
1244 |
}
|
1245 |
|
1335 |
|
1336 |
return false;
|
1337 |
}
|
1338 |
+
|
1339 |
+
/**
|
1340 |
+
* Handle the redis failure gracefully or throw an exception.
|
1341 |
+
*
|
1342 |
+
* @param \Exception $exception Exception thrown.
|
1343 |
+
*/
|
1344 |
+
protected function handle_exception($exception) {
|
1345 |
+
$this->redis_connected = false;
|
1346 |
+
|
1347 |
+
// When Redis is unavailable, fall back to the internal cache by forcing all groups to be "no redis" groups
|
1348 |
+
$this->ignored_groups = array_unique(array_merge($this->ignored_groups, $this->global_groups));
|
1349 |
+
|
1350 |
+
if (! $this->fail_gracefully) {
|
1351 |
+
throw $exception;
|
1352 |
+
}
|
1353 |
+
|
1354 |
+
error_log($exception);
|
1355 |
+
}
|
1356 |
}
|
1357 |
|
1358 |
endif;
|
includes/servers-list.php
CHANGED
@@ -52,7 +52,11 @@ class Servers_List extends WP_List_Table {
|
|
52 |
|
53 |
$this->items = $this->get_servers();
|
54 |
|
55 |
-
$this->_column_headers = array(
|
|
|
|
|
|
|
|
|
56 |
|
57 |
}
|
58 |
|
@@ -93,7 +97,7 @@ class Servers_List extends WP_List_Table {
|
|
93 |
'scheme' => 'tcp',
|
94 |
);
|
95 |
|
96 |
-
foreach (
|
97 |
$constant = sprintf( 'WP_REDIS_%s', strtoupper( $setting ) );
|
98 |
|
99 |
if ( defined( $constant ) ) {
|
@@ -117,9 +121,9 @@ class Servers_List extends WP_List_Table {
|
|
117 |
$servers = array( $server );
|
118 |
}
|
119 |
|
120 |
-
return array_map(function($parameters) {
|
121 |
-
return is_string($parameters) ? Predis\Connection\Parameters::parse($parameters) : $parameters;
|
122 |
-
}, $servers);
|
123 |
|
124 |
}
|
125 |
|
52 |
|
53 |
$this->items = $this->get_servers();
|
54 |
|
55 |
+
$this->_column_headers = array(
|
56 |
+
$this->get_columns(),
|
57 |
+
$this->get_hidden_columns(),
|
58 |
+
array()
|
59 |
+
);
|
60 |
|
61 |
}
|
62 |
|
97 |
'scheme' => 'tcp',
|
98 |
);
|
99 |
|
100 |
+
foreach ( array( 'scheme', 'host', 'port', 'path', 'password', 'database' ) as $setting ) {
|
101 |
$constant = sprintf( 'WP_REDIS_%s', strtoupper( $setting ) );
|
102 |
|
103 |
if ( defined( $constant ) ) {
|
121 |
$servers = array( $server );
|
122 |
}
|
123 |
|
124 |
+
return array_map( function ( $parameters ) {
|
125 |
+
return is_string( $parameters ) ? Predis\Connection\Parameters::parse( $parameters ) : $parameters;
|
126 |
+
}, $servers );
|
127 |
|
128 |
}
|
129 |
|
includes/wp-cli-commands.php
CHANGED
@@ -19,7 +19,7 @@ class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
|
|
19 |
$client = $plugin->get_redis_client_name();
|
20 |
|
21 |
|
22 |
-
switch ($status) {
|
23 |
case __( 'Disabled', 'redis-cache' ):
|
24 |
$status = WP_CLI::colorize( "%y{$status}%n" );
|
25 |
break;
|
@@ -58,7 +58,7 @@ class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
|
|
58 |
|
59 |
if ( $plugin->object_cache_dropin_exists() ) {
|
60 |
|
61 |
-
if ($plugin->validate_object_cache_dropin()) {
|
62 |
WP_CLI::line( __( 'Redis object cache already enabled.', 'redis-cache' ) );
|
63 |
} else {
|
64 |
WP_CLI::error( __('An unknown object cache drop-in was found. To use Redis run: wp redis update-dropin.', 'redis-cache') );
|
@@ -68,7 +68,7 @@ class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
|
|
68 |
|
69 |
WP_Filesystem();
|
70 |
|
71 |
-
if ($wp_filesystem->copy( WP_PLUGIN_DIR . '/redis-cache/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', true )) {
|
72 |
WP_CLI::success( __( 'Object cache enabled.', 'redis-cache' ) );
|
73 |
} else {
|
74 |
WP_CLI::error( __( 'Object cache could not be enabled.', 'redis-cache' ) );
|
@@ -103,13 +103,13 @@ class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
|
|
103 |
|
104 |
if ( ! $plugin->validate_object_cache_dropin() ) {
|
105 |
|
106 |
-
WP_CLI::error( __('An unknown object cache drop-in was found. To use Redis run: wp redis update-dropin.', 'redis-cache') );
|
107 |
|
108 |
} else {
|
109 |
|
110 |
WP_Filesystem();
|
111 |
|
112 |
-
if ($wp_filesystem->delete( WP_CONTENT_DIR . '/object-cache.php' )) {
|
113 |
WP_CLI::success( __( 'Object cache disabled.', 'redis-cache' ) );
|
114 |
} else {
|
115 |
WP_CLI::error( __( 'Object cache could not be disabled.', 'redis-cache' ) );
|
@@ -138,7 +138,7 @@ class RedisObjectCache_CLI_Commands extends WP_CLI_Command {
|
|
138 |
|
139 |
WP_Filesystem();
|
140 |
|
141 |
-
if ($wp_filesystem->copy( WP_PLUGIN_DIR . '/redis-cache/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', true
|
142 |
WP_CLI::success( __( 'Updated object cache drop-in and enabled Redis object cache.', 'redis-cache' ) );
|
143 |
} else {
|
144 |
WP_CLI::error( __( 'Object cache drop-in could not be updated.', 'redis-cache' ) );
|
19 |
$client = $plugin->get_redis_client_name();
|
20 |
|
21 |
|
22 |
+
switch ( $status ) {
|
23 |
case __( 'Disabled', 'redis-cache' ):
|
24 |
$status = WP_CLI::colorize( "%y{$status}%n" );
|
25 |
break;
|
58 |
|
59 |
if ( $plugin->object_cache_dropin_exists() ) {
|
60 |
|
61 |
+
if ( $plugin->validate_object_cache_dropin() ) {
|
62 |
WP_CLI::line( __( 'Redis object cache already enabled.', 'redis-cache' ) );
|
63 |
} else {
|
64 |
WP_CLI::error( __('An unknown object cache drop-in was found. To use Redis run: wp redis update-dropin.', 'redis-cache') );
|
68 |
|
69 |
WP_Filesystem();
|
70 |
|
71 |
+
if ( $wp_filesystem->copy( WP_PLUGIN_DIR . '/redis-cache/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', true ) ) {
|
72 |
WP_CLI::success( __( 'Object cache enabled.', 'redis-cache' ) );
|
73 |
} else {
|
74 |
WP_CLI::error( __( 'Object cache could not be enabled.', 'redis-cache' ) );
|
103 |
|
104 |
if ( ! $plugin->validate_object_cache_dropin() ) {
|
105 |
|
106 |
+
WP_CLI::error( __( 'An unknown object cache drop-in was found. To use Redis run: wp redis update-dropin.', 'redis-cache' ) );
|
107 |
|
108 |
} else {
|
109 |
|
110 |
WP_Filesystem();
|
111 |
|
112 |
+
if ( $wp_filesystem->delete( WP_CONTENT_DIR . '/object-cache.php' ) ) {
|
113 |
WP_CLI::success( __( 'Object cache disabled.', 'redis-cache' ) );
|
114 |
} else {
|
115 |
WP_CLI::error( __( 'Object cache could not be disabled.', 'redis-cache' ) );
|
138 |
|
139 |
WP_Filesystem();
|
140 |
|
141 |
+
if ( $wp_filesystem->copy( WP_PLUGIN_DIR . '/redis-cache/includes/object-cache.php', WP_CONTENT_DIR . '/object-cache.php', true )) {
|
142 |
WP_CLI::success( __( 'Updated object cache drop-in and enabled Redis object cache.', 'redis-cache' ) );
|
143 |
} else {
|
144 |
WP_CLI::error( __( 'Object cache drop-in could not be updated.', 'redis-cache' ) );
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: tillkruess
|
|
3 |
Donate link: https://www.paypal.me/tillkruss
|
4 |
Tags: redis, predis, phpredis, hhvm, pecl, caching, cache, object cache, performance, replication, clustering
|
5 |
Requires at least: 3.3
|
6 |
-
Tested up to: 5.
|
7 |
-
Stable tag: 1.4.
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -95,6 +95,10 @@ To adjust the configuration, define any of the following constants in your `wp-c
|
|
95 |
|
96 |
Set to `true` to disable the object cache at runtime.
|
97 |
|
|
|
|
|
|
|
|
|
98 |
* `WP_REDIS_IGBINARY` (default: _not set_)
|
99 |
|
100 |
Set to `true` to enable the [igbinary](https://github.com/igbinary/igbinary) serializer.
|
@@ -175,6 +179,13 @@ The following commands are supported:
|
|
175 |
|
176 |
== Changelog ==
|
177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
= 1.4.1 =
|
179 |
|
180 |
* Fixed potential fatal error related to `wp_suspend_cache_addition()`
|
@@ -323,6 +334,10 @@ The following commands are supported:
|
|
323 |
|
324 |
== Upgrade Notice ==
|
325 |
|
|
|
|
|
|
|
|
|
326 |
= 1.4.0 =
|
327 |
|
328 |
This update adds support for igbinary and `wp_suspend_cache_addition()`.
|
3 |
Donate link: https://www.paypal.me/tillkruss
|
4 |
Tags: redis, predis, phpredis, hhvm, pecl, caching, cache, object cache, performance, replication, clustering
|
5 |
Requires at least: 3.3
|
6 |
+
Tested up to: 5.2
|
7 |
+
Stable tag: 1.4.2
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
95 |
|
96 |
Set to `true` to disable the object cache at runtime.
|
97 |
|
98 |
+
* `WP_REDIS_GRACEFUL` (default: _not set_)
|
99 |
+
|
100 |
+
Set to `false` to disable graceful failures and throw exceptions.
|
101 |
+
|
102 |
* `WP_REDIS_IGBINARY` (default: _not set_)
|
103 |
|
104 |
Set to `true` to enable the [igbinary](https://github.com/igbinary/igbinary) serializer.
|
179 |
|
180 |
== Changelog ==
|
181 |
|
182 |
+
= 1.4.2 =
|
183 |
+
|
184 |
+
* Added graceful Redis failures and `WP_REDIS_GRACEFUL` constant
|
185 |
+
* Improved cluster support
|
186 |
+
* Added `redis_cache_expiration` filter
|
187 |
+
* Renamed `redis_object_cache_get` filter to `redis_object_cache_get_value`
|
188 |
+
|
189 |
= 1.4.1 =
|
190 |
|
191 |
* Fixed potential fatal error related to `wp_suspend_cache_addition()`
|
334 |
|
335 |
== Upgrade Notice ==
|
336 |
|
337 |
+
= 1.4.2 =
|
338 |
+
|
339 |
+
This update renames the `redis_object_cache_get` filter to avoid conflicts. Update your code if necessary.
|
340 |
+
|
341 |
= 1.4.0 =
|
342 |
|
343 |
This update adds support for igbinary and `wp_suspend_cache_addition()`.
|
redis-cache.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Redis Object Cache
|
4 |
Plugin URI: https://wordpress.org/plugins/redis-cache/
|
5 |
Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, HHVM, replication, clustering and WP-CLI.
|
6 |
-
Version: 1.4.
|
7 |
Text Domain: redis-cache
|
8 |
Domain Path: /languages
|
9 |
Author: Till Krüss
|
3 |
Plugin Name: Redis Object Cache
|
4 |
Plugin URI: https://wordpress.org/plugins/redis-cache/
|
5 |
Description: A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, HHVM, replication, clustering and WP-CLI.
|
6 |
+
Version: 1.4.2
|
7 |
Text Domain: redis-cache
|
8 |
Domain Path: /languages
|
9 |
Author: Till Krüss
|