-
-
Notifications
You must be signed in to change notification settings - Fork 266
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
Schema types fix #658
Schema types fix #658
Conversation
That rips out the heart of the lazy type loader (see #405 ) and tests are breaking. See also the discussion in #390 (comment) regarding the performance improvements It's quite possible it works in your project (and probably would also in mine), but we wouldn't reap the benefits of lazy loading on larger schemas when not all types are necessary for a given request (think about a schema with 100 types and 100 queries but any given request only requires a fraction of them). |
7434d7e
to
628ce80
Compare
@mfn how about this? Seems to work and the tests pass. |
6a19f7f
to
c975ecb
Compare
Before taking a deeper look I decided to re-test the benchmarks from #390 (comment) and #390 (comment) I can report back that, although the absolute numbers changed, the relative improvement is also still there 👍 For this to work I only applied the diff from this PR manually as this uses an older version and I wasn't keen yet do upgrade this.
I couldn't see any difference between the existing lazyload_types and from this PR 👍 @stevelacey since this PR supposedly fixes something 😏 can you please add a test showing this? A test I expect would not work without this change. Thanks! |
@mfn awesome, good to know. I've updated the tests, they now fail on the previous commit with |
@@ -70,6 +70,9 @@ public function schema($schema = null): Schema | |||
$schemaQuery = $schema['query'] ?? []; | |||
$schemaMutation = $schema['mutation'] ?? []; | |||
$schemaSubscription = $schema['subscription'] ?? []; | |||
$schemaTypes = $schema['types'] ?? []; | |||
|
|||
$this->addTypes($schemaTypes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is interesting.
Every time a query is now run, it adds the schema types to the internal types
list.
Previously this was only done once when constructing the GraphQL instance.
Multiple invocation within the same process of the same query will work correctly, as types
are stored by their name.
Now, if multiple schemas with same named types are used... they will overwrite previous one but probably "just" work. I guess.
It's in fact similar to typesInstances
with the difference that they're cleared before every query, so instances of different schemas are never mixed.
I still have to think about the impact here but if you've any insights here, please share them!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mfn the thing is this whole mechanism seems to rely on php's request lifetime already, and I've not addressed that problem to reach my goal here – really we should do better, but it looks like a significant piece of work to get there I think. The GraphQL::type(...)
helper would need to become schema-aware, and know to look within a separate pool of independently built/cached types depending on the current schema in use.
I figured the tests would exercise this problem and break for this reason, but they didn't, probably because even when >1 queries are executed within the same test, they're happening against the same schema, the same as in a request. Since a request can only be performed against one schema at a time, I figured this solution would probably do for now, but really I'd prefer this scenario was handled better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One concern I had was regarding "always adding" and the memory consumption, i.e.:
this whole mechanism seems to rely on php's request lifetime already
I've stress tested with workers and horizon: single worker, dispatching about a million jobs which just perform GraphQL queries. Whilst a saw the memory going up over time:
- it was very slowly (a few kb every minute)
- it can't vouch that other (unrelated) code might have a leak -> I tested this in a real project
- I never had issues in the past with workers so I can't even say if they naturally grow a bit over time or not, i.e. never did I look closely before.
So for now my feeling is: this seems to work!
Ah, one more thing I noticed: the readme from the beginning did give examples of multiple schemas, i.e. starts off with the So the best practice for defining queries/mutation is in fact per schema. Interestingly, for the types it was never. We're basically promoting global types. That's also emphasized by the default config we publish: there is even a I wonder if this general sentiment should be changed, to focus on the whole "per schema" experience and only use global types for specific cases (something like the Any feeling about this? |
Yeah, I agree, globally defined types shouldn't be the recommendation, in the project I've been working on it's resulted in 8 schema all with types half of them don't use. The most common reason for even having multiple schema is probably to differentiate public and private APIs, which likely have significant differences in their type offerings. In my case, only 1 of these 8 APIs is a public API, and it shouldn't receive the types used exclusively by the private APIs, nor populate the new public schema I'm adding with types that I've deprecated. I am able to move 20 unused input types out of the new schema with this change + move a few obscure types in to the private schema that exclusively use them. Another thing worth noting is that sharing types between schema isn't hard even without a global types pool, encouraging users to define everything per schema and deprecate the feature entirely might be the way to go, it'll probably raise the quality of GraphQL APIs produced with this library – especially when you consider the tools like Graphidocs and GraphQL Playground that build documentation out of these type definitions. |
@crissi in case you're still around 😅 since you're the original author of the improved type loader, do you think you've time for a review? My concern from #658 (comment) isn't addressed yet, but I also found no good solution ATM. The PR isn't yet finished in terms of tests, but I tested it successfully on a private project with per schema-types and also per-schema types mixed with global types etc. and everything worked out. |
I've added some tests for these cases. They did show me that when I was running it against master branch, they broke. But they worked in this branch 🎉 |
Still around:) I can try to test the branch tomorrow with some production code and see if it breaks anything or slows execution down significantly |
@crissi that would be great!
PS: done from my side! |
I ran on my project and my tests run succesfully and It does not seem to affect performance 👍 |
@crissi thanks, same experience here! I'll probably maybe merge and release this later today. |
Almost forgot: @stevelacey thanks for the PR! |
Nice to see this finally merge! @Bradez |
Summary
Specifying additional types per schema is broken, this fixes that and updates the tests to exercise the problem.
Type of change
Checklist
composer fix-style