Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add caching for VideoPress functions with meta queries #14803

Merged
merged 14 commits into from
Mar 23, 2020

Conversation

kienstra
Copy link
Contributor

@kienstra kienstra commented Feb 26, 2020

Changes proposed in this Pull Request:

  • Caches functions that use WP_Query
  • Adds some arguments to WP_Query to improve performance, like 'no_found_rows' => true
  • Adds a few unit tests

Is this a new feature or does it add/remove features to an existing part of Jetpack?

  • Enhances an existing feature, no intended change to functionality

Testing instructions:

(Regression testing for VideoPress)

  1. Ensure VideoPress is enabled:
    settings-jetpack

  2. Create a new post

  3. Add a Video block

  4. Upload a video to it

  5. Expected: the video plays in the editor.

  6. Expected: the video plays on the front-end

Proposed changelog entry for your changes:

  • Performance enhancement for VideoPress, caching and improving queries

These involve meta queries,
so it'd be good to have
some kind of caching.
@kienstra kienstra requested a review from a team as a code owner February 26, 2020 00:34
@@ -108,8 +108,8 @@ public function __construct( $guid, $maxwidth = 0, $options = array() ) {

if ( ! defined( 'WP_DEBUG' ) || WP_DEBUG !== true ) {
$expire = 3600;
if ( isset( $video->expires ) && is_int( $video->expires ) ) {
$expires_diff = time() - $video->expires;
if ( isset( $this->video->expires ) && is_int( $this->video->expires ) ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With unset( $video ); above, it looks like isset( $video->expires ) will never be true

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch.

@jetpackbot
Copy link

jetpackbot commented Feb 26, 2020

Thank you for the great PR description!

When this PR is ready for review, please apply the [Status] Needs Review label. If you are an a11n, please have someone from your team review the code if possible. The Jetpack team will also review this PR and merge it to be included in the next Jetpack release.

Scheduled Jetpack release: April 7, 2020.
Scheduled code freeze: March 31, 2020

Generated by 🚫 dangerJS against c13c629

@@ -655,9 +678,13 @@ function video_get_post_by_guid( $guid ) {

$query = new WP_Query( $args );

$post = $query->next_post();
Copy link
Contributor Author

@kienstra kienstra Feb 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can be an error here if the query didn't find any posts.

@kienstra kienstra added the [Status] Needs Review To request a review from Crew. Label will be renamed soon. label Feb 26, 2020
@@ -111,7 +117,9 @@ function videopress_get_attachment_id_by_url( $url ) {
$cropped_files = wp_list_pluck( $meta['sizes'], 'file' );

if ( $original_file === $file || in_array( $file, $cropped_files ) ) {
return (int) $attachment_id;
$attachment_id = (int) $attachment_id;
wp_cache_set( $cache_key, $attachment_id, $cache_group, HOUR_IN_SECONDS );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the cache expiration time should be different

@jeherve jeherve added [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Focus] Performance [Feature] VideoPress A feature to help you upload and insert videos on your site. labels Feb 26, 2020
@jeherve jeherve added this to the 8.4 milestone Feb 26, 2020
$file = basename( $url );
$cache_key = 'videopress_get_attachment_id_by_url_' . md5( $url );
$cache_group = 'videopress';
$cached_id = wp_cache_get( $cache_key, $cache_group );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick question; did you consider using transients instead of object caching? Would it be better for performance on sites that do not use caching plugins?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, I'll look at that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I could add a transient here if you'd like.

But since the attachment ID is from a database query (WP_Query), I'm not sure that using a transient to store it in the database (wp_options) would be the best approach.

It would probably improve performance for sites without persistent object caching. But it could fill the wp_options table.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kienstra Expiring transients aren't autoloaded and are deleted once they expire.

Do you think we need to worry about polluting wp_options under these circumstances?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kienstra Also, is videopress_get_attachment_id_by_url ever called?

I think the original usage was in videopress_shortcode_override_for_core_shortcode (771097d), but has been superseded by 32dbcd7, but the method itself has never been removed.

I ran git log -p -S videopress_get_attachment_id_by_url to confirm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Use transients, but store only the post ID
  2. We could use the object cache to store the post object, avoiding multiple calls to get_post() if we want.

Thanks, what do you think about the latest commits, which apply those 2 points?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And to wrap things up, I'd get the post ID in a separate method, which would be a direct replacement for the method we are deprecating :) .

Hm, did you have in mind something like:

/**
 * Using a GUID, find a post ID.
 *
 * @param string $guid The guid to use to find the post ID.
 * @return int|false The post ID.
 */
function video_get_post_id_by_guid( $guid ) {
	$post = video_get_post_by_guid( $guid );

	if ( is_object( $post ) && 'WP_Post' === get_class( $post ) ) {
		return $post->ID;
	}

	return false;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, what do you think about the latest commits, which apply those 2 points?

What I thought is that we can use both transients and wp_cache at the same time, each one for a purpose. Transients to store the post ID, so we avoid making the costly SQL SELECT many times though several requests. Object Caching to avoid calling get_post() several times within the same request.

Hm, did you have in mind something like:

Not exactly. I would actually leave the WP_Query call in video_get_post_id_by_guid, adding the 'fields' => 'ids'. I would call it from video_get_post_by_guid and then call get_post. So I would have the same behavior every time. (Always fetch the ID and then call get_post)

Looks a bit cleaner to me. Each method doing just one thing, and avoiding things like $cached_post sometimes holding the actual post, and sometimes holding just the post id.

Also it's important to add an expiration time for the transient.

This is how I see it. (Please consider this just as an opinion!)

function video_get_post_by_guid( $guid ) {
	// ...
	$cached_post = wp_cache_get( $cache_key, $cache_group );

	if ( $cached_post ) {
		return $cached_post;
	}

	$post_id = $this->video_get_post_id_by_guid( $guid );

	if ( is_int( $post_id ) ) {
		$post = get_post( $cached_post );
		wp_cache_set( $cache_key, $post, $cache_group, HOUR_IN_SECONDS );
		if ( $post ) {
			return $post;
		}
	}

}

function video_get_post_id_by_guid( $guid ) {
	// ... 
	$cached_id = get_transient( $cache_key );
	if ( $cached_id ) {
		return $cached_id;
	}

	// do the query
	set_transient( $cache_key, $id, HOUR_IN_SECONDS );
	return $id;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, and sorry for the delay. I'm working on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this look? It mainly uses your snippet above.

@jeherve jeherve added [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Feb 26, 2020
As Jeremy mentioned,
8.3.0 now has a code freeze.
@kienstra kienstra requested a review from dero February 27, 2020 00:07
@kienstra
Copy link
Contributor Author

Hi @dero,
Hope you're doing great.

Could you please review this?

@jeherve jeherve added [Status] Needs Review To request a review from Crew. Label will be renamed soon. and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! labels Feb 27, 2020
Copy link
Collaborator

@dero dero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kienstra Changes look good. I had a question about transients vs. wp_cache_* usage and I also think one of the methods that receives caching is no longer used in the codebase and can be removed.

$file = basename( $url );
$cache_key = 'videopress_get_attachment_id_by_url_' . md5( $url );
$cache_group = 'videopress';
$cached_id = wp_cache_get( $cache_key, $cache_group );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kienstra Expiring transients aren't autoloaded and are deleted once they expire.

Do you think we need to worry about polluting wp_options under these circumstances?

$file = basename( $url );
$cache_key = 'videopress_get_attachment_id_by_url_' . md5( $url );
$cache_group = 'videopress';
$cached_id = wp_cache_get( $cache_key, $cache_group );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kienstra Also, is videopress_get_attachment_id_by_url ever called?

I think the original usage was in videopress_shortcode_override_for_core_shortcode (771097d), but has been superseded by 32dbcd7, but the method itself has never been removed.

I ran git log -p -S videopress_get_attachment_id_by_url to confirm.

As Dero mentioned,
it looks like this isn't used in Jetpack.
As Jeremy mentioned, this should
give third-party developers a chance
to change to something else.
@kraftbj kraftbj added [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Mar 6, 2020
@kraftbj
Copy link
Contributor

kraftbj commented Mar 6, 2020

Marking for author reply pending resolution of the wp_cache_* vs transient question.

@kienstra
Copy link
Contributor Author

kienstra commented Mar 8, 2020

Thanks, I responded above.

Also, store the full WP_Post in the cache,
if it is available.
There is actually an existing function
that does the same thing.
Add video_get_post_id_by_guid(),
and a unit test for it.
To correspond to its position
in utility-functions.php.
Following Leo's snippet,
this should have an expiration.
Copy link
Contributor

@leogermani leogermani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kienstra ,

Thanks a lot for the changes.

There are few small things though:

  • Use the fields => ids param in the query. Since this PR is all about performance, this is a must-have.
  • Add the @since keywork to the new functions. (see https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/php/#1-functions-class-methods)
  • Now we have a perfect replacement for that deprecated function! Add there in the @see keyword there with our new function.
  • I see that this file have functions prefixed both with video and with videopress. Most of them with videopress and, since this is the name of the module, we should stick to it. Those functions that are using only video as prefix we can review another time. But I think we should enforce the most appropriate prefix. So, change the prefix of the new functions to videopress

modules/videopress/utility-functions.php Show resolved Hide resolved
modules/videopress/utility-functions.php Show resolved Hide resolved
The see tag points to a possible replacement.
Also, the DocBlock summary references the wrong function.
Also change the transient cache key.
Also, simply return the post, instead of
accessing the ->ID property.
@kienstra
Copy link
Contributor Author

I see that this file have functions prefixed both with video and with videopress. Most of them with videopress and, since this is the name of the module, we should stick to it. Those functions that are using only video as prefix we can review another time. But I think we should enforce the most appropriate prefix. So, change the prefix of the new functions to videopress

OK, is 64918b1 what you had in mind? It renames video_get_post_id_by_guid to videopress_get_post_id_by_guid()

videopress_get_post_id_by_guid()
now has a @SInCE tag,
in addition to other dataProviders
This applied when it was part of
video_get_post_by_guid(),
but not to the new function it's in.
@kienstra
Copy link
Contributor Author

Hi @leogermani,
Thanks for your review. All 4 of your points are applied.

Copy link
Contributor

@leogermani leogermani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kienstra ,

Thanks for all the work, it looks great now!

I had a quick chat with the team and we thought it was worth to rename one of the old functions to have a bit more consistency. I already did it since it doesn't change anything with the logic you implemented.

@leogermani leogermani added [Status] Needs Review To request a review from Crew. Label will be renamed soon. and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! labels Mar 20, 2020
@kienstra
Copy link
Contributor Author

kienstra commented Mar 20, 2020

Hi @leogermani,

I had a quick chat with the team and we thought it was worth to rename one of the old functions to have a bit more consistency. I already did it since it doesn't change anything with the logic you implemented.

Sounds good, thanks for pushing that change.

@leogermani leogermani merged commit f98f1e1 into master Mar 23, 2020
@leogermani leogermani deleted the add/caching-videopress branch March 23, 2020 18:23
@matticbot matticbot added [Status] Needs Changelog and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Mar 23, 2020
jeherve added a commit that referenced this pull request Mar 31, 2020
jeherve added a commit that referenced this pull request Mar 31, 2020
* Initial changelog entry

* Changelog: add #14904

* Changelog: add #14910

* Changelog: add #14913

* Changelog: add #14916

* Changelog: add #14922

* Changelog: add #14924

* Changelog: add #14925

* Changelog: add #14928

* Changelog: add #14840

* Changelog: add #14841

* Changelog: add #14842

* Changelog: add #14826

* Changelog: add #14835

* Changelog: add #14859

* Changelog: add #14884

* Changelog: add #14888

* Changelog: add #14817

* Changelog: add #14814

* Changelog: add #14819

* Changelog;: add #14797

* Changelog: add #14798

* Changelog: add #14802

* Changelog: add #13676

* Changelog: add #13744

* Changelog: add #13777

* Changelog: add #14446

* Changelog: add #14739

* Changelog: add #14770

* Changelog: add #14784

* Changelog: add #14897

* Changelog: add #14898

* Changelog: add #14968

* Changelog: add #14985

* Changelog: add #15044

* Changelog: add #15052

* Update to remove Podcast since it remains in Beta

* Changelog: add #14803

* Changelog: add #15028

* Changelog: add #15065

* Changelog:add #14886

* Changelog: add #15118

* Changelog: add #14990

* Changelog: add #14528

* Changelog: add #15120

* Changelog: add #15126

* Changelog: add #15049

* Chanegelog: add #14852

* Changelog: add #15090

* Changelog: add #15138

* Changelog: add #15124

* Changelog:add #15055

* Changelog: add #15017

* Changelog: add #15109

* Changelog: add #15145

* Changelog:add #15096

* Changelog:add #15153

* Changelog: add #15133

* Changelog: add #14960

* Changelog: add #15127

* Changelog: add #15056

* Copy current changelog to changelog archive.

* Clarify changelog description
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] VideoPress A feature to help you upload and insert videos on your site. [Focus] Performance [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants