wp-rest-blocks icon indicating copy to clipboard operation
wp-rest-blocks copied to clipboard

Implement caching for `get_blocks`

Open lukasbesch opened this issue 3 years ago • 5 comments

On some posts the response time is quite long.

This pull request implements a caching for the parsing using transients (or site transients for multisite). The cache key contains a md5 hash of the content and the post meta (only on posts). By default the expiration is set to 0, so that the cached data will be used until either post content or post meta changes, or until you clear transients manually.

In my case this decreases the response time from ≈30s on the first call to ≈1.5s on subsequent calls. I will have to check which specific block might cause the performance issue as not all posts take that much time.

Did anyone have a similar experience? I did not dig deeper into it, my guess is that the pQuery parser is kind of slow, or it trips on particular blocks.


This pull request additionally introduces two new filters:

  • rest_api_blocks_output
  • rest_api_handle_block

I use them to add additional data to some third-party blocks which don't provide all necessary data as attributes or to apply other transformations.

lukasbesch avatar Dec 02 '21 00:12 lukasbesch

Thanks for the PR!

I like the idea, but how does cache invalidation happen here?

spacedmonkey avatar Dec 10 '21 12:12 spacedmonkey

The cache key is using a md5 hash of the post content plus a md5 hash of the serialized post meta data. So if the post content or meta changes, the cached data is not used anymore, but it is still in the database.

The expiration is currently set to 0, so that the transient never expires. Probably we should use something like one year, so that the cache is not filled with content that might never reappear. Expired transients are cleared on database upgrades.

One more thing to note: the cache key does not include the post id, so if two posts have exactly the same content (and meta), they use the same cache key. But I guess that is rather unlikely.

lukasbesch avatar Dec 10 '21 12:12 lukasbesch

What about blocks that stored in widgets or templates parts that do not have post ids?

spacedmonkey avatar Dec 11 '21 14:12 spacedmonkey

Good point! If no post_id is supplied (or it is 0), only the content string is hashed. I added some tests for that, but:

In general it is problematic if blocks such as core/latest-posts are cached – the attributes do not change but the rendered property does change. Another example would be a third party block that fetches data from an external API.

As an alternative, we could cache not on content level but on block level (after the default parsing into blocks), with a whitelist of cacheable blocks. That would result in a lot more cache keys though, and might not be significantly faster (will have to measure that).

Also I'd rather like to find the root of the issue that causes the long response time rather than just trying to "cache it away" :)

What do you think?

lukasbesch avatar Dec 11 '21 17:12 lukasbesch

I had a try at caching in my own PR: https://github.com/spacedmonkey/wp-rest-blocks/pull/29

spacedmonkey avatar Dec 13 '21 20:12 spacedmonkey