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.

Built from https://develop.svn.wordpress.org/trunk@28972


git-svn-id: http://core.svn.wordpress.org/trunk@28761 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Helen Hou-Sandí 2014-07-03 16:45:14 +00:00
parent c6c1f56d60
commit 5f6b531f70
2 changed files with 38 additions and 17 deletions

View File

@ -225,10 +225,8 @@ function wp_ajax_imgedit_preview() {
* @since 3.1.0
*/
function wp_ajax_oembed_cache() {
global $wp_embed;
$return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
wp_die( $return );
$GLOBALS['wp_embed']->cache_oembed( $_GET['post'] );
wp_die( 0 );
}
/**

View File

@ -31,9 +31,6 @@ class WP_Embed {
// Attempts to embed all URLs in a post
add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
// When a post is saved, invalidate the oEmbed cache
add_action( 'pre_post_update', array( $this, 'delete_oembed_caches' ) );
// After a post is saved, cache oEmbed items via AJAX
add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) );
}
@ -78,7 +75,7 @@ class WP_Embed {
public function maybe_run_ajax_cache() {
$post = get_post();
if ( ! $post || empty($_GET['message']) || 1 != $_GET['message'] )
if ( ! $post || empty( $_GET['message'] ) )
return;
?>
@ -192,15 +189,36 @@ class WP_Embed {
if ( $post_ID ) {
// Check for a cached result (stored in the post meta)
$cachekey = '_oembed_' . md5( $url . serialize( $attr ) );
if ( $this->usecache ) {
$cache = get_post_meta( $post_ID, $cachekey, true );
$key_suffix = md5( $url . serialize( $attr ) );
$cachekey = '_oembed_' . $key_suffix;
$cachekey_time = '_oembed_time_' . $key_suffix;
// Failures are cached
/**
* Filter the oEmbed TTL (time to live).
*
* @since 4.0.0
*
* @param string $url The attempted embed URL.
* @param array $attr An array of shortcode attributes.
* @param int $post_ID Post ID.
*/
$ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, $url, $attr, $post_ID );
$cache = get_post_meta( $post_ID, $cachekey, true );
$cache_time = get_post_meta( $post_ID, $cachekey_time, true );
if ( ! $cache_time ) {
$cache_time = 0;
}
$cached_recently = ( time() - $cache_time ) < $ttl;
if ( $this->usecache || $cached_recently ) {
// Failures are cached. Serve one if we're using the cache.
if ( '{{unknown}}' === $cache )
return $this->maybe_make_link( $url );
if ( ! empty( $cache ) )
if ( ! empty( $cache ) ) {
/**
* Filter the cached oEmbed HTML.
*
@ -214,6 +232,7 @@ class WP_Embed {
* @param int $post_ID Post ID.
*/
return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
}
}
/**
@ -230,9 +249,13 @@ class WP_Embed {
// Use oEmbed to get the HTML
$html = wp_oembed_get( $url, $attr );
// Cache the result
$cache = ( $html ) ? $html : '{{unknown}}';
update_post_meta( $post_ID, $cachekey, $cache );
// Maybe cache the result
if ( $html ) {
update_post_meta( $post_ID, $cachekey, $html );
update_post_meta( $post_ID, $cachekey_time, time() );
} elseif ( ! $cache ) {
update_post_meta( $post_ID, $cachekey, '{{unknown}}' );
}
// If there was a result, return it
if ( $html ) {
@ -246,7 +269,7 @@ class WP_Embed {
}
/**
* Delete all oEmbed caches.
* Delete all oEmbed caches. Unused by core as of 4.0.0.
*
* @param int $post_ID Post ID to delete the caches for.
*/