-
Notifications
You must be signed in to change notification settings - Fork 621
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Make GraphQL schema cacheable #7222
Comments
@mildlygeeky yeah, the schema definition is required for every call, otherwise, it's impossible to validate the incoming query against it. We've tried to cache the resulting schema, but, for now, it's impossible, as GraphQL fields are defined within Closures, to help to resolve circular dependencies. When you try to serialize anything with a Closure in it, PHP throws a hissy fit about it, so there's no way currently to cache generated schema. For Craft 4.0, I hope to add something like https://github.com/opis/closure to help alleviate this, but that's not going to happen for 3.6. |
Aaah - that makes sense around closures being the reason why you can't simply memoize/serialize. Thanks for the explanation, @andris-sevcenko, and hope to see this in a future release. |
@brandonkelly @andris-sevcenko if I could put together a PR for this, might this something that could get into 3.x (3.7)? Really seeing a lot of stress on Craft for sites using heavy use of GQL, and would be happy to look at caching this (thought is it would respect Craft's overall GQL caching, and break the cache for this in the same way). |
@mildlygeeky, I decided to give it a shot and see what I can come up with. So, the problem here was that the Schema on the PHP end is a complex beast. It's not only a GraphQL schema to validate a query against, but it also holds all the knowledge on how to resolve different fields and whatnot. Further, since entries can relate entries, for example, the fields have to be defined as callbacks, otherwise, you end up with infinite loops. Now, to go to an even more fun place, callbacks/closures cannot be serialized, so it's hard to cache without any wizardry. Thankfully, there are excellent libraries out there that can do this for us, and we should assume that it's with decent performance. Maybe not perfect, but probably not too much overhead on top of PHPs serialization goes into wrapping all the closures in classes so they can be serialized. Long story short, I made that happen. Now, let's take a detour. If you're not in the mood for detours and rambles, skip to the end. I don't recall if you were a fan of Game Of Thrones, but we can probably all agree that George RR Martin is a master of plot twists and great stories in general. Did you know he started by writing science fiction stories? I was not aware of this until I went hunting for the science fiction story I recalled that pairs up nicely with this GH issue - it was a story I read a long time ago as part of this book. The story, it turns out, was by George RR Martin, and it was called FTA. If you're not into science fiction, you can read the plot synopsis here. If you are, well, that book has some good stories. Anyway, as you might have guessed, caching is way slower than generating the Schema every time. About 3x slower. I'll look into some more, uhh, "experimental" solutions that might be available on some hosts. |
In particular, maybe preloading can be made to work here, but that requires PHP 7.4, so the Craft 4.0 milestone still remains. |
Brainstormed a little bit with @Wiejeben over Discord about this. Currently, seems like the best (maybe the only) realistic approach here is to leverage Swoole here as a dedicated GraphQL server which holds the Schemas in the memory. Then, using the |
Friends, this is why I will forever "stan" for @andris-sevcenko. You crack me up, man. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
@brandonkelly - So this is interesting - we have a headless site paired with a static site generator, and whenever the site regenerates we are seeing the server spend almost all of its time rebuilding the schema via
Gql::getSchemaDef
- here is some profiling we did on New Relic to see where we were spending so much time - as you can see, a ton of time is being spent in PHP, and actually very little in MySQL:We have our rebuild pretty well-optimized (GQL caching as well as GQL batching, on pages with multiple calls), but digging into the API GQL controller I can see that even with GQL caching, it does quite a bit of work pulling the schema definition on every request. Would it be possible for the schema to be cached once the query has been validated? Seems like there is a lot of time being spent here when it probably doesn't have to.
Originally posted by @mildlygeeky in #6639 (comment)
The text was updated successfully, but these errors were encountered: