You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm playing around with the idea of a donut cache execution layer that can be placed "inside" of the wrapping live query execution, i.e. that is executed on each time the live query triggers. We are currently using rather large live queries that end up being quite cpu-intensive on each invalidation, so any way to cut corners would be great. I do appreciate the simplicity of this tool as it is and don't think it should include any such caching mechanism. Rather, I'm playing around with the idea of a separate plugin.
If I have a large live query that tracks maybe 20-30 entities, an invalidation of a single entity in that list ends up being quite costly as the entire query has to execute again. My thinking is, what if I can do a runtime response stitching using two cached sources:
The previous response, cached in its entirety - a la response caching
A list of entities that is tracked by this specific response AND that has been invalidated
Let's say my original (inner) query looks like this:
And the cached result from my original execution looks something like this:
{data: {company: {__typename: "Company",id: "1",owner: {__typename: "Owner",id: "1",/* A bunch of owner-related data */},assets: [{id: "1",/* A bunch of asset data */},/* ... etc .. */]/* A bunch of company-related data */}}}
Let's then say I invalidate Owner:1. Ideally I don't want to have to execute the resolver code for assets again, or any field in the Company fragment.
How could we accomplish this?
My idea is something like the following:
Take the cached execution result, and for every known invalidated entity, collect every set of (operation/fragment) coordinates to that entity
Traverse the selection set of the incoming query, and prune any selections in non-invalidated types that don't lead toward one of those invalidated entities. In this case, for instance, we'd prune assets (and more) from the selectionSet at Query.company. Of course, we'd have to do this step both for fragments and operations.
When hitting upon an invalidated type during traversal, always include all selections for that selection set.
Execute the partial query, and merge the partial query execution result into the cached result
Ok, but what about lists? If I invalidate Asset:1, I will still have to include the entire selectionSet under assets, which could go very deep and imply a lot of redundant database operations.
My idea here is to allow the plugin to know certain simple shortcuts to entities through configuration. Maybe something like this:
Which would mean the following gets added to the query at some point during the steps above:
{
company_assets_0: asset(id: "1") {
# The original selectionSet for "Query.company.assets"...CompanyAsset
}
}
As per the example above, we can add the original data path to the invalidated entity as alias here to easily merge this data into the final execution result.
As an extension of this idea, we could even allow field-level batching:
Potentially this could see usage even outside live query. Although not as efficient as a response cache in some situations, I think it could be a great tool for services where you have a very good and uniform view of any data changes (i.e. a read view, or maybe a monolith).
Thoughts? Would this be something that could interest anyone else?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Thank you @n1ru4l for a great tool!
I'm playing around with the idea of a donut cache execution layer that can be placed "inside" of the wrapping live query execution, i.e. that is executed on each time the live query triggers. We are currently using rather large live queries that end up being quite cpu-intensive on each invalidation, so any way to cut corners would be great. I do appreciate the simplicity of this tool as it is and don't think it should include any such caching mechanism. Rather, I'm playing around with the idea of a separate plugin.
If I have a large live query that tracks maybe 20-30 entities, an invalidation of a single entity in that list ends up being quite costly as the entire query has to execute again. My thinking is, what if I can do a runtime response stitching using two cached sources:
Let's say my original (inner) query looks like this:
And the cached result from my original execution looks something like this:
Let's then say I invalidate
Owner:1
. Ideally I don't want to have to execute the resolver code forassets
again, or any field in theCompany
fragment.How could we accomplish this?
My idea is something like the following:
assets
(and more) from the selectionSet atQuery.company
. Of course, we'd have to do this step both for fragments and operations.Ok, but what about lists? If I invalidate
Asset:1
, I will still have to include the entire selectionSet underassets
, which could go very deep and imply a lot of redundant database operations.My idea here is to allow the plugin to know certain simple shortcuts to entities through configuration. Maybe something like this:
Which would mean the following gets added to the query at some point during the steps above:
As per the example above, we can add the original data path to the invalidated entity as alias here to easily merge this data into the final execution result.
As an extension of this idea, we could even allow field-level batching:
And, to extend further on this, we could simply allow auto-detection of such resolvers through some directive, i.e:
Potentially this could see usage even outside live query. Although not as efficient as a response cache in some situations, I think it could be a great tool for services where you have a very good and uniform view of any data changes (i.e. a read view, or maybe a monolith).
Thoughts? Would this be something that could interest anyone else?
Beta Was this translation helpful? Give feedback.
All reactions