Make WordPress Core

Changeset 28972


Ignore:
Timestamp:
07/03/2014 04:44:15 PM (10 years ago)
Author:
helen
Message:

Improve oEmbed caching. Introduces the concept of a TTL for oEmbed caches and a filter for oembed_ttl.

We will no longer replace previously valid oEmbed responses with an {{unknown}} cache value. When this happens due to reaching a rate limit or a service going down, it is data loss, and is not acceptable. This means that oEmbed caches for a post are no longer deleted indiscriminately every time that post is saved.

oEmbed continues to be cached in post meta, with the addition of a separate meta key containing the timestamp of the last retrieval, which is used to avoid re-requesting a recently cached oEmbed response. By default, we consider a valued cached in the past day to be fresh. This can greatly reduce the number of outbound requests, especially in cases where a post containing multiple embeds is saved frequently.

The TTL used to determine whether or not to request a response can be filtered using oembed_ttl, thus allowing for the possibility of respecting the optional oEmbed response parameter cache_age or altering the period of time a cached value is considered to be fresh.

Now that oEmbeds are previewed in the visual editor as well as the media modal, oEmbed caches are often populated before a post is saved or published. By pre-populating and avoiding having to re-request that response, we also greatly reduce the chances of a stampede happening when a published post is visible before oEmbed caching is complete.

As it previously stood, a stampede was extremely likely to happen, as the AJAX caching was only triggered when $_GET['message'] was 1. The published message is 6. We now trigger the caching every time $_GET['message'] is present on the edit screen, as we are able to avoid triggering so many HTTP requests overall.

props markjaquith. fixes #14759. see #17210.

Location:
trunk/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/ajax-actions.php

    r28919 r28972  
    226226 */
    227227function wp_ajax_oembed_cache() {
    228     global $wp_embed;
    229 
    230     $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
    231     wp_die( $return );
     228    $GLOBALS['wp_embed']->cache_oembed( $_GET['post'] );
     229    wp_die( 0 );
    232230}
    233231
  • trunk/src/wp-includes/class-wp-embed.php

    r28923 r28972  
    3232        add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
    3333
    34         // When a post is saved, invalidate the oEmbed cache
    35         add_action( 'pre_post_update', array( $this, 'delete_oembed_caches' ) );
    36 
    3734        // After a post is saved, cache oEmbed items via AJAX
    3835        add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) );
     
    7976        $post = get_post();
    8077
    81         if ( ! $post || empty($_GET['message']) || 1 != $_GET['message'] )
     78        if ( ! $post || empty( $_GET['message'] ) )
    8279            return;
    8380
     
    193190
    194191            // Check for a cached result (stored in the post meta)
    195             $cachekey = '_oembed_' . md5( $url . serialize( $attr ) );
    196             if ( $this->usecache ) {
    197                 $cache = get_post_meta( $post_ID, $cachekey, true );
    198 
    199                 // Failures are cached
     192            $key_suffix = md5( $url . serialize( $attr ) );
     193            $cachekey = '_oembed_' . $key_suffix;
     194            $cachekey_time = '_oembed_time_' . $key_suffix;
     195
     196            /**
     197             * Filter the oEmbed TTL (time to live).
     198             *
     199             * @since 4.0.0
     200             *
     201             * @param string $url     The attempted embed URL.
     202             * @param array  $attr    An array of shortcode attributes.
     203             * @param int    $post_ID Post ID.
     204             */
     205            $ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, $url, $attr, $post_ID );
     206
     207            $cache = get_post_meta( $post_ID, $cachekey, true );
     208            $cache_time = get_post_meta( $post_ID, $cachekey_time, true );
     209
     210            if ( ! $cache_time ) {
     211                $cache_time = 0;
     212            }
     213
     214            $cached_recently = ( time() - $cache_time ) < $ttl;
     215
     216            if ( $this->usecache || $cached_recently ) {
     217                // Failures are cached. Serve one if we're using the cache.
    200218                if ( '{{unknown}}' === $cache )
    201219                    return $this->maybe_make_link( $url );
    202220
    203                 if ( ! empty( $cache ) )
     221                if ( ! empty( $cache ) ) {
    204222                    /**
    205223                     * Filter the cached oEmbed HTML.
     
    215233                     */
    216234                    return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
     235                }
    217236            }
    218237
     
    231250            $html = wp_oembed_get( $url, $attr );
    232251
    233             // Cache the result
    234             $cache = ( $html ) ? $html : '{{unknown}}';
    235             update_post_meta( $post_ID, $cachekey, $cache );
     252            // Maybe cache the result
     253            if ( $html ) {
     254                update_post_meta( $post_ID, $cachekey, $html );
     255                update_post_meta( $post_ID, $cachekey_time, time() );
     256            } elseif ( ! $cache ) {
     257                update_post_meta( $post_ID, $cachekey, '{{unknown}}' );
     258            }
    236259
    237260            // If there was a result, return it
     
    247270
    248271    /**
    249      * Delete all oEmbed caches.
     272     * Delete all oEmbed caches. Unused by core as of 4.0.0.
    250273     *
    251274     * @param int $post_ID Post ID to delete the caches for.
Note: See TracChangeset for help on using the changeset viewer.