Class: ElasticGraph::QueryRegistry::ClientData
- Inherits:
-
Data
- Object
- Data
- ElasticGraph::QueryRegistry::ClientData
- Defined in:
- lib/elastic_graph/query_registry/client_data.rb
Instance Attribute Summary collapse
-
#canonical_query_strings ⇒ Object
readonly
Returns the value of attribute canonical_query_strings.
-
#operation_names ⇒ Object
readonly
Returns the value of attribute operation_names.
-
#queries_by_last_string ⇒ Object
readonly
Returns the value of attribute queries_by_last_string.
-
#queries_by_original_string ⇒ Object
readonly
Returns the value of attribute queries_by_original_string.
-
#schema_element_names ⇒ Object
readonly
Returns the value of attribute schema_element_names.
Class Method Summary collapse
- .canonical_query_string_from(query, schema_element_names:) ⇒ Object
- .from(schema, registered_query_strings) ⇒ Object
Instance Method Summary collapse
- #cached_query_for(query_string) ⇒ Object
- #unregistered_query_error_for(query, client) ⇒ Object
- #with_updated_last_query(query_string, query) ⇒ Object
Instance Attribute Details
#canonical_query_strings ⇒ Object (readonly)
Returns the value of attribute canonical_query_strings
11 12 13 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 11 def canonical_query_strings @canonical_query_strings end |
#operation_names ⇒ Object (readonly)
Returns the value of attribute operation_names
11 12 13 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 11 def operation_names @operation_names end |
#queries_by_last_string ⇒ Object (readonly)
Returns the value of attribute queries_by_last_string
11 12 13 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 11 def queries_by_last_string @queries_by_last_string end |
#queries_by_original_string ⇒ Object (readonly)
Returns the value of attribute queries_by_original_string
11 12 13 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 11 def queries_by_original_string @queries_by_original_string end |
#schema_element_names ⇒ Object (readonly)
Returns the value of attribute schema_element_names
11 12 13 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 11 def schema_element_names @schema_element_names end |
Class Method Details
.canonical_query_string_from(query, schema_element_names:) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 84 def self.canonical_query_string_from(query, schema_element_names:) return "" unless (document = query.document) canonicalized_definitions = document.definitions.map do |definition| if definition.directives.empty? definition else # Ignore the `@egLatencySlo` directive if it is present. We want to allow it to be included (or not) # and potentially have different values from the registered query so that clients don't have to register # a new version of their query just to change the latency SLO value. # # Note: we don't ignore _all_ directives here because other directives might cause significant behavioral # changes that should be enforced by the registry query approval process. directives = definition.directives.reject do |dir| dir.name == schema_element_names.eg_latency_slo end definition.merge(directives: directives) end end document.merge(definitions: canonicalized_definitions).to_query_string end |
.from(schema, registered_query_strings) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 13 def self.from(schema, registered_query_strings) queries_by_original_string = registered_query_strings.to_h do |query_string| [query_string, schema.new_graphql_query(query_string, validate: false)] end canonical_query_strings = queries_by_original_string.values.map do |q| canonical_query_string_from(q, schema_element_names: schema.element_names) end.to_set operation_names = queries_by_original_string.values.flat_map { |q| q.operations.keys }.to_set new( queries_by_original_string: queries_by_original_string, queries_by_last_string: {}, canonical_query_strings: canonical_query_strings, operation_names: operation_names, schema_element_names: schema.element_names ) end |
Instance Method Details
#cached_query_for(query_string) ⇒ Object
33 34 35 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 33 def cached_query_for(query_string) queries_by_original_string[query_string] || queries_by_last_string[query_string] end |
#unregistered_query_error_for(query, client) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 56 def unregistered_query_error_for(query, client) # Note: we use `selected_operation_name` instead of `operation_name` because `operation_name` can return # `nil` for single-operation queries when no explicit operation_name parameter is passed if accessed before # the query AST is parsed, whereas `selected_operation_name` parses the query AST and returns the operation # name from the query document in that case. selected_op_name = query.selected_operation_name.to_s if operation_names.include?(selected_op_name) "Query #{fingerprint_for(query)} differs from the registered form of `#{selected_op_name}` " \ "for client #{client.description}." else "Query #{fingerprint_for(query)} is unregistered; client #{client.description} has no " \ "registered query with a `#{selected_op_name}` operation." end end |
#with_updated_last_query(query_string, query) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/elastic_graph/query_registry/client_data.rb', line 37 def with_updated_last_query(query_string, query) canonical_string = canonical_query_string_from(query) # We normally expect to only see one alternate query form from a client. However, a misbehaving # client could send us a slightly different query string on each request (imagine if the query # had a dynamically generated comment with a timestamp). Here we guard against that case by # pruning out the previous hash entry that resolves to the same registered query, ensuring # we only cache the most recently seen query string. Note that this operation is unfortunately # O(N) instead of O(1) but we expect this operation to happen rarely (and we don't expect many # entries in the `queries_by_last_string` hash). We could maintain a 2nd parallel data structure # allowing an `O(1)` lookup here but I'd rather not introduce that added complexity for marginal # benefit. updated_queries_by_last_string = queries_by_last_string.reject do |_, cached_query| canonical_query_string_from(cached_query) == canonical_string end.merge(query_string => query) with(queries_by_last_string: updated_queries_by_last_string) end |