-
Notifications
You must be signed in to change notification settings - Fork 11.2k
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] Add a new multiGetObjects
query on Query
.
#20300
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
3 Skipped Deployments
|
let limits = self.reporter.limits; | ||
let mut stack = vec![&value.node]; | ||
while let Some(value) = stack.pop() { | ||
match value { |
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.
Need to handle V::Variable
@@ -2882,7 +2882,7 @@ input ObjectFilter { | |||
""" | |||
Filter for live or potentially historical objects by their ID and version. | |||
""" | |||
objectKeys: [ObjectKey!] | |||
objectKeys: [ObjectKey!] @deprecated(reason: "Use multiGetObjects instead. This field will be removed in a future release.") |
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.
does this need to be updated again since you mentioned async-graphql doesnt work with this directive?
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.
circling back, then we're losing the ability to select objects that match additional criteria among a list of objects (and optional versions)
/// multiGet queries can only pass a number of keys that does not exceed the max page size. | ||
/// This checks for the number of keys and deducts the raw size of the keys from the payload | ||
/// size. | ||
fn check_multiget_arg( |
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.
As multi-get functionality is achieved through connections, we do a pretty simple assumption that we will yield connection_page_size
results, which is the default_page_size
unless an override has been specified by the caller. I wonder if we could do something similar here, assume that a particular multi-get if invoked will yield the maximum allowed number of results?
Then we can do something similar, where in the resolver (such as TransactionBlock::paginate
) we have the actual check for ids.len() > limits.max_multiget -> return Error
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.
How can I tell multi-get functionality is achieved through connections?
This query does not return a page, but returns the number of keys passed in, which cannot be larger than max page size.
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.
Sorry for the confusion, what I meant is that today to do multi-get you go through objects
connection, which assumes that we'll yield default_page_size
results unless this is explicitly overwritten with first
or last
. Wonder if we could simplify by making a similar assumption, if we see multiGet
, then we defer to the default or max limit for that multiGet
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 see. But this function still needs to account for those input object keys and remove them from the query limit. So I am not sure what you're thinking of.
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.
Requesting changes for the query limit checker stuff mainly!
@@ -2880,7 +2880,8 @@ input ObjectFilter { | |||
""" | |||
objectIds: [SuiAddress!] | |||
""" | |||
Filter for live or potentially historical objects by their ID and version. | |||
Filter for live objects by their ID and version. | |||
For historical versions, use multiGetObjects query instead. |
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 do want to deprecate this input, it doesn't make a ton of sense to query live objects by their ID and version. Add a deprecation notice here (it can just be in the doc comment if the @deprecated
support isn't there in async-graphql
) that mentions the following:
- Why this is being deprecated (it doesn't mean what people think it means).
- What to use instead.
- When it's going away (earliest date and major version)
Check out other deprecation notices in the schema for examples:
sui/crates/sui-graphql-rpc/schema.graphql
Lines 4344 to 4359 in a25c0cb
""" | |
Limit to transactions that accepted the given object as an input. NOTE: this input filter | |
has been deprecated in favor of `affectedObject` which offers an easier to under behavior. | |
This filter will be removed with 1.36.0 (2024-10-14), or at least one release after | |
`affectedObject` is introduced, whichever is later. | |
""" | |
inputObject: SuiAddress | |
""" | |
Limit to transactions that output a versioon of this object. NOTE: this input filter has | |
been deprecated in favor of `affectedObject` which offers an easier to understand behavor. | |
This filter will be removed with 1.36.0 (2024-10-14), or at least one release after | |
`affectedObject` is introduced, whichever is later. | |
""" | |
changedObject: SuiAddress |
@@ -3399,6 +3400,10 @@ type Query { | |||
- `author` is the address of the signer of the transaction or personal msg. | |||
""" | |||
verifyZkloginSignature(bytes: Base64!, signature: Base64!, intentScope: ZkLoginIntentScope!, author: SuiAddress!): ZkLoginVerifyResult! | |||
""" |
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: can you move the implementation of this up near the other accessor functions so it shows up in that order in the schema? Let's put multi-gets between the point lookups and the rich paginated queries (so at the moment, between fn transaction_block
and fn coins
.
Self { | ||
max_query_depth: 20, | ||
max_query_nodes: 300, | ||
max_output_nodes: 100_000, | ||
max_query_payload_size: 5_000, | ||
max_db_query_cost: 20_000, | ||
default_page_size: 20, | ||
max_page_size: 50, | ||
max_page_size, | ||
max_multi_get_objects_keys: max_page_size, // keep the same as max_page_size |
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.
- Let's not make this the same as
max_page_size
, the reason we factored it out into its own config is that it can/should be different -- we can start by setting this to 500 or something. - Let's move it next to
max_transaction_ids
below, because that's what it is semantically closest to.
@@ -67,6 +68,9 @@ struct LimitsTraversal<'a> { | |||
input_budget: u32, | |||
output_budget: u32, | |||
depth_seen: u32, | |||
|
|||
// The total number of object keys in multiGetObjects query | |||
num_obj_keys_seen: u32, |
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 haven't seen how this is used, but you probably don't need this.
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 was right, you don't need this).
match &item.node { | ||
Selection::Field(f) => { | ||
let name = &f.node.name.node; | ||
if name.starts_with(MULTI_GET_OBJECTS) { |
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 idea was for support in the query limits checker to be fully generic, so that in future, we could add multi gets without making further changes here (so we wouldn't forget to add them). To achieve that we should look for names that start with "multiGet".
// If the field being traversed is a multiGet query, multiplicity is the number of | ||
// keys seen in the request. |
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.
No, it is the number of keys passed in the parameter to this multi-get query multiplied by the existing multiplicity (similar to how page size works).
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.
Let's write a lot of tests for this:
- For the potential panic introduced by the
expect
. - For how multiplicity should be handled for multi-gets.
If it's not clear what the limit check change is supposed to be doing, let's discuss during pair programming.
@@ -425,6 +529,10 @@ impl<'a> LimitsTraversal<'a> { | |||
.ok_or_else(|| self.output_node_error())? | |||
}; | |||
|
|||
if multiplicity > self.output_budget { |
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 change should not be necessary
@@ -883,6 +884,40 @@ impl Object { | |||
} | |||
} | |||
|
|||
/// Fetch objects by their id and version. If you need to query for live objects, use the |
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: ordering, I think we put the query functions above the paginate functions usually.
if object_keys.len() > cfg.limits.max_multi_get_objects_keys as usize { | ||
return Err(Error::Client(format!( | ||
"Number of keys exceeds max limit of '{}'", | ||
cfg.limits.max_multi_get_objects_keys | ||
)) | ||
.into()); | ||
} |
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 check is being duplicated here and in the query limits check. I think it's fine/good to have it done here -- that mirrors what we do for pages, but let's keep it down to one place where we do the check.
Description
This PR adds a new query for fetching multiple objects by their ids and versions.
Test plan
How did you test the new or updated feature?
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.