Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

QueryComplexity analyzer may have IO side-effect

Đang mở
#5,261 3 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
42/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
ruby
Lĩnh vực
api, backend

Hướng nghiên cứu

Start with lib/graphql/schema/field.rb around the connection complexity calculation and the GraphQL::Analysis::QueryComplexity entry point. Run the reproduction script with ActiveRecord logging enabled, then trace how argument_cache is accessed during analysis. Done means complexity analysis reads needed arguments statically without triggering the loads: lookup or another database call.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Describe the bug

Discussed in https://github.com/rmosolgo/graphql-ruby/pull/4800#issuecomment-2684939962

The GraphQL::Analysis::QueryComplexity may have IO side-effects (eg making a DB query via active record), while it would be expected to be fully static (as mentioned in the doc "None of GraphQL-Ruby’s validators make IO calls").
This happens because the field complexity calculation for connections (in https://github.com/rmosolgo/graphql-ruby/blob/v2.4.10/lib/graphql/schema/field.rb#L504) calls the argument_cache to read the arguments (to read static arguments like :first), which fully resolves the arguments. This is a problem for example when an argument uses loads: to get an ActiveRecord object from id. This makes using the validate_timeout feature for analysis unsafe.

Versions

graphql version: 2.4.10

Script to reproduce

(took inspiration from the script in https://github.com/rmosolgo/graphql-ruby/issues/5036#issuecomment-2298473769)

require 'bundler/inline'

gemfile do
  gem 'graphql'
  gem 'sqlite3'
  gem 'activerecord', require: 'active_record'
end

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Schema.define do
  create_table :mentions do |t|
    t.string(:content)
    t.belongs_to :ticket
  end
  create_table :tickets do |t|
    t.string(:subject)
  end
end

class Mention < ActiveRecord::Base; end

class Ticket < ActiveRecord::Base
  has_many :mentions
end

ticket = Ticket.create!(subject: "Ticket 1")

Mention.create!(content: "Mention 1", ticket_id: ticket.id)

class MySchema < GraphQL::Schema

  class Mention < GraphQL::Schema::Object
    field :content, String
  end

  class Ticket < GraphQL::Schema::Object
    field :subject, String
    field :mentions, Mention.connection_type

    def mentions(obj)
      obj.mentions
    end
  end

  class Query < GraphQL::Schema::Object
    field :mentions, Mention.connection_type do
      argument :ticket_id, ID, loads: Ticket
    end

    def mentions(ticket:)
      ticket.mentions
    end
  end

  default_page_size 50
  max_complexity 1000
  query(Query)

  def self.object_from_id(id, ctx)
    ::Ticket.find(id)
  end

  def self.resolve_type(abs_t, obj, ctx)
    Ticket
  end
end

query_str = <<~GRAPHQL
  query queryOne($ticketId: ID!, $first: Int!) {
    mentions(ticketId: $ticketId, first: $first) {
      nodes { content }
    }
  }
GRAPHQL

ActiveRecord::Base.logger = Logger.new(STDOUT) # Logs ActiveRecord SQL queries

query = GraphQL::Query.new(MySchema, query_str, variables: { ticketId: '1', first: 10 })

pp GraphQL::Analysis.analyze_query(query, [GraphQL::Analysis::QueryComplexity])
# D, [2025-02-28T16:55:50.009374 #66030] DEBUG -- :   Ticket Load (0.2ms)  SELECT "tickets".* FROM "tickets" WHERE "tickets"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
# [12]
pp query.arguments_cache.instance_variable_get(:@storage).values[0].values[0].values[0]
# #<GraphQL::Execution::Interpreter::Arguments @keyword_arguments={:first=>10, :ticket=>#<Ticket id: 1, subject: "Ticket 1">}>

Expected behavior

No DB call should be made, analyzer should be fully static. Arguments that are needed for the complexity calculation should be read statically.

Actual behavior

We can see a DB call made through ActiveRecord

D, [2025-02-28T16:55:50.009374 #66030] DEBUG -- :   Ticket Load (0.2ms)  SELECT "tickets".* FROM "tickets" WHERE "tickets"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]

And can see the argument resolved in the arguments_cache

 #<GraphQL::Execution::Interpreter::Arguments @keyword_arguments={:first=>10, :ticket=>#<Ticket id: 1, subject: "Ticket 1">}>
Ngôn ngữ chính
Ruby
Star
5.4k
Fork
1.4k
Merge trung bình
1 ngày 8 giờ
Pull request đã merge (30 ngày)
74

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của rmosolgo/graphql-ruby

Tất cả issue của rmosolgo/graphql-ruby

Issue tương tự

Thêm issue về Ruby

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.