Automatic query complexity
oprypkhantc opened this issue · comments
Hey.
There was a similar issue here, see last comment: #306 . What's important here is the following: it'd be nice to have graphqlite
automatically compute query complexity using pre-defined settings and an attribute. Some other GraphQL implementations (for other languages) have been doing this for a while and it's pretty neat.
For example, here's a guide from HotChocolate (.NET graphql implementation): https://chillicream.com/docs/hotchocolate/v13/security/operation-complexity
The way they do it is pretty simple: they count every non-object and non-list field as 1
, and every object or list or anything with a custom resolver as 5
, and allow overriding that through an annotation:
type Query {
books(take: Int = 10): [Book] @cost(complexity: 5, multipliers:[take])
}
type Book {
title
author: Author @cost(complexity: 5)
}
type Author {
name
}
Given this example, a query like this:
query {
books {
title
}
}
costs 10
(take
parameter) * (5
(each Book in books
cost) + 1
(title of each Book)) = 10 * (5 + 1) = 60
While a query like that:
query {
books {
title
author {
name
}
}
}
costs 10 * (5 + 1 + 5) = 110.
The implementation consists of a new attribute #[Cost(int $complexity = 1, ?int $defaultMultiplier = null, array $multipliers = [])]
and a ComplexityFieldMiddleware
. Again, thanks to webonyx/graphql-php
supporting query complexity out of the box, it's pretty trivial, yet quite nice.
I've already implemented this in our package and would like to backport this to graphqlite
, if there's any interest in it here.
@oprypkhantc Let's do it!
We'll need some good documentation on security and calculating ideal values. How does a multiplier work, and why would you want multiple multipliers - what benefits are there for that, etc.