-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[GraphQL] Try to remove objectKeys #21032
base: main
Are you sure you want to change the base?
[GraphQL] Try to remove objectKeys #21032
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
2 Skipped Deployments
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're mostly there, but can just delete some more stuff...
@@ -71,7 +71,6 @@ impl GasInput { | |||
let page = Page::from_params(ctx.data_unchecked(), first, after, last, before)?; | |||
|
|||
let filter = ObjectFilter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need to be replaced with a call to multi-get (hopefully a test failed because of this change 🤞 ?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in e2e tests, will have to double check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fix is not correct as indicated by the E2E tests above -- you are now fetching the latest version of each gas payment object rather than the version specified by the input. As mentioned previously, please use the multi-get API you just introduced.
// If both object IDs and object keys are specified, then we need to query in | ||
// both historical and consistent views, and then union the results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Judging by this comment, this whole first branch should be removed, because it only applies if both object keys and object IDs are provided, which cannot happen any longer.
In fact this whole function becomes:
build_objects_query(
if !filter.has_filters() {
View::Historical
} else {
View::Consistent
},
range,
page,
move |query| filter.apply(query),
move |newer| newer,
)
I was initially confused why we use this "Historical" view if there are no filters. I think I've figured out why, but generally it's pretty confusing, so let me write it out, and then @wlmyng and @emmazzz can correct me:
View::Historical
makes it so that after we find candidate objects that meet our filter criteria, we don't look for newer versions of those objects (which would cause us to discard the candidate).- Previously, when we supported ID filters, key filters and pagination, we had the following semantics:
- If you supply object keys and other filters, you are asking: "Find these versions of these objects, and tell me if they meet this criteria".
- If you supply object IDs and other filters, you are asking: "Find the latest versions of these objects, and then tell me if they meet this criteria".
- If you supply both IDs and Keys, you are really doing two distinct queries.
- This should hopefully make it clear why we don't discard objects that meet our criteria if we supply keys (we were interested in those specific versions to begin with).
- The reason we also do this when we don't supply any filter is because then we know that there can't be any newer objects (because we didn't apply any filter, the first query will just always find the latest objects). Could you add this explanation to the function's doc comment?
TL;DR -- I'm looking forward to separating all multi-get APIs from all query APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really follow as I don't know how the objects query is constructed.
@wlmyng could you verify this logic + let me know what I should update the doc comment to?
e14e86c
to
2ad5d2a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you take another look at the changes to gas payment and filter intersection? They seem incorrect to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: these are no longer related to pagination -- it's probably worth putting them in their own test for multi_get
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved!
@@ -118,20 +118,18 @@ module Test::M1 { | |||
|
|||
//# run-graphql | |||
{ | |||
objects_at_version: address(address: "@{A}") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, this query also imposed an ownership constraint -- was that relevant for the test? It seems like from the results, version 3 didn't used to exist in the output and now it does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what is an ownership constraint
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The outer query on address(...)
means that the inner query only returns objects owned by that address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that these results have changed is concerning -- before, the numbers were all different, and now they are not. Seems related to the changes to how gas payment lookups work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed the code to call Object::query_many
which takes the Vec<ObjectKey>
and checkpoint_viewed_at
, but the result is the same. Something fishy.
@@ -71,7 +71,6 @@ impl GasInput { | |||
let page = Page::from_params(ctx.data_unchecked(), first, after, last, before)?; | |||
|
|||
let filter = ObjectFilter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fix is not correct as indicated by the E2E tests above -- you are now fetching the latest version of each gas payment object rather than the version specified by the input. As mentioned previously, please use the multi-get API you just introduced.
.map(|key| PointLookupKey { | ||
id: key.object_id, | ||
version: key.version.into(), | ||
// Keep track of input keys' indices to ensure same output object order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be done more efficiently -- data
is already a HashMap, so you should be able to construct your desired results by iterating over keys
, creating point lookup keys, and then fetching them from that map.
let keys: Vec<_> = keys
.into_iter()
.map(|key| PointLookupKey {
id: key.object_id,
version: key.version.into(),
})
.collect();
let data = loader.load_many(keys.clone()).await;
Ok(keys.into_iter().map(|k| data.get(&k).cloned()).collect())
Writing this also made me realise that if ordering is relevant, then if we don't find an object key, then we should probably return null
for that (so that other results line up). The snippet above does that, but it needs to be propagated to the actual implementation, schema, docs and tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this but it looks like the gas related numbers in E2E tests stayed the same, which is strange.
.flatten() | ||
.filter_map(|(id, v)| v.is_none().then_some(*id)) | ||
.collect(); | ||
if let (Some(obj_ids), Some(other_obj_ids)) = (&self.object_ids, &other.object_ids) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are missing a couple of cases here:
- If only one of the filters have object ids, then I think we should be preserving those IDs in the intersection. I suspect using the
intersect::field
helper would achieve that. - If the resulting intersection is empty, then we need to return
None
from this function to indicate the fact that we know in advance that the result is inconsistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think I fixed this.
Description
This PR removes the
objectKeys
field fromObjectFilter
as per the previous deprecation notice. UsemultiGetObjects
instead.Test plan
Updated tests accordingly and ensured all existing tests pass.
Release notes
Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.
For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates.
objectKeys
field fromObjectFilter
as per the previous deprecation notice. UsemultiGetObjects
instead to fetch multiple objects.