Skip to content

Commit

Permalink
Try using Fiber::[] for runtime state
Browse files Browse the repository at this point in the history
  • Loading branch information
rmosolgo committed Jul 20, 2024
1 parent ed566c5 commit d697575
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 26 deletions.
4 changes: 2 additions & 2 deletions lib/graphql/current.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
module GraphQL
module Current
def self.operation_name
Thread.current[:__graphql_runtime_info]&.keys&.first&.selected_operation_name
Fiber[:__graphql_runtime_info]&.keys&.first&.selected_operation_name
end

def self.field_path
Thread.current[:__graphql_runtime_info]&.values&.first&.current_field&.path
Fiber[:__graphql_runtime_info]&.values&.first&.current_field&.path
end

def self.dataloader_source_class
Expand Down
6 changes: 3 additions & 3 deletions lib/graphql/execution/interpreter/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ def directives_include?(node, graphql_object, parent_type)
end

def get_current_runtime_state
current_state = Thread.current[:__graphql_runtime_info] ||= begin
current_state = Fiber[:__graphql_runtime_info] ||= begin
per_query_state = {}
per_query_state.compare_by_identity
per_query_state
Expand Down Expand Up @@ -817,11 +817,11 @@ def arguments(graphql_object, arg_owner, ast_node)
end

def delete_all_interpreter_context
per_query_state = Thread.current[:__graphql_runtime_info]
per_query_state = Fiber[:__graphql_runtime_info]
if per_query_state
per_query_state.delete(@query)
if per_query_state.size == 0
Thread.current[:__graphql_runtime_info] = nil
Fiber[:__graphql_runtime_info] = nil
end
end
nil
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/pagination/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def cursor_for(item)

def detect_was_authorized_by_scope_items
if @context &&
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
(query_runtime_state = current_runtime_state[@context.query])
query_runtime_state.was_authorized_by_scope_items
else
Expand Down
8 changes: 4 additions & 4 deletions lib/graphql/query/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def [](key)
if key == :current_path
current_path
else
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
(query_runtime_state = current_runtime_state[@query]) &&
(query_runtime_state.public_send(key))
end
Expand Down Expand Up @@ -142,7 +142,7 @@ def execution_errors
end

def current_path
current_runtime_state = Thread.current[:__graphql_runtime_info]
current_runtime_state = Fiber[:__graphql_runtime_info]
query_runtime_state = current_runtime_state && current_runtime_state[@query]

path = query_runtime_state &&
Expand All @@ -167,7 +167,7 @@ def delete(key)

def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
if RUNTIME_METADATA_KEYS.include?(key)
(runtime = Thread.current[:__graphql_runtime_info]) &&
(runtime = Fiber[:__graphql_runtime_info]) &&
(query_runtime_state = runtime[@query]) &&
(query_runtime_state.public_send(key))
elsif @scoped_context.key?(key)
Expand All @@ -185,7 +185,7 @@ def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)

def dig(key, *other_keys)
if RUNTIME_METADATA_KEYS.include?(key)
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
(query_runtime_state = current_runtime_state[@query]) &&
(obj = query_runtime_state.public_send(key)) &&
if other_keys.empty?
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/schema/field/scope_extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def after_resolve(object:, arguments:, context:, value:, memo:)
if ret_type.respond_to?(:scope_items)
scoped_items = ret_type.scope_items(value, context)
if !scoped_items.equal?(value) && !ret_type.reauthorize_scoped_objects
if (current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
if (current_runtime_state = Fiber[:__graphql_runtime_info]) &&
(query_runtime_state = current_runtime_state[context.query])
query_runtime_state.was_authorized_by_scope_items = true
end
Expand Down
4 changes: 2 additions & 2 deletions lib/graphql/types/relay/connection_behaviors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def add_page_info_field(obj_type)
def edges
# Assume that whatever authorization needed to happen
# already happened at the connection level.
current_runtime_state = Thread.current[:__graphql_runtime_info]
current_runtime_state = Fiber[:__graphql_runtime_info]
query_runtime_state = current_runtime_state[context.query]
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
@object.edges
Expand All @@ -205,7 +205,7 @@ def edges
def nodes
# Assume that whatever authorization needed to happen
# already happened at the connection level.
current_runtime_state = Thread.current[:__graphql_runtime_info]
current_runtime_state = Fiber[:__graphql_runtime_info]
query_runtime_state = current_runtime_state[context.query]
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
@object.nodes
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/types/relay/edge_behaviors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def self.included(child_class)
end

def node
current_runtime_state = Thread.current[:__graphql_runtime_info]
current_runtime_state = Fiber[:__graphql_runtime_info]
query_runtime_state = current_runtime_state[context.query]
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
@object.node
Expand Down
10 changes: 5 additions & 5 deletions spec/graphql/execution/interpreter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def self.trace(event, data)
module EnsureThreadCleanedUp
def execute_multiplex(multiplex:)
res = super
runtime_info = Thread.current[:__graphql_runtime_info]
runtime_info = Fiber[:__graphql_runtime_info]
if !runtime_info.nil? && runtime_info != {}
if !multiplex.context[:allow_pending_thread_state]
# `nestedQuery` can allow this
Expand Down Expand Up @@ -369,15 +369,15 @@ def execute_multiplex(multiplex:)
{"__typename" => "Expansion", "sym" => "RAV"},
]
assert_equal expected_abstract_list, result["data"]["find"]
assert_nil Thread.current[:__graphql_runtime_info]
assert_nil Fiber[:__graphql_runtime_info]
end

it "runs a nested query and maintains proper state" do
query_str = "query($queryStr: String!) { nestedQuery(query: $queryStr) { result currentPath } }"
result = InterpreterTest::Schema.execute(query_str, variables: { queryStr: "{ __typename }" })
assert_equal '{"data":{"__typename":"Query"}}', result["data"]["nestedQuery"]["result"]
assert_equal ["nestedQuery"], result["data"]["nestedQuery"]["currentPath"]
assert_nil Thread.current[:__graphql_runtime_info]
assert_nil Fiber[:__graphql_runtime_info]
end

it "runs mutation roots atomically and sequentially" do
Expand Down Expand Up @@ -428,7 +428,7 @@ def execute_multiplex(multiplex:)
"exp5" => {"name" => "Ravnica, City of Guilds"},
}
assert_equal expected_data, result["data"]
assert_nil Thread.current[:__graphql_runtime_info]
assert_nil Fiber[:__graphql_runtime_info]
end

describe "temporary interpreter flag" do
Expand Down Expand Up @@ -477,7 +477,7 @@ def execute_multiplex(multiplex:)
# propagated to here
assert_nil res["data"].fetch("expansion")
assert_equal ["Cannot return null for non-nullable field Expansion.name"], res["errors"].map { |e| e["message"] }
assert_nil Thread.current[:__graphql_runtime_info]
assert_nil Fiber[:__graphql_runtime_info]
end

it "places errors ahead of data in the response" do
Expand Down
4 changes: 2 additions & 2 deletions spec/graphql/pagination/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
conn.context = context
assert_nil conn.was_authorized_by_scope_items?

Thread.current[:__graphql_runtime_info] = { context.query => OpenStruct.new(was_authorized_by_scope_items: true) }
Fiber[:__graphql_runtime_info] = { context.query => OpenStruct.new(was_authorized_by_scope_items: true) }
conn.context = context
assert_equal true, conn.was_authorized_by_scope_items?
ensure
Thread.current[:__graphql_runtime_info] = nil
Fiber[:__graphql_runtime_info] = nil
end
end
end
10 changes: 5 additions & 5 deletions spec/graphql/query/context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
after do
# Clean up test fixtures so they don't pollute later tests
# (Usually this is cleaned up by execution code, but many tests here don't actually execute queries)
Thread.current[:__graphql_runtime_info] = nil
Fiber[:__graphql_runtime_info] = nil
end

class ContextTestSchema < GraphQL::Schema
Expand Down Expand Up @@ -100,7 +100,7 @@ def push_query_error

it "allows you to read values of contexts using dig" do
assert_equal(1, context.dig(:a, :b))
Thread.current[:__graphql_runtime_info] = { context.query => OpenStruct.new(current_arguments: {c: 1}) }
Fiber[:__graphql_runtime_info] = { context.query => OpenStruct.new(current_arguments: {c: 1}) }
assert_equal 1, context.dig(:current_arguments, :c)
assert_equal({c: 1}, context.dig(:current_arguments))
end
Expand All @@ -118,7 +118,7 @@ def push_query_error

it "can override values set by runtime" do
context = GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: {a: {b: 1}})
Thread.current[:__graphql_runtime_info] = { context.query => OpenStruct.new({ current_object: :runtime_value }) }
Fiber[:__graphql_runtime_info] = { context.query => OpenStruct.new({ current_object: :runtime_value }) }
assert_equal :runtime_value, context[:current_object]
context[:current_object] = :override_value
assert_equal :override_value, context[:current_object]
Expand Down Expand Up @@ -391,7 +391,7 @@ class ContextSchema < GraphQL::Schema
it "always retrieves a scoped context value if set" do
context = GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil)
dummy_runtime = OpenStruct.new(current_result: nil)
Thread.current[:__graphql_runtime_info] = { context.query => dummy_runtime }
Fiber[:__graphql_runtime_info] = { context.query => dummy_runtime }
dummy_runtime.current_result = OpenStruct.new(path: ["somewhere"])
expected_key = :a
expected_value = :test
Expand Down Expand Up @@ -453,7 +453,7 @@ class ContextSchema < GraphQL::Schema
it "has a #current_path method" do
context = GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil)
current_result = OpenStruct.new(path: ["somewhere", "child", "grandchild"])
Thread.current[:__graphql_runtime_info] = { context.query => OpenStruct.new(current_result: current_result) }
Fiber[:__graphql_runtime_info] = { context.query => OpenStruct.new(current_result: current_result) }
assert_equal ["somewhere", "child", "grandchild"], context.scoped_context.current_path
end
end
Expand Down

0 comments on commit d697575

Please sign in to comment.