Skip to content
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] query costing #14463

Merged
merged 9 commits into from
Oct 27, 2023
Merged

[graphql] query costing #14463

merged 9 commits into from
Oct 27, 2023

Conversation

wlmyng
Copy link
Contributor

@wlmyng wlmyng commented Oct 26, 2023

Description

Now that we've split out query building from execution, we can run a cost analysis through db explain, and stop early if it exceeds query cost limits set in config

Test Plan

Manual testing, making sure existing tests pass


If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process.

Type of Change (Check all that apply)

  • protocol change
  • user-visible impact
  • breaking change for a client SDKs
  • breaking change for FNs (FN binary must upgrade)
  • breaking change for validators or node operators (must upgrade binaries)
  • breaking change for on-chain data layout
  • necessitate either a data wipe or data migration

Release notes

@vercel
Copy link

vercel bot commented Oct 26, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sui-typescript-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 27, 2023 0:50am
4 Ignored Deployments
Name Status Preview Comments Updated (UTC)
explorer ⬜️ Ignored (Inspect) Visit Preview Oct 27, 2023 0:50am
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Oct 27, 2023 0:50am
mysten-ui ⬜️ Ignored (Inspect) Visit Preview Oct 27, 2023 0:50am
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Oct 27, 2023 0:50am

@wlmyng wlmyng merged commit 8904957 into main Oct 27, 2023
32 checks passed
@wlmyng wlmyng deleted the graphql-query-costing branch October 27, 2023 02:41
Comment on lines +49 to +50
let re = Regex::new(r"(LIMIT\s+)\$(\d+)")
.map_err(|e| crate::error::Error::Internal(format!("Failed create valid regex: {}", e)))?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • If we need Regexes like this, we should be able to create them once (statically) and then re-use them.
  • Setting the limit to DEFAULT_PAGE_SIZE kind of defeats the point of this check because it means that someone can create a query that requests 1000x the default page size, and we'll think it costs as much as a default page. I'm fine with us incrementally building towards the costing algorithm, but do we have a plan for how to get the query with all the parameters in place? Without that, this form of costing is not going to be effective.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ah thanks, I'm not super familiar with regex but will look into that
  • and yes follow up PR to apply the correct bindings. Although on this note, does it make sense for us to limit to default page size or allow users to provide an arbitrary limit? I assumed the former (altho the code doesn't do the capping today)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But yes the true cost and estimated cost here are a bit off rn due to replacing the placeholder value with these arbitrary values

E: From<diesel::result::Error> + std::error::Error + Send + 'static,
T: Send + 'static,
{
let max_db_query_cost = self.limits.max_db_query_cost;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This limit applies to all queries that are run as part of a single request, but currently it looks like we're judging the cost of each transaction individually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a q I had posed to @oxade , and I think I was convinced by the explanation (unless I misunderstood it) that the node and complexity limiting already cover the whole request, so the query cost limiting is just to make sure that each individual db operation is not overly complex

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, my recollection of past discussions was that this step was also intended to cover the whole request, so that each successive cost check (node + depth, explain, timeout) is successively more rigorous, because otherwise, a bad actor can take advantage of a discrepancy between our least and most expensive node to compute:

If we set a local explain limit (like in this PR), it has to be generous enough to run a sensible query involving our cheaper nodes, but then the bad actor can fill up a query with really expensive nodes to query (like the analytics queries for explorer, or the APY query), and overload the system. If we set a global limit, we don't have that problem.

jonas-lj pushed a commit to jonas-lj/sui that referenced this pull request Nov 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants