Make WordPress Core


Ignore:
Timestamp:
05/11/2024 11:51:55 PM (2 years ago)
Author:
peterwilsoncc
Message:

Options, Meta APIs: Prime transient options prior to use.

Reduce the number of queries getting and setting transients on sites without a persistent cache.

Transients are stored in two options: one each for the transient value and timeout. Priming the cache reduces the database queries for getting a transient from two to one.

Props peterwilsoncc, swissspidy.
Fixes #61193.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/option/transient.php

    r54668 r58134  
    7979                update_option( '_transient_timeout_' . $key, $now - 1 );
    8080                $this->assertFalse( get_transient( $key ) );
     81        }
     82
     83        /**
     84         * Ensure get_transient() makes a single database request.
     85         *
     86         * @ticket 61193
     87         *
     88         * @covers ::get_transient
     89         */
     90        public function test_get_transient_with_timeout_makes_a_single_database_call() {
     91                global $wpdb;
     92                $key                        = 'test_transient';
     93                $value                      = 'test_value';
     94                $timeout                    = 100;
     95                $expected_query             = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name IN ('_transient_{$key}','_transient_timeout_{$key}')";
     96                $unexpected_query_transient = "SELECT option_value FROM $wpdb->options WHERE option_name = '_transient_{$key}' LIMIT 1";
     97                $unexpected_query_timeout   = "SELECT option_value FROM $wpdb->options WHERE option_name = '_transient_timeout_{$key}' LIMIT 1";
     98                $queries                    = array();
     99
     100                set_transient( $key, $value, $timeout );
     101
     102                // Clear the cache of both the transient and the timeout.
     103                $option_names = array(
     104                        '_transient_' . $key,
     105                        '_transient_timeout_' . $key,
     106                );
     107                foreach ( $option_names as $option_name ) {
     108                        wp_cache_delete( $option_name, 'options' );
     109                }
     110
     111                add_filter(
     112                        'query',
     113                        function ( $query ) use ( &$queries ) {
     114                                $queries[] = $query;
     115                                return $query;
     116                        }
     117                );
     118
     119                $before_queries = get_num_queries();
     120                $this->assertSame( $value, get_transient( $key ) );
     121                $transient_queries = get_num_queries() - $before_queries;
     122                $this->assertSame( 1, $transient_queries, 'Expected a single database query to retrieve the transient.' );
     123                $this->assertContains( $expected_query, $queries, 'Expected query to prime both transient options in a single call.' );
     124                // Note: Some versions of PHPUnit and/or the test suite may report failures as asserting to contain rather than not to contain.
     125                $this->assertNotContains( $unexpected_query_transient, $queries, 'Unexpected query of transient option individually.' );
     126                $this->assertNotContains( $unexpected_query_timeout, $queries, 'Unexpected query of transient timeout option individually.' );
     127        }
     128
     129        /**
     130         * Ensure set_transient() primes the option cache checking for an existing transient.
     131         *
     132         * @ticket 61193
     133         *
     134         * @covers ::set_transient
     135         */
     136        public function test_set_transient_primes_option_cache() {
     137                global $wpdb;
     138                $key                        = 'test_transient';
     139                $value                      = 'test_value';
     140                $timeout                    = 100;
     141                $expected_query             = "SELECT option_name, option_value FROM $wpdb->options WHERE option_name IN ('_transient_{$key}','_transient_timeout_{$key}')";
     142                $unexpected_query_transient = "SELECT option_value FROM $wpdb->options WHERE option_name = '_transient_{$key}' LIMIT 1";
     143                $unexpected_query_timeout   = "SELECT option_value FROM $wpdb->options WHERE option_name = '_transient_timeout_{$key}' LIMIT 1";
     144                $queries                    = array();
     145
     146                add_filter(
     147                        'query',
     148                        function ( $query ) use ( &$queries ) {
     149                                $queries[] = $query;
     150                                return $query;
     151                        }
     152                );
     153
     154                $before_queries = get_num_queries();
     155                $this->assertTrue( set_transient( $key, $value, $timeout ) );
     156                $transient_queries = get_num_queries() - $before_queries;
     157                $this->assertSame( 3, $transient_queries, 'Expected three database queries setting the transient.' );
     158                $this->assertContains( $expected_query, $queries, 'Expected query to prime both transient options in a single call.' );
     159                // Note: Some versions of PHPUnit and/or the test suite may report failures as asserting to contain rather than not to contain.
     160                $this->assertNotContains( $unexpected_query_transient, $queries, 'Unexpected query of transient option individually.' );
     161                $this->assertNotContains( $unexpected_query_timeout, $queries, 'Unexpected query of transient timeout option individually.' );
    81162        }
    82163
Note: See TracChangeset for help on using the changeset viewer.