Transient deletion failing
-
Hi, I’ve run into two issues with
delete_transient()
when redis-cache is active:delete_transient
never returnstrue
anymore even if a transient is/was present (not sure if deletion from the object cache is taking place at all, see #2).- On
set_transient
the transient is stored in the database (why? is redis-cache doing that?) but ondelete_transient
the transient is not deleted from the database.
I should note: This issue occurs on a subsite on a multisite installation. Is this a known issue or is this happening only on this installation?
-
You can read the source code of the
*_transient()
methods, it’s got little to do with this plugin.https://developer.wordpress.org/reference/functions/set_transient/#source
That’s exactly what I was looking at. I assume that when redis-cache is active and wp_using_ext_object_cache() is true, this applies:
if ( wp_using_ext_object_cache() || wp_installing() ) {
$result = wp_cache_set( $transient, $value, 'transient', $expiration );
}calling wp_cache_set() which uses the redis-cache method, not the else part of set_transient() which uses add_option() to store transient and timeout to the database…
But… to my surprise I find that transients still appear in the database, right after set_transient is run. Where / when is this happening? Is redis-cache not doing that? If not, is it WordPress itself or something else on my installation?
I should maybe explain more about the issue I’m facing with this:
I’ve got a small implementation that stores external API queries with set_transient() for an hour to prevent the API being consulted too often and to improve load times. The implementation also has an admin method that will call delete_transient() to allow “flushing” the cached data before expiry, with an admin notice if any stored transient data was successfully deleted.
function delete_my_plugin_data( $transient ) {
$result = delete_transient( $transient );
if ( $result ) {
wp_admin_notice( 'Success!', [ 'type' => 'success' ] );
} else {
wp_admin_notice( 'Not found!', [ 'type' => 'error' ] );
}
}This works perfectly without Redis Object Cache activated. But with Redis Object Cache is active, delete_transient() does not delete the transient data anymore. At least not from the database. And
$result
is always false.To fix this, I had to add an extra routine to delete the transient from the database:
function delete_my_plugin_data( $transient ) {
$result = delete_transient( $transient );
// When an object cache is active, make sure the DB entry is deleted as well.
if ( wp_using_ext_object_cache() ) {
$result = delete_option( '_transient_' . $transient );
if ( $result ) {
delete_option( '_transient_timeout_' . $transient );
}
}
if ( $result ) {
wp_admin_notice( 'Success!', [ 'type' => 'success' ] );
} else {
wp_admin_notice( 'Not found!', [ 'type' => 'error' ] );
}
}Is it normal that I should do this “double” routine to delete a transient when redis-cache is used?
Thank you for your insights 🙂
After running
wp transient delete --all
, and navigating around the site a little bit, do Transients still show up in the database?You shouldn’t need alter your code, I’ll take a look at this.
I just tested
delete_transient()
against Redis Object Cache as well as Object Cache Pro (both using PhpRedis) and both returntrue
once and thenfalse
as expected. Must be something with your particular WordPress setup.I’d check what
wp_cache_delete()
returns insidedelete_transient()
.Initially, after my
wp transient delete --all
transients did not show up anymore but then I did a Purge cache from the Object cache admin bar menu and right after that, the transients start appearing in the database again.$ wp --path=/xxx/xxx/htdocs --url=ecranvillage.net transient delete --all
Success: 153 transients deleted from the database.
Warning: Transients are stored in an external object cache, and this command only deletes those stored in the database. You must flush the cache to delete all transients.Please note: this is a multisite. It is in fact a multi-network with https://fr.wordpress.org/plugins/wp-multi-network/ … Could this be causing a conflict?
You probably have to call
wp transient delete --all --network
instead.Make sure you’re not using
WP_REDIS_GRACEFUL
.Wanted to limit the test to one network subsite, but I’ll try with –network and let you know 🙂
(WP_REDIS_GRACEFUL is not set in wp-config.php, could it be anywhere else?)
Somehow, with the –network flag it does not look like sub-site transients are deleted from the DB, not even the main site ones. Maybe only network transients (wherever they are stored) ?
$ wp transient delete --all --network
PHP Warning: Undefined array key "HTTP_HOST" in phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1335) : eval()'d code on line 64
PHP Warning: Undefined array key "HTTP_HOST" in /var/www/xxx/htdocs/wp-includes/ms-settings.php on line 57
Warning: Undefined array key "HTTP_HOST" in /var/www/xxx/htdocs/wp-includes/ms-settings.php on line 57
Success: 101 transients deleted from the database.
Warning: Transients are stored in an external object cache, and this command only deletes those stored in the database. You must flush the cache to delete all transients.So to confirm:
- with
wp --url=ecranvillage.net transient delete --all
the transients get deleted from the database but remain in the redis object cache as expected; - running
delete_transient
from admin will not delete a transient from the redis object cache (and returns false); - only clearing the full object cache from admin will get rid of all the transients;
- after clearing the redis object cache, transients will start appearing in the database again;
- points 2 and 4 are not supposed to happen, meaning there is some conflict on my network installation.
Could there be any reason outside of the WP install (like missing PHP modules or server settings) that could explain this? If not, I’ll have to do some thorough debugging :/
My diagnostics:
Status: Connecté
Client: PhpRedis (v5.3.7)
Drop-in: Valid
Disabled: No
Ping: 1
Errors: []
PhpRedis: 5.3.7
Relay: Not loaded
Predis: 2.1.2
Credis: Not loaded
PHP Version: 8.3.6
Plugin Version: 2.5.4
Redis Version: 7.0.15
Multisite: Yes
Metrics: Enabled
Metrics recorded: 5055
Filesystem: Writable
Global Prefix: ""
Blog Prefix: 1
Timeout: 1
Read Timeout: 1
Retry Interval:
WP_REDIS_SCHEME: "unix"
WP_REDIS_PATH: "/var/run/redis/redis.sock"
WP_REDIS_DATABASE: 0
WP_REDIS_PREFIX: "xx.x:"
WP_CACHE_KEY_SALT: "xx.x:"
WP_REDIS_PLUGIN_PATH: "/var/www/xxx/htdocs/wp-content/plugins/redis-cache"
Global Groups: [
"blog-details",
"blog-id-cache",
"blog-lookup",
"global-posts",
"networks",
"rss",
"sites",
"site-details",
"site-lookup",
"site-options",
"site-transient",
"users",
"useremail",
"userlogins",
"usermeta",
"user_meta",
"userslugs",
"redis-cache",
"blog_meta",
"image_editor",
"network-queries",
"site-queries",
"theme_files",
"translation_files",
"user-queries"
]
Ignored Groups: [
"counts",
"plugins",
"theme_json",
"themes"
]
Unflushable Groups: []
Groups Types: {
"blog-details": "global",
"blog-id-cache": "global",
"blog-lookup": "global",
"global-posts": "global",
"networks": "global",
"rss": "global",
"sites": "global",
"site-details": "global",
"site-lookup": "global",
"site-options": "global",
"site-transient": "global",
"users": "global",
"useremail": "global",
"userlogins": "global",
"usermeta": "global",
"user_meta": "global",
"userslugs": "global",
"redis-cache": "global",
"blog_meta": "global",
"image_editor": "global",
"network-queries": "global",
"site-queries": "global",
"theme_files": "global",
"translation_files": "global",
"user-queries": "global",
"counts": "ignored",
"plugins": "ignored",
"theme_json": "ignored",
"themes": "ignored"
}
Drop-ins: [
"Anti-Splog (Spammed Notice and Splog Review Form) v by WPMU DEV",
"Redis Object Cache Drop-In v2.5.4 by Till Krüss"
]Just wondering… for a multisite, should I make WP_REDIS_PREFIX dynamic? Something like:
define( 'WP_REDIS_PREFIX', $_SERVER['HTTP_HOST'] );
You’ll have to debug this why 2 and 4 are happening, since I can’t replicate it.
I found the conflict. It was legacy code from a few years back put in place to work around an issue with transients in the W3 Total Cache Object Cache module at the time. Long since moved away from W3TC, the old work-around remained in place, causing this conflict with Redis Object Cache.
Removing the old work-around, fixed everything.
My sincerest apologies for having bothered you with this. And many many thanks for your time and thoughts, and for the excellent plugin 🙂
- with
- You must be logged in to reply to this topic.