Closed sealabcore closed 2 weeks ago
Hey, I'm so sorry for the trouble! Thanks for such a detailed report.
App should not raise on every graphql request.
I'm going to go ahead and agree with you on that expectation 😅
My first hunch is that it's a multi-threading issue in loading schema files. Does this error ever occur in development? (I'm guessing not...)
The system is supposed to make sure all files are loaded at boot time in Production: https://github.com/rmosolgo/graphql-ruby/blob/700fc49e39e8a8d8e75c18ebfda129853d34c263/lib/graphql/schema/visibility.rb#L14
But I see that ensure_loaded
is being called at runtime in the stack trace of the FrozenError
. That means that ensure_loaded
wasn't already called -- or at least that the call hadn't already finished. (I think what would happen with a bunch of threads calling it at once, it could start running on all those different threads, then they'd clash when loading field extensions like this, since they'd be adding the extension more than once.)
One possibility is to put a real lock on this code so that it only runs once.
Another issue is that I guess it only actually preloads if there are any named preloads:
(If profiles
is empty, .each
will iterate zero times 😖 .)
I'm going to take a look at both of these things and I'll follow up back here.
Hey, I'm so sorry for the trouble! Thanks for such a detailed report.
App should not raise on every graphql request.
I'm going to go ahead and agree with you on that expectation 😅
My first hunch is that it's a multi-threading issue in loading schema files. Does this error ever occur in development? (I'm guessing not...)
We have not seen this issue in development environments, and out of about 10 deploys to our production environment, only two deploys showed the Frozen error, and one showed the two visible definitions error on every request.
The system is supposed to make sure all files are loaded at boot time in Production:
But I see that
ensure_loaded
is being called at runtime in the stack trace of theFrozenError
. That means thatensure_loaded
wasn't already called -- or at least that the call hadn't already finished. (I think what would happen with a bunch of threads calling it at once, it could start running on all those different threads, then they'd clash when loading field extensions like this, since they'd be adding the extension more than once.)
We do run 12 threads with 2 workers via Puma in our production environment so it's possible the higher number of threads the more chance that this occurs. As we did not see this in our staging environment that only runs 2 threads on 1 worker.
One possibility is to put a real lock on this code so that it only runs once.
Another issue is that I guess it only actually preloads if there are any named preloads:
(If
profiles
is empty,.each
will iterate zero times 😖 .)I'm going to take a look at both of these things and I'll follow up back here.
Thank for looking into this! We've downgraded to 2.3.19 for now.
Thanks again for the detailed report. I just improved the preloading behavior and released it in 2.4.2. If you get a chance to try that new version, please let me know how it goes for you!
Thank you! I'll test this in our staging environment with more threads and a lot of test deploys before going back to production and get back to you on if I see either error again.
Thanks for the quick turnaround! 🎉
Describe the bug
We are seeing intermittent issues in the latest version of the graphql gem. Our app was raising on this error
This was raising on every graphql request, even ones that didn't even have
Query.eventSchedules.userIds
in the query. So it seems like some weird caching issue in the new visiblity code.We also get this error with the latest graphql code, but it's only once or twice a day right after deploy
These actually seem related, we got the FrozenError first when we deployed, and then started seeing the first error on every request after that.
Versions
graphql
version: 2.4.1rails
(or other framework): Rails 7.2.2 other applicable versions (graphql-batch
, etc)Steps to reproduce
This would happen intermittently when deploying our app with the latest graphql gem.
Expected behavior
App should not raise on every graphql request.
Actual behavior
What specifically went wrong?
Place full backtrace here (if a Ruby exception is involved):
Click to view first frozen exception backtrace
``` vendor/bundle/ruby/3.3.0/gems/graphql-2.4.1/lib/graphql/schema/field_extension.rb:111:in `after_define_apply': can't modify frozen GraphQL::Schema::Field::ScopeExtension: #Click to view second exception backtrace that crashed every following request
``` vendor/bundle/ruby/3.3.0/gems/graphql-2.4.1/lib/graphql/schema/visibility/profile.rb:373:in `raise_duplicate_definition': Found two visible definitions for `Query.eventSchedules.userIds`: #Additional context
Add any other context about the problem here.
With these details, we can efficiently hunt down the bug!