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
Lazy resolvers #4919
Comments
Hey, thanks for the detailed write-up. I'm definitely open to exploring options for loading the schema as-needed. Currently, any GraphQL query loads the entire schema, because, as you noticed, I think making a
If we did all that, we'd probably want to keep the old code too, so that in Production, the whole schema could be loaded upfront -- before the first request comes in, to reduce latency, and before any forking, to improve memory sharing in copy-on-write situations. So, it's all possible -- but I think it will be a bit more than accepting procs for |
Thanks for mapping out the process @rmosolgo. I'll try to roughly implement this and let you know if I get stuck. Once we have something working I imagine it will be easier to accept a patch. |
Looks like I'm wrong about this. As soon as the schema is loaded everything is loaded (which also explains my particularly flamegraphs). Proc typed fields just defer loading when you load them in isolation (eg. |
Is your feature request related to a problem? Please describe.
Right now, resolver classes are defined like this:
In Rails applications with lots of resolvers, this can trigger a lot of autoloads, and contribute to loading a lot of files we don't actually need to execute a query in development mode.
Describe the solution you'd like
GraphQL types have solved this problem already by wrapping type defs in procs like this:
I think it would be great if we could have this syntax to delay loading resolvers until actually used:
But it raises an error:
Describe alternatives you've considered
I considered opening an issue for a feature that lazily loads the root
query
ormutation
, but that seems a little more difficult from a public API perspective, and doesn't really solve the problem as granularly as I'd like. It would defer loading all mutation code until the first mutation, and all query code until the first query. Lazy resolvers should theoretically only load the code and types needed to execute a query/mutation while keeping the root types intact.I also thought about creating a schema for queries and a different one for mutations to split loading the root query and mutation. This would work, but it seems like a hack that doesn't really address the root concern in the GraphQL gem.
Additional context
I noticed this problem when profiling my application and seeing that
AppNameSchema.execute(...)
would load both query and mutation roots (and subsequent resolvers). My application's schema is really big and takes ~3 seconds to load the mutation root and ~2 seconds to load the query root, so this feature would really help the time to first query in autoloaded environments.cc @swalkinshaw
The text was updated successfully, but these errors were encountered: