Class: GraphQL::Schema::Timeout
- Inherits:
-
Object
- Object
- GraphQL::Schema::Timeout
- Defined in:
- lib/graphql/schema/timeout.rb
Overview
This plugin will stop resolving new fields after max_seconds
have elapsed.
After the time has passed, any remaining fields will be nil
, with errors added
to the errors
key. Any already-resolved fields will be in the data
key, so
you’ll get a partial response.
You can subclass GraphQL::Schema::Timeout
and override max_seconds
and/or handle_timeout
to provide custom logic when a timeout error occurs.
Note that this will stop a query in between field resolutions, but
it doesn’t interrupt long-running resolve
functions. Be sure to use
timeout options for external connections. For more info, see
www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/
Defined Under Namespace
Classes: TimeoutError
Class Method Summary collapse
Instance Method Summary collapse
-
#handle_timeout(error, query) ⇒ Object
Invoked when a query times out.
-
#initialize(max_seconds:) ⇒ Timeout
constructor
A new instance of Timeout.
-
#max_seconds(query) ⇒ Integer, false
Called at the start of each query.
-
#trace(key, data) ⇒ Object
Constructor Details
#initialize(max_seconds:) ⇒ Timeout
Returns a new instance of Timeout.
42 43 44 |
# File 'lib/graphql/schema/timeout.rb', line 42 def initialize(max_seconds:) @max_seconds = max_seconds end |
Class Method Details
.use(schema, **options) ⇒ Object
[View source]
36 37 38 39 |
# File 'lib/graphql/schema/timeout.rb', line 36 def self.use(schema, **) tracer = new(**) schema.tracer(tracer) end |
Instance Method Details
#handle_timeout(error, query) ⇒ Object
Invoked when a query times out.
105 106 107 |
# File 'lib/graphql/schema/timeout.rb', line 105 def handle_timeout(error, query) # override to do something interesting end |
#max_seconds(query) ⇒ Integer, false
Called at the start of each query.
The default implementation returns the max_seconds:
value from installing this plugin.
98 99 100 |
# File 'lib/graphql/schema/timeout.rb', line 98 def max_seconds(query) @max_seconds end |
#trace(key, data) ⇒ Object
[View source]
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/graphql/schema/timeout.rb', line 46 def trace(key, data) case key when 'execute_multiplex' data.fetch(:multiplex).queries.each do |query| timeout_duration_s = max_seconds(query) timeout_state = if timeout_duration_s == false # if the method returns `false`, don't apply a timeout false else now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) timeout_at = now + (max_seconds(query) * 1000) { timeout_at: timeout_at, timed_out: false } end query.context.namespace(self.class)[:state] = timeout_state end yield when 'execute_field', 'execute_field_lazy' query_context = data[:context] || data[:query].context timeout_state = query_context.namespace(self.class).fetch(:state) # If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query. if timeout_state != false && Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at) error = if data[:context] GraphQL::Schema::Timeout::TimeoutError.new(query_context.parent_type, query_context.field) else field = data.fetch(:field) GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field) end # Only invoke the timeout callback for the first timeout if !timeout_state[:timed_out] timeout_state[:timed_out] = true handle_timeout(error, query_context.query) end error else yield end else yield end end |