Remove broken Transient cache for large query results

This did not consider the meta cache and caused potentially hundreds of additional queries instead of preventing them. Welp.
This commit is contained in:
Tetrakern 2024-10-17 16:06:13 +02:00
parent 0304d228ae
commit f10c80c201
6 changed files with 3 additions and 282 deletions

View File

@ -301,7 +301,7 @@ Fictioneer customizes WordPress by using as many standard action and filter hook
| `save_post` | `fictioneer_refresh_chapters_schema` (20), `fictioneer_refresh_chapter_schema` (20), `fictioneer_refresh_collections_schema` (20), `fictioneer_refresh_post_caches` (20), `fictioneer_refresh_post_schema` (20), `fictioneer_refresh_recommendations_schema` (20), `fictioneer_refresh_recommendation_schema` (20), `fictioneer_refresh_stories_schema` (20), `fictioneer_refresh_story_schema` (20), `fictioneer_save_seo_metabox` (10), `fictioneer_save_word_count` (10), `fictioneer_track_chapter_and_story_updates` (10), `fictioneer_update_modified_date_on_story_for_chapter` (10), `fictioneer_update_shortcode_relationships` (10), `fictioneer_purge_transients_after_update` (10), `fictioneer_save_story_metaboxes` (10), `fictioneer_save_chapter_metaboxes` (10), `fictioneer_save_extra_metabox` (10), `fictioneer_save_support_links_metabox` (10), `fictioneer_save_collection_metaboxes` (10), `fictioneer_save_recommendation_metaboxes` (10), `fictioneer_save_post_metaboxes` (10), `fictioneer_delete_cached_story_card_after_update` (10), `fictioneer_rebuild_story_data_collection` (999), `fictioneer_post_chapter_to_discord` (99), `fictioneer_bulk_edit_save_patreon` (10), `fictioneer_bulk_edit_save_chapter_fields` (10)
| `send_headers` | `fictioneer_block_pages_from_indexing` (10)
| `show_user_profile` | `fictioneer_custom_profile_fields` (20)
| `shutdown` | `fictioneer_save_story_card_cache` (10), `fictioneer_save_query_result_cache_registry` (10)
| `shutdown` | `fictioneer_save_story_card_cache` (10)
| `switch_theme` | `fictioneer_theme_deactivation` (10)
| `template_redirect` | `fictioneer_generate_epub` (10), `fictioneer_oauth2_process` (10), `fictioneer_logout` (10), `fictioneer_disable_attachment_pages` (10), `fictioneer_gate_unpublished_content` (10), `fictioneer_serve_sitemap` (10), `fictioneer_redirect_story` (10)
| `transition_post_status` | `fictioneer_log_story_chapter_status_changes` (10), `fictioneer_chapter_future_to_publish` (10), `fictioneer_post_story_to_discord` (99)

View File

@ -117,14 +117,6 @@ if ( ! defined( 'FICTIONEER_ENABLE_STORY_CARD_CACHING' ) ) {
);
}
// Boolean: Query result caching enabled?
if ( ! defined( 'FICTIONEER_ENABLE_QUERY_RESULT_CACHING' ) ) {
define(
'FICTIONEER_ENABLE_QUERY_RESULT_CACHING',
get_option( 'fictioneer_enable_query_result_caching' ) && ! is_customize_preview()
);
}
// =============================================================================
// ENABLE TRANSIENTS?
// =============================================================================
@ -1482,233 +1474,3 @@ function fictioneer_save_story_card_cache() {
set_transient( 'fictioneer_card_cache', $fictioneer_story_card_cache, FICTIONEER_CARD_CACHE_EXPIRATION_TIME );
}
add_action( 'shutdown', 'fictioneer_save_story_card_cache' );
// =============================================================================
// TRANSIENT QUERY RESULT CACHE
// =============================================================================
/**
* Checks whether the registry is locked by another process
*
* Note: Locks the registry for 30 seconds if currently unlocked,
* which needs to be cleared afterwards. The lock state for this
* process is cached in a static variable.
*
* @since 5.22.3
*
* @return bool True if locked, false if free for this process.
*/
function fictioneer_query_result_cache_lock() {
static $lock = null;
if ( $lock !== null ) {
return $lock;
}
if ( get_transient( 'fictioneer_query_result_cache_lock' ) ) {
$lock = true;
} else {
set_transient( 'fictioneer_query_result_cache_lock', 1, 30 );
$lock = false;
}
return $lock;
}
/**
* Returns the global registry array for cached query results
*
* Note: The registry is stored as auto-loaded options in the
* database and set up as global variable on request. It is
* only updated in the 'shutdown' action.
*
* @since 5.22.3
* @global $fictioneer_query_result_registry
*
* @return array Array with Transient keys for cached query results.
*/
function fictioneer_get_query_result_cache_registry() {
// Abort if...
if ( ! FICTIONEER_ENABLE_QUERY_RESULT_CACHING ) {
return [];
}
// Initialize lock to avoid race conditions
fictioneer_query_result_cache_lock();
// Initialize global cache variable
global $fictioneer_query_result_registry;
if ( ! $fictioneer_query_result_registry ) {
$fictioneer_query_result_registry = get_option( 'fictioneer_query_cache_registry' );
if ( ! is_array( $fictioneer_query_result_registry ) ) {
$fictioneer_query_result_registry = [];
update_option( 'fictioneer_query_cache_registry', [] );
}
}
// Return array for good measure, but the global will do
return $fictioneer_query_result_registry;
}
/**
* Adds query result to the global query result cache
*
* Note: Only query results that exceed a certain threshold (75)
* are stored in the cache and only the latest n items (50).
*
* @since 5.22.3
* @global $fictioneer_query_result_registry
* @see FICTIONEER_QUERY_RESULT_CACHE_THRESHOLD
* @see FICTIONEER_QUERY_RESULT_CACHE_LIMIT
*
* @param string $key The cache key of the query.
* @param array $result The result of the query.
*/
function fictioneer_cache_query_result( $key, $result ) {
// Abort if...
if ( ! FICTIONEER_ENABLE_QUERY_RESULT_CACHING || fictioneer_query_result_cache_lock() ) {
return;
}
if ( count( $result ) < FICTIONEER_QUERY_RESULT_CACHE_THRESHOLD ) {
return;
}
// Initialize global cache variable
global $fictioneer_query_result_registry;
if ( ! $fictioneer_query_result_registry ) {
$fictioneer_query_result_registry = fictioneer_get_query_result_cache_registry();
}
// Build key; must begin with fictioneer_query_{$post_id} for clearing purposes
$transient_key = "fictioneer_query_{$key}";
// Prepend result to stack
$fictioneer_query_result_registry = array_merge( array( $key => $transient_key ), $fictioneer_query_result_registry );
// Randomized expiration to avoid large sets of results to expire simultaneously
set_transient( $transient_key, $result, 8 * HOUR_IN_SECONDS + rand( 0, 4 * HOUR_IN_SECONDS ) );
// Only allow n items in the cache to avoid bloating the database
if ( count( $fictioneer_query_result_registry ) > FICTIONEER_QUERY_RESULT_CACHE_LIMIT ) {
array_pop( $fictioneer_query_result_registry ); // Drop oldest entry
}
}
/**
* Adds query result to the global query result cache
*
* Note: Only query results that exceed a certain threshold (75)
* are stored in the cache and only the latest n items (50).
*
* @since 5.22.3
* @global $fictioneer_query_result_registry
*
* @param string $key The cache key of the query.
*
* @return array|null Array of WP_Post objects or null if not cached or expired.
*/
function fictioneer_get_cached_query_result( $key ) {
// Abort if...
if ( ! FICTIONEER_ENABLE_QUERY_RESULT_CACHING ) {
return null;
}
// Initialize global cache variable
global $fictioneer_query_result_registry;
if ( ! $fictioneer_query_result_registry ) {
$fictioneer_query_result_registry = fictioneer_get_query_result_cache_registry();
}
// Look for cached result...
if ( isset( $fictioneer_query_result_registry[ $key ] ) ) {
$transient = get_transient( $fictioneer_query_result_registry[ $key ] );
if ( is_array( $transient ) ) {
// Hit
return $transient;
} else {
// Miss
fictioneer_delete_cached_query_result( $key ); // Cleanup
}
}
// Nothing cached or expired
return null;
}
/**
* Deletes query result from the global query result cache
*
* @since 5.22.3
* @global $fictioneer_query_result_registry
*
* @param string $key The cache key of the query.
*/
function fictioneer_delete_cached_query_result( $key ) {
// Abort if...
if ( ! FICTIONEER_ENABLE_QUERY_RESULT_CACHING ) {
return;
}
// Initialize global cache variable
global $fictioneer_query_result_registry;
if ( ! $fictioneer_query_result_registry ) {
$fictioneer_query_result_registry = fictioneer_get_query_result_cache_registry();
}
// Remove entry (if present)
unset( $fictioneer_query_result_registry[ $key ] );
}
/**
* Saves the final global query result cache to the database
*
* @since 5.22.3
* @global $fictioneer_query_result_registry
*/
function fictioneer_save_query_result_cache_registry() {
// Abort if...
if ( ! FICTIONEER_ENABLE_QUERY_RESULT_CACHING || fictioneer_query_result_cache_lock() ) {
return;
}
// Clear lock
delete_transient( 'fictioneer_query_result_cache_lock' );
// Initialize global cache variable
global $fictioneer_query_result_registry;
if ( is_null( $fictioneer_query_result_registry ) || ! is_array( $fictioneer_query_result_registry ) ) {
return;
}
// Ensure the limit is respected
$count = count( $fictioneer_query_result_registry );
if ( $count > FICTIONEER_QUERY_RESULT_CACHE_LIMIT ) {
$fictioneer_query_result_registry = array_slice(
$fictioneer_query_result_registry,
0,
FICTIONEER_QUERY_RESULT_CACHE_LIMIT,
true
);
}
// Anything to save?
if ( $fictioneer_query_result_registry !== get_option( 'fictioneer_query_cache_registry' ) ) {
update_option( 'fictioneer_query_cache_registry', $fictioneer_query_result_registry ?: [] );
}
}
add_action( 'shutdown', 'fictioneer_save_query_result_cache_registry' );

View File

@ -61,10 +61,10 @@ function fictioneer_get_theme_cache_dir( $context = null ) {
function fictioneer_bring_out_legacy_trash() {
// Setup
$options = wp_cache_get( 'alloptions', 'options' );
$obsolete = ['fictioneer_disable_html_in_comments', 'fictioneer_block_subscribers_from_admin', 'fictioneer_admin_restrict_menus', 'fictioneer_admin_restrict_private_data', 'fictioneer_admin_reduce_subscriber_profile', 'fictioneer_enable_subscriber_self_delete', 'fictioneer_strip_shortcodes_for_non_administrators', 'fictioneer_restrict_media_access', 'fictioneer_subscription_enabled', 'fictioneer_patreon_badge_map', 'fictioneer_patreon_tier_as_badge', 'fictioneer_patreon_campaign_ids', 'fictioneer_patreon_campaign_id', 'fictioneer_mount_wpdiscuz_theme_styles', 'fictioneer_base_site_width', 'fictioneer_featherlight_enabled', 'fictioneer_tts_enabled', 'fictioneer_log', 'fictioneer_enable_ajax_nonce', 'fictioneer_flush_object_cache', 'fictioneer_enable_all_block_styles', 'fictioneer_light_mode_as_default', 'fictioneer_remove_wp_svg_filters', 'fictioneer_update_check_timestamp', 'fictioneer_latest_version', 'fictioneer_update_notice_timestamp', 'fictioneer_theme_status', 'fictioneer_disable_anti_flicker'];
$obsolete = ['fictioneer_disable_html_in_comments', 'fictioneer_block_subscribers_from_admin', 'fictioneer_admin_restrict_menus', 'fictioneer_admin_restrict_private_data', 'fictioneer_admin_reduce_subscriber_profile', 'fictioneer_enable_subscriber_self_delete', 'fictioneer_strip_shortcodes_for_non_administrators', 'fictioneer_restrict_media_access', 'fictioneer_subscription_enabled', 'fictioneer_patreon_badge_map', 'fictioneer_patreon_tier_as_badge', 'fictioneer_patreon_campaign_ids', 'fictioneer_patreon_campaign_id', 'fictioneer_mount_wpdiscuz_theme_styles', 'fictioneer_base_site_width', 'fictioneer_featherlight_enabled', 'fictioneer_tts_enabled', 'fictioneer_log', 'fictioneer_enable_ajax_nonce', 'fictioneer_flush_object_cache', 'fictioneer_enable_all_block_styles', 'fictioneer_light_mode_as_default', 'fictioneer_remove_wp_svg_filters', 'fictioneer_update_check_timestamp', 'fictioneer_latest_version', 'fictioneer_update_notice_timestamp', 'fictioneer_theme_status', 'fictioneer_disable_anti_flicker', 'fictioneer_query_cache_registry', 'fictioneer_enable_query_result_caching'];
// Check for most recent obsolete option...
if ( isset( $options['fictioneer_disable_anti_flicker'] ) ) {
if ( isset( $options['fictioneer_enable_query_result_caching'] ) ) {
// Looping everything is not great but it only happens once!
foreach ( $obsolete as $trash ) {
delete_option( $trash );

View File

@ -234,7 +234,6 @@ if ( ! function_exists( 'fictioneer_get_last_fiction_update' ) ) {
function fictioneer_get_story_chapter_posts( $story_id, $args = [], $full = false ) {
// Static variable cache
static $cached_results = [];
static $query_count = 0;
// Setup
$chapter_ids = fictioneer_get_story_chapter_ids( $story_id );
@ -267,13 +266,6 @@ function fictioneer_get_story_chapter_posts( $story_id, $args = [], $full = fals
return $cached_results[ $cache_key ];
}
// Query result cache registry hit?
$cached_query_result = fictioneer_get_cached_query_result( $cache_key );
if ( $cached_query_result ) {
return $cached_query_result;
}
// Batched or one go?
if ( count( $chapter_ids ) <= FICTIONEER_QUERY_ID_ARRAY_LIMIT ) {
$query_args['post__in'] = $chapter_ids ?: [0];
@ -320,17 +312,6 @@ function fictioneer_get_story_chapter_posts( $story_id, $args = [], $full = fals
}
}
// Count query
$query_count++;
// Cache for subsequent calls
$cached_results[ $cache_key ] = $chapter_posts;
// Put on breaks for large queries uploaded to the database
if ( $query_count <= FICTIONEER_QUERY_RESULT_CACHE_BREAK ) {
fictioneer_cache_query_result( $cache_key, $chapter_posts );
}
// Return chapters selected in story
return $chapter_posts;
}

View File

@ -690,12 +690,6 @@ define( 'FICTIONEER_OPTIONS', array(
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
'default' => 0
),
'fictioneer_enable_query_result_caching' => array(
'name' => 'fictioneer_enable_query_result_caching',
'group' => 'fictioneer-settings-general-group',
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
'default' => 0
),
'fictioneer_allow_rest_save_actions' => array(
'name' => 'fictioneer_allow_rest_save_actions',
'group' => 'fictioneer-settings-general-group',
@ -1209,7 +1203,6 @@ function fictioneer_get_option_label( $option ) {
'fictioneer_enable_anti_flicker' => __( 'Enable anti-flicker script', 'fictioneer' ),
'fictioneer_hide_categories' => __( 'Hide categories on posts', 'fictioneer' ),
'fictioneer_enable_story_card_caching' => __( 'Enable caching of story cards', 'fictioneer' ),
'fictioneer_enable_query_result_caching' => __( 'Enable caching of large query results', 'fictioneer' ),
'fictioneer_allow_rest_save_actions' => __( 'Allow REST requests to trigger save actions', 'fictioneer' ),
'fictioneer_enable_global_splide' => __( 'Enable Splide slider globally', 'fictioneer' ),
'fictioneer_log_posts' => __( 'Log all post updates', 'fictioneer' ),

View File

@ -839,21 +839,6 @@ $images = get_template_directory_uri() . '/img/documentation/';
?>
</div>
<div class="fictioneer-card__row">
<?php
fictioneer_settings_label_checkbox(
'fictioneer_enable_query_result_caching',
__( 'Enable caching of large query results', 'fictioneer' ),
sprintf(
__( 'Caches the latest %d query results with %s or more posts in the database to speed up loading.', 'fictioneer' ),
FICTIONEER_QUERY_RESULT_CACHE_LIMIT,
FICTIONEER_QUERY_RESULT_CACHE_THRESHOLD
),
__( '<p>With this feature enabled, the results of large queries are cached in the database. Repeating resource-intensive queries, especially for stories with hundreds of chapters, can slow down the site and even cause timeouts. Caching them typically leads to faster loading times.</p><p>You can use the <code>FICTIONEER_QUERY_RESULT_CACHE_THRESHOLD</code> constant to define what constitutes as large query result (default is 50) and the <code>FICTIONEER_QUERY_RESULT_CACHE_LIMIT</code> constant to change the number of cached results (default is 50). Be aware that increasing these numbers will result in higher RAM consumption.</p>', 'fictioneer' )
);
?>
</div>
</div>
</div>
</div>