Add in-memory caching to QueryRunner
#475
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a performance and developer experience improvement to remove redundant query executions during a single request. It implements a simple in-memory cache in
QueryRunner
so that repeated identical queries are quickly resolved from cache.Why is in-memory caching beneficial?
Mainly, because block bindings with identical queries are often repeated within a remote data block. For example, this remote data block has 7 children core blocks with block bindings, each of which needs the same data from the exact same query:
Currently, for this example, our block binding resolver function executes the exact same query 7 times. Via our Guzzle client, the redundant query executions resolve from object cache. On top of this, WP Core implements its own in-memory cache for object cache, which means that there is only one network request to object cache.
So why do we need this additional caching? Two main reasons:
JsonPath
in order to extract the values defined by the query's output schema.It has a small side benefit of removing the appearance of multiple calls in our logging and debugging tools:
Why implement in-memory caching here?
The
QueryRunner
implements query execution and response parsing, so it feels like a natural location. We could implement caching at the block binding level, but use cases that executed queries directly (e.g., custom code, REST API, interactivity API) would not benefit.Another option is to inject the post-processing logic into our Guzzle middleware and cache the result, but that could result in breakage when processing code is updated. It's much safer to cache the raw API response.