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:
parent
0304d228ae
commit
f10c80c201
@ -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)
|
||||
|
@ -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' );
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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' ),
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user