From 0cd2a9db5b985f7191e2d579409ed9301baf6377 Mon Sep 17 00:00:00 2001 From: wpdev Date: Sun, 27 Sep 2026 22:41:46 +0800 Subject: [PATCH 1/3] perf(2meet-data-optimizer-hivepress-addon): (column, post_id) indexes for the listing sorts HivePress offers - hp_listing_core declares (hp_price, post_id), (hp_rating, post_id) and (hp_hourly_rate, post_id): with core 1.4.0 a flat-first price, rating or hourly-rate sort reads them in order instead of sorting every match (dev36 stage 3: the price-range + price-sort search was the slowest routed page, 2.9 s at 1.3M listings); core 1.3.0 ignores indexes ending with post_id - the pinned schema hash is unchanged (indexes are not part of it) - Verify: HivePressEntityGroupsTest, unit 148, integration 53, phpcs; dev36 front-end sorts - PR: PR-119 --- .../class-tmdo-hivepress-entity-groups.php | 9 +++++++-- tests/unit/HivePressEntityGroupsTest.php | 20 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/includes/class-tmdo-hivepress-entity-groups.php b/includes/class-tmdo-hivepress-entity-groups.php index 42a78f8..6dc4071 100644 --- a/includes/class-tmdo-hivepress-entity-groups.php +++ b/includes/class-tmdo-hivepress-entity-groups.php @@ -266,8 +266,13 @@ final class TMDO_HivePress_Entity_Groups { // Only with core 1.3.0+ (ddl_allowed()): older cores run the ALTER // inside whatever request comes first, a visitor's included. 'indexes' => method_exists( 'TMDO_Schema_Manager', 'ddl_allowed' ) ? array( - 'hourly_rate' => array( 'hp_hourly_rate' ), - 'rating_count' => array( 'hp_rating_count' ), + 'hourly_rate' => array( 'hp_hourly_rate' ), + 'rating_count' => array( 'hp_rating_count' ), + // HivePress sorts: the value then the ID tie-break, which core 1.4.0 + // reads in order (flat-first) instead of sorting every match. + 'price_id' => array( 'hp_price', 'post_id' ), + 'rating_id' => array( 'hp_rating', 'post_id' ), + 'hourly_rate_id' => array( 'hp_hourly_rate', 'post_id' ), ) : array(), ) ); diff --git a/tests/unit/HivePressEntityGroupsTest.php b/tests/unit/HivePressEntityGroupsTest.php index e004493..2dffdc4 100644 --- a/tests/unit/HivePressEntityGroupsTest.php +++ b/tests/unit/HivePressEntityGroupsTest.php @@ -37,9 +37,15 @@ class HivePressEntityGroupsTest extends TestCase { 'hp_user' => 'hp_vendor_core', ); + private function post_adapter(): TMDO_Entity_Adapter_Interface { + $adapter = $this->createMock( TMDO_Entity_Adapter_Interface::class ); + $adapter->method( 'get_entity_id_column' )->willReturn( 'post_id' ); + return $adapter; + } + protected function setUp(): void { TMDO_Entity_Registry::init(); - TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); + TMDO_Entity_Registry::register_adapter( 'post', $this->post_adapter() ); TMDO_Entity_Registry::register_adapter( 'user', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); TMDO_HivePress_Entity_Groups::register_entity_fields(); } @@ -66,8 +72,12 @@ class HivePressEntityGroupsTest extends TestCase { public function test_listing_columns_filtered_and_sorted_on_are_indexed(): void { $this->assertSame( array( - 'hourly_rate' => array( 'hp_hourly_rate' ), - 'rating_count' => array( 'hp_rating_count' ), + 'hourly_rate' => array( 'hp_hourly_rate' ), + 'rating_count' => array( 'hp_rating_count' ), + // Sorts: the value then the ID tie-break, read in order (2.4 PR-119). + 'price_id' => array( 'hp_price', 'post_id' ), + 'rating_id' => array( 'hp_rating', 'post_id' ), + 'hourly_rate_id' => array( 'hp_hourly_rate', 'post_id' ), ), TMDO_Entity_Registry::get_group_indexes( 'post', 'hp_listing_core' ) ); @@ -94,7 +104,7 @@ class HivePressEntityGroupsTest extends TestCase { $GLOBALS['_wp_did_action']['after_setup_theme'] = 1; try { TMDO_Entity_Registry::init(); - TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); + TMDO_Entity_Registry::register_adapter( 'post', $this->post_adapter() ); TMDO_Entity_Registry::register_adapter( 'user', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); TMDO_HivePress_Entity_Groups::register_entity_fields(); } finally { @@ -118,7 +128,7 @@ class HivePressEntityGroupsTest extends TestCase { add_filter( 'tmdo_hp_listing_attribute_fields', static fn() => array( 'hp_warranty' => 'integer' ) ); try { TMDO_Entity_Registry::init(); - TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); + TMDO_Entity_Registry::register_adapter( 'post', $this->post_adapter() ); TMDO_Entity_Registry::register_adapter( 'user', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); TMDO_HivePress_Entity_Groups::register_entity_fields(); $this->assertSame( array(), TMDO_Entity_Registry::get_group_keys( 'post', 'hp_listing_attrs' ), 'plugins_loaded run: not yet' ); From 15bbf335f40f1f88fae99e98596441413526f5d5 Mon Sep 17 00:00:00 2001 From: wpdev Date: Sun, 27 Sep 2026 23:26:08 +0800 Subject: [PATCH 2/3] perf(2meet-data-optimizer-hivepress-addon): keep HivePress transients a day in the object cache - MAX_CACHE_TTL: a week -> a day (HivePress's own default); a timeout still outlives its value by a minute - dev36 (1.3M listings): 4.7M entries / 1 GB in the shared Redis at a week, evicting other sites' keys - Verify: composer test (148), integration (53), phpcs clean on the file - PR: PR-120 --- includes/class-tmdo-hivepress-transient-filter.php | 4 ++-- tests/integration/HivepressTransientFilterTest.php | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/includes/class-tmdo-hivepress-transient-filter.php b/includes/class-tmdo-hivepress-transient-filter.php index 85a681a..c5a0f44 100644 --- a/includes/class-tmdo-hivepress-transient-filter.php +++ b/includes/class-tmdo-hivepress-transient-filter.php @@ -80,8 +80,8 @@ final class TMDO_Hivepress_Transient_Filter { /** Object cache group used instead of wp_options when a persistent cache is present. */ public const CACHE_GROUP = 'tmdo_hp_transient'; - /** Longest an object-cache entry lives: a week (HivePress's default is a day). */ - public const MAX_CACHE_TTL = 604800; + /** Longest an object-cache entry lives: a day, HivePress's own default (2.4 PR-120). */ + public const MAX_CACHE_TTL = DAY_IN_SECONDS; /** * Register the four metadata filters on `init`. Idempotent — safe to call diff --git a/tests/integration/HivepressTransientFilterTest.php b/tests/integration/HivepressTransientFilterTest.php index ada423f..92fae91 100644 --- a/tests/integration/HivepressTransientFilterTest.php +++ b/tests/integration/HivepressTransientFilterTest.php @@ -215,11 +215,14 @@ class HivepressTransientFilterTest extends TestCase { /** * Entries expire in the object cache too (2.3 PR-099): the value (written - * first, before its timeout is known) after a week, the timeout after the + * first, before its timeout is known) after a day, the timeout after the * later of that and its own time, plus a minute. Orphans of deleted posts * no longer pile up. */ public function test_with_an_object_cache_entries_get_a_ttl(): void { + // A day, HivePress's own default: at a week, 1.3M listings kept 4.7M + // entries (1 GB) in a shared Redis and pushed other sites' keys out (2.4 PR-120). + $this->assertSame( 86400, WPDO_Hivepress_Transient_Filter::MAX_CACHE_TTL ); $GLOBALS['_wp_using_ext_object_cache'] = true; $key = '_transient_hp_models/cat/v1'; $translated = WPDO_Hivepress_Transient_Filter::translate_key( 100, $key ); From bfe89126005c4171f8bce3448530b20ae0a64a90 Mon Sep 17 00:00:00 2001 From: wpdev Date: Sun, 27 Sep 2026 23:29:33 +0800 Subject: [PATCH 3/3] chore(2meet-data-optimizer-hivepress-addon): 0.5.0 release notes and version - CHANGELOG: PR-119 (sort indexes ending with post_id), PR-120 (a day's TTL) - Version 0.4.0 -> 0.5.0 (header, TMDO_HIVEPRESS_VERSION) - PR: PR-125 --- 2meet-data-optimizer-hivepress-addon.php | 4 ++-- CHANGELOG.md | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/2meet-data-optimizer-hivepress-addon.php b/2meet-data-optimizer-hivepress-addon.php index d57a191..8cb85fc 100644 --- a/2meet-data-optimizer-hivepress-addon.php +++ b/2meet-data-optimizer-hivepress-addon.php @@ -3,7 +3,7 @@ * Plugin Name: 2meet Data Optimizer — Hivepress AddOn * Plugin URI: https://2meet.io/2meet-data-optimizer/hivepress * Description: HivePress + 12 擴充整合:13 adapter (core/reviews/bookings/messages/memberships/requests/favorites/statistics/tags/seo/social-links/blocks/marketplace) + 7 HPCT interceptor + 5 query interceptor + admin tab + CLI namespace - * Version: 0.4.0 + * Version: 0.5.0 * Requires at least: 6.0 * Tested up to: 6.9.4 * Requires PHP: 8.1 @@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } -define( 'TMDO_HIVEPRESS_VERSION', '0.4.0' ); +define( 'TMDO_HIVEPRESS_VERSION', '0.5.0' ); define( 'TMDO_HIVEPRESS_PATH', plugin_dir_path( __FILE__ ) ); define( 'TMDO_HIVEPRESS_URL', plugin_dir_url( __FILE__ ) ); define( 'TMDO_HIVEPRESS_FILE', __FILE__ ); diff --git a/CHANGELOG.md b/CHANGELOG.md index d5c29f8..b23d027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,26 @@ Versioning follows [Semantic Versioning](https://semver.org/). --- +## [0.5.0] — 2026-09-28 + +Released with 2meet-data-optimizer 1.4.0 (hardening 2.4). + +### Changed + +- `hp_listing_core` declares `(hp_price, post_id)`, `(hp_rating, post_id)` and + `(hp_hourly_rate, post_id)` indexes for the listing sorts HivePress offers: + with core 1.4.0 reading the ID tie-break from the flat `post_id`, a sort walks + the index and stops at the page instead of sorting every match (dev36, 1.3M + listings: price sort 14 s native → 0.37 s routed, hourly rate 11.5 s → 0.35 s, + rating 43 s → 0.51 s). Core 1.3.0 ignores indexes ending with `post_id`, so + nothing changes there. The pinned schema hash is unchanged. (PR-119) +- Transient entries in a persistent object cache live a day (`MAX_CACHE_TTL`, + HivePress's own default) instead of a week; a timeout still outlives its value + by a minute. At a week dev36 kept 4.7M entries (1 GB) in the shared Redis and + pushed other sites' keys out. Entries already cached keep their week. (PR-120) + +--- + ## [0.4.0] — 2026-09-27 Released with 2meet-data-optimizer 1.3.0 (hardening 2.3).