KGraphQL
KGraphQL copied to clipboard
Standardizing resolver inputs?
Graphql-js resolvers have the following syntax: (Source, Args, Context, Info) -> T
Graphql-java resolvers get passed a DataFetchingEnvironment that has all of the above (Source, Args, etc) as properties. So its syntax is: (DataFetchingEnvironment) -> T
Might be a good idea to standardize the syntax to one of the above.
I suggest: fun resolver (fetch: suspend (Source, Args, Context, Info) -> T)
Potential Benefits:
- It allows an unlimited number of arguments.
- It exposes the "Info" of a field/request - such as whether the current operation is a Query or Mutation, and what the field name is. One use case is that you can enable caching when the operation is a Query, and disable it when the operation is a Mutation.
- It allows more complicated resolvers, such as dealing with suspend functions.
- Forward compatibility with the reference implementation.
Hi @Togrias,
Thank you for proposal. Standarization of resolver syntax would be nice, although I'm not sold on all potential benefits.
Ad1. KGraphQL supports up to 6 arguments, I hope that nobody requires more than that in their API, especially considering that argument can be an object. Nonetheless, there is some value in supporting this case.
Ad2. Information whether resolver is query or mutation is available to the person implementing resolver. Programmatic access through Info
object is only syntactic sugar.
Ad3. Thanks to PR by @Bertrand KGraphQL already supports suspending resolvers on 0.3.0-alpha release based on Kotlin 1.3.
Currently resolver signature is introspected and provides infomation for schema compiler about expected arguments. With this solution, schema has full type information and resolvers don't bother with type casting.
Introducing syntax proposed by you we would have to change DSL for query/mutation declaration, do you have any ideas?
Hi @pgutkowski
Thank you for your reply. I've been thinking of the use cases. One possible concern about Ad1 is that the limit of 6 arguments may prove to be insufficient especially if a developer needs to develop to some specification beyond their control. For example, the Relay Specification defines Connections to have at least 4 arguments: First, Last, Before and After. Add in OrderBy and Filter, and we're maxed out. It may not be possible to squish the arguments into an Input Object, because of compliance issues.
Perhaps you may wish to consider supporting a more open-ended field definition system to be used in the alternative?
Regarding Ad2, if a mutation returns some object type, and that object can be accessed, then whether the root is a mutation might be relevant, especially when optimising DataLoaders. For example:
type Book {
#Some fields
name: String!
}
mutation createBook (input: NewBookInput!) {
newBook {
name # Here it may be useful to check whether it's a mutation or a query.
}
}
I admit that these are rare cases that 95% of developers won't encounter. But it may be good for future-proofing purposes.