fix(2meet-data-optimizer-hivepress-addon): keep HivePress transients in the object cache when there is one

- With a persistent object cache (wp_using_ext_object_cache(), Redis on the HivePress sites) the transient filter stores HivePress's per-post transient pairs in the tmdo_hp_transient cache group instead of wp_options, where they piled up (1.15 M rows on dev36). Reads fall back to wp_options for values written before; deletes clear both. Without an object cache nothing changes.
- Verify: HivepressTransientFilterTest object-cache cases (RED before); dev36 with Redis: update/get/delete_post_meta on an HP transient key leaves 0 rows in wp_options and postmeta.
- PR: PR-081
This commit is contained in:
2026-09-27 09:00:03 +08:00
parent fda9e43087
commit b515b8441e
3 changed files with 72 additions and 7 deletions
@@ -77,6 +77,9 @@ final class TMDO_Hivepress_Transient_Filter {
/** Namespace prefix for translated wp_options entries. */
public const TRANSLATED_NAMESPACE = 'wpdo_hp_pm_';
/** Object cache group used instead of wp_options when a persistent cache is present. */
public const CACHE_GROUP = 'tmdo_hp_transient';
/**
* Register the four metadata filters on `init`. Idempotent — safe to call
* multiple times.
@@ -164,7 +167,11 @@ final class TMDO_Hivepress_Transient_Filter {
// HivePress cache layer reads the timeout *first*, then decides whether
// to read the value. We must preserve raw stored values until HivePress
// itself orders deletion.
$value = get_option( $option_name, null );
$value = wp_using_ext_object_cache() ? wp_cache_get( $option_name, self::CACHE_GROUP ) : false;
if ( false === $value ) {
// wp_options: where values went before an object cache was used.
$value = get_option( $option_name, null );
}
if ( null === $value ) {
// Cache miss in our store → fall through to normal postmeta path
@@ -239,16 +246,23 @@ final class TMDO_Hivepress_Transient_Filter {
$translated = self::translate_key( (int) $object_id, (string) $meta_key );
$option_name = ( $is_timeout ? '_transient_timeout_' : '_transient_' ) . $translated;
if ( wp_using_ext_object_cache() ) {
wp_cache_delete( $option_name, self::CACHE_GROUP );
}
delete_option( $option_name );
return true;
}
/**
* Internal: persist value or timeout to wp_options.
* Internal: persist value or timeout to the object cache when a persistent
* one is in use (Redis: a TTL cache belongs there, not in wp_options), else
* to wp_options.
*
* Both halves of the transient pair are written with `autoload=no` (they
* are read on-demand only — never via wp_load_alloptions() — so eagerly
* loading them on every page would defeat the point of the move).
* In wp_options both halves of the transient pair are written with
* `autoload=no` (they are read on-demand only — never via
* wp_load_alloptions() — so eagerly loading them on every page would defeat
* the point of the move). HivePress checks the timeout itself, so the
* cache entries get no TTL of their own.
*
* @param int $post_id Post ID.
* @param string $meta_key Original `_transient_*` meta_key.
@@ -260,6 +274,10 @@ final class TMDO_Hivepress_Transient_Filter {
$translated = self::translate_key( $post_id, $meta_key );
$option_name = ( $is_timeout ? '_transient_timeout_' : '_transient_' ) . $translated;
if ( wp_using_ext_object_cache() ) {
wp_cache_set( $option_name, $meta_value, self::CACHE_GROUP );
return;
}
update_option( $option_name, $meta_value, false );
}