When using GraphQL Ruby 2.5.0 with both GraphQL::Tracing::ActiveSupportNotificationsTrace and GraphQL::Dataloader, an intermittent NoMethodError exception occasionally occurs during query execution.
workspace/graphql-ruby/lib/graphql/tracing/notifications_trace.rb:142:in 'GraphQL::Tracing::NotificationsTrace#dataloader_fiber_resume': undefined method 'name' for nil (NoMethodError)
begin_notifications_event(prev_ev.name, prev_ev.payload)
Versions
graphql version: 2.5.0
rails (or other framework): 8.0.2
GraphQL schema and query
require 'bundler/inline'
gemfile do
gem 'graphql', path: "./"
gem 'sqlite3'
gem 'activerecord', require: 'active_record'
end
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Schema.define do
create_table :microposts do |t|
t.string(:content)
t.belongs_to :user
end
create_table :users do |t|
t.string(:name)
end
end
class Micropost < ActiveRecord::Base; end
class User < ActiveRecord::Base
has_many :microposts
end
user = User.create!(name: 'Sample')
user.microposts.create!(content: 'Hello World!')
class MySchema < GraphQL::Schema
class Micropost < GraphQL::Schema::Object
field :content, String
end
class User < GraphQL::Schema::Object
field :name, String
field :microposts, [Micropost]
end
class Query < GraphQL::Schema::Object
field :microposts, [Micropost] do
argument :user_id, ID, loads: User
end
def microposts(user:)
user.microposts
end
end
max_complexity 1000
query(Query)
trace_with(GraphQL::Tracing::ActiveSupportNotificationsTrace)
use(GraphQL::Dataloader)
def self.object_from_id(id, ctx)
ctx.dataloader.with(GraphQL::Dataloader::ActiveRecordSource, ::User).load(id)
end
def self.resolve_type(abs_t, obj, ctx)
User
end
end
query_str = <<~GRAPHQL
query queryOne($userId: ID!) {
microposts(userId: $userId) {
content
}
}
GRAPHQL
query = GraphQL::Query.new(MySchema, query_str, variables: { userId: '1' })
pp query.result.to_h
Actual behavior
Click to view exception backtrace
workspace/graphql-ruby/lib/graphql/tracing/notifications_trace.rb:142:in 'GraphQL::Tracing::NotificationsTrace#dataloader_fiber_resume': undefined method 'name' for nil (NoMethodError)
begin_notifications_event(prev_ev.name, prev_ev.payload)
^^^^^
from workspace/graphql-ruby/lib/graphql/dataloader.rb:138:in 'GraphQL::Dataloader#yield'
from workspace/graphql-ruby/lib/graphql/dataloader/source.rb:96:in 'GraphQL::Dataloader::Source#sync'
from workspace/graphql-ruby/lib/graphql/dataloader/source.rb:57:in 'GraphQL::Dataloader::Source#load'
from workspace/graphql-ruby/lib/graphql/dataloader/active_record_source.rb:15:in 'GraphQL::Dataloader::ActiveRecordSource#load'
from dataloder_sample.rb:60:in 'MySchema.object_from_id'
from workspace/graphql-ruby/lib/graphql/schema/member/has_arguments.rb:335:in 'GraphQL::Schema::Member::HasArguments::ArgumentObjectLoader#object_from_id'
from workspace/graphql-ruby/lib/graphql/schema/member/has_arguments.rb:343:in 'GraphQL::Schema::Member::HasArguments::ArgumentObjectLoader#load_application_object'
from workspace/graphql-ruby/lib/graphql/schema/member/has_arguments.rb:347:in 'GraphQL::Schema::Member::HasArguments::ArgumentObjectLoader#load_and_authorize_application_object'
from workspace/graphql-ruby/lib/graphql/schema/argument.rb:356:in 'GraphQL::Schema::Argument#load_and_authorize_value'
from workspace/graphql-ruby/lib/graphql/schema/argument.rb:292:in 'block in GraphQL::Schema::Argument#coerce_into_values'
from workspace/graphql-ruby/lib/graphql/execution/interpreter/runtime.rb:784:in 'GraphQL::Execution::Interpreter::Runtime#minimal_after_lazy'
from workspace/graphql-ruby/lib/graphql/query.rb:414:in 'GraphQL::Query#after_lazy'
from workspace/graphql-ruby/lib/graphql/schema/argument.rb:282:in 'GraphQL::Schema::Argument#coerce_into_values'
from workspace/graphql-ruby/lib/graphql/schema/member/has_arguments.rb:255:in 'block (3 levels) in GraphQL::Schema::Member::HasArguments#coerce_arguments'
from workspace/graphql-ruby/lib/graphql/dataloader.rb:300:in 'block in GraphQL::Dataloader#spawn_job_fiber'
from workspace/graphql-ruby/lib/graphql/dataloader.rb:255:in 'block in GraphQL::Dataloader#spawn_fiber'
Additional context
This issue is caused by changes introduced in PR #5298. The error can be fixed by modifying the code similar to how it's implemented in lib/graphql/tracing/monitor_trace.rb, by adding a nil check:
def dataloader_fiber_resume(source)
prev_ev = Fiber[PREVIOUS_EV_KEY]
if prev_ev
begin_notifications_event(prev_ev.name, prev_ev.payload)
end
super
end
Since the exact conditions that trigger this error are not clearly understood, it's difficult to write a reliable test case.
I would like your support, if possible.
When using GraphQL Ruby 2.5.0 with both GraphQL::Tracing::ActiveSupportNotificationsTrace and GraphQL::Dataloader, an intermittent NoMethodError exception occasionally occurs during query execution.
Versions
graphqlversion: 2.5.0rails(or other framework): 8.0.2GraphQL schema and query
Actual behavior
Click to view exception backtrace
Additional context
This issue is caused by changes introduced in PR #5298. The error can be fixed by modifying the code similar to how it's implemented in
lib/graphql/tracing/monitor_trace.rb, by adding a nil check:Since the exact conditions that trigger this error are not clearly understood, it's difficult to write a reliable test case.
I would like your support, if possible.