File: tracer.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (80 lines) | stat: -rw-r--r-- 2,666 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
# frozen_string_literal: true
module GraphQL
  class Backtrace
    # TODO this is not fiber-friendly
    module Tracer
      module_function

      # Implement the {GraphQL::Tracing} API.
      def trace(key, metadata)
        case key
        when "lex", "parse"
          # No context here, don't have a query yet
          nil
        when "execute_multiplex", "analyze_multiplex"
          # No query context yet
          nil
        when "validate", "analyze_query", "execute_query", "execute_query_lazy"
          push_key = []
          if (query = metadata[:query]) || ((queries = metadata[:queries]) && (query = queries.first))
            push_data = query
            multiplex = query.multiplex
          elsif (multiplex = metadata[:multiplex])
            push_data = multiplex.queries.first
          end
        when "execute_field", "execute_field_lazy"
          query = metadata[:query]
          multiplex = query.multiplex
          push_key = query.context[:current_path]
          parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]

          if parent_frame.is_a?(GraphQL::Query)
            parent_frame = parent_frame.context
          end

          push_data = Frame.new(
            query: query,
            path: push_key,
            ast_node: metadata[:ast_node],
            field: metadata[:field],
            object: metadata[:object],
            arguments: metadata[:arguments],
            parent_frame: parent_frame,
          )
        else
          # Custom key, no backtrace data for this
          nil
        end

        if push_data && multiplex
          push_storage = multiplex.context[:graphql_backtrace_contexts] ||= {}
          push_storage[push_key] = push_data
          multiplex.context[:last_graphql_backtrace_context] = push_data
        end

        if key == "execute_multiplex"
          multiplex_context = metadata[:multiplex].context
          begin
            yield
          rescue StandardError => err
            # This is an unhandled error from execution,
            # Re-raise it with a GraphQL trace.
            potential_context = multiplex_context[:last_graphql_backtrace_context]

            if potential_context.is_a?(GraphQL::Query::Context) ||
                potential_context.is_a?(Backtrace::Frame)
              raise TracedError.new(err, potential_context)
            else
              raise
            end
          ensure
            multiplex_context.delete(:graphql_backtrace_contexts)
            multiplex_context.delete(:last_graphql_backtrace_context)
          end
        else
          yield
        end
      end
    end
  end
end