graphql-fragment_cache 0.1.4 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5ab2d2bd11b30a0c40476378f1b9ad0c064ccffec7f4595f9d81dbb0ad85eac
4
- data.tar.gz: 44c09dce73b8836f656f186291ed4a45b9cdab6c0ed8844dea38bb9fe9b276bc
3
+ metadata.gz: 760e0c3b18dc1081e3f7a2d1534087e1cc827b790c919ed2e4a9619777bd1ae7
4
+ data.tar.gz: 94a9b27d60ef3dbf0e69d13947fadd247c628da22dacde4e84323e69366e68f1
5
5
  SHA512:
6
- metadata.gz: c225d6650aa383253eda036366f92d9a9ae2109c873cc9f4f69e9b736367c31c9c7b0c59c42ad830f4554184af75016239a0c3a739d2e3f1b4621fcbed9814e1
7
- data.tar.gz: 556d2eced9aef328be63f06de9404e78e958a06f5cba2394c1fda4d449c63d04399730978767a40a7b4544b41418f1bab96384aafddd819cd4c6bbad79b62af0
6
+ metadata.gz: afc55177d8c5b14ad4d1f5f95cf69c8dd499e43408205d4797b3f82068144cb39d63f200799b4e5dba13925055009527ef8515f3108b1dc98854377d1f26d9bf
7
+ data.tar.gz: c9da2cb81cd250f92984c732facf1c6fe62bd45f9161a4e38a28eb5a9e90c167baf74278af80eaf15edb53992df9b00e476f935e421404f5939d3b19cc45101c
@@ -2,6 +2,27 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.0.1 (2020-06-17)
6
+
7
+ - [PR#25](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/25) Support fragments with aliases for CacheKeyBuilder ([@DmitryTsepelev][])
8
+
9
+ ## 1.0.0 (2020-06-13)
10
+
11
+ - [PR#24](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/24) Add nil caching. **BREAKING CHANGE**: custom cache stores must also implement `#exist?(key)` method ([@DmitryTsepelev][])
12
+
13
+ ## 0.1.7 (2020-06-02)
14
+
15
+ - [PR#23](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/23) Avoid extra queries after restoring connection from cache ([@DmitryTsepelev][])
16
+
17
+ ## 0.1.6 (2020-05-30)
18
+
19
+ - [PR#22](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/22) Properly cache entites inside collections ([@DmitryTsepelev][])
20
+
21
+ ## 0.1.5 (2020-04-28)
22
+
23
+ - [PR#19](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/19) Add connections support ([@DmitryTsepelev][])
24
+ - [PR#18](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/18) Support aliases in cache key generation ([@palkan][], [@DmitryTsepelev][])
25
+
5
26
  ## 0.1.4 (2020-04-25)
6
27
 
7
28
  - Fix railtie to set up null store for tests ([@DmitryTsepelev][])
data/README.md CHANGED
@@ -61,6 +61,15 @@ class QueryType < BaseObject
61
61
  end
62
62
  ```
63
63
 
64
+ If you use [connections](https://graphql-ruby.org/pagination/connection_concepts.html) and plan to cache them—please turn on [brand new](https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/pagination/connections.rb#L5) connections hierarchy in your schema:
65
+
66
+ ```ruby
67
+ class GraphqSchema < GraphQL::Schema
68
+ # ...
69
+ use GraphQL::Pagination::Connections
70
+ end
71
+ ```
72
+
64
73
  ## Cache key generation
65
74
 
66
75
  Cache keys consist of implicit and explicit (provided by user) parts.
@@ -243,7 +252,7 @@ Rails.application.configure do |config|
243
252
  end
244
253
  ```
245
254
 
246
- ⚠️ Cache store must implement `#read(key)` and `#write(key, value, **options)` methods.
255
+ ⚠️ Cache store must implement `#read(key)`, `#write(key, value, **options)` and `#exist?(key)` methods.
247
256
 
248
257
  The gem provides only in-memory store out-of-the-box (`GraphQL::FragmentCache::MemoryStore`). It's used by default.
249
258
 
@@ -266,10 +275,6 @@ class QueryType < BaseObject
266
275
  end
267
276
  ```
268
277
 
269
- ## Limitations
270
-
271
- - [Field aliases](https://spec.graphql.org/June2018/#sec-Field-Alias) are not currently supported (take a look at the failing spec [here](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/7))
272
-
273
278
  ## Credits
274
279
 
275
280
  Based on the original [gist](https://gist.github.com/palkan/faad9f6ff1db16fcdb1c071ec50e4190) by [@palkan](https://github.com/palkan) and [@ssnickolay](https://github.com/ssnickolay).
@@ -18,6 +18,77 @@ module GraphQL
18
18
  }.join(".")
19
19
  end
20
20
  end
21
+
22
+ refine ::GraphQL::Language::Nodes::AbstractNode do
23
+ def alias?(_)
24
+ false
25
+ end
26
+ end
27
+
28
+ refine ::GraphQL::Language::Nodes::Field do
29
+ def alias?(val)
30
+ self.alias == val
31
+ end
32
+ end
33
+
34
+ refine ::GraphQL::Execution::Lookahead do
35
+ def selection_with_alias(name, **kwargs)
36
+ return selection(name, **kwargs) if selects?(name, **kwargs)
37
+ alias_selection(name, **kwargs)
38
+ end
39
+
40
+ def alias_selection(name, selected_type: @selected_type, arguments: nil)
41
+ return alias_selections[name] if alias_selections.key?(name)
42
+
43
+ alias_node = lookup_alias_node(ast_nodes, name)
44
+ return ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD unless alias_node
45
+
46
+ next_field_name = alias_node.name
47
+
48
+ # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
49
+ next_field_defn = get_class_based_field(selected_type, next_field_name)
50
+
51
+ alias_selections[name] =
52
+ if next_field_defn
53
+ next_nodes = []
54
+ arguments = @query.arguments_for(alias_node, next_field_defn)
55
+ arguments = arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) ? arguments.keyword_arguments : arguments
56
+ @ast_nodes.each do |ast_node|
57
+ ast_node.selections.each do |selection|
58
+ find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
59
+ end
60
+ end
61
+
62
+ if next_nodes.any?
63
+ ::GraphQL::Execution::Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
64
+ else
65
+ ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
66
+ end
67
+ else
68
+ ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
69
+ end
70
+ end
71
+
72
+ def alias_selections
73
+ return @alias_selections if defined?(@alias_selections)
74
+ @alias_selections ||= {}
75
+ end
76
+
77
+ def lookup_alias_node(nodes, name)
78
+ return if nodes.empty?
79
+
80
+ nodes.find do |node|
81
+ if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
82
+ node = @query.fragments[node.name]
83
+ raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
84
+ end
85
+
86
+ return node if node.alias?(name)
87
+ child = lookup_alias_node(node.children, name)
88
+ return child if child
89
+ end
90
+ end
91
+ end
21
92
  })
22
93
 
23
94
  # Builds cache key for fragment
@@ -59,7 +130,12 @@ module GraphQL
59
130
 
60
131
  def selections_cache_key
61
132
  current_root =
62
- path.reduce(query.lookahead) { |lkhd, name| lkhd.selection(name) }
133
+ path.reduce(query.lookahead) { |lkhd, field_name|
134
+ # Handle cached fields inside collections:
135
+ next lkhd if field_name.is_a?(Integer)
136
+
137
+ lkhd.selection_with_alias(field_name)
138
+ }
63
139
 
64
140
  current_root.selections.to_selections_key
65
141
  end
@@ -68,12 +144,16 @@ module GraphQL
68
144
  lookahead = query.lookahead
69
145
 
70
146
  path.map { |field_name|
71
- lookahead = lookahead.selection(field_name)
147
+ # Handle cached fields inside collections:
148
+ next field_name if field_name.is_a?(Integer)
149
+
150
+ lookahead = lookahead.selection_with_alias(field_name)
151
+ raise "Failed to look ahead the field: #{field_name}" if lookahead.is_a?(::GraphQL::Execution::Lookahead::NullLookahead)
72
152
 
73
- next field_name if lookahead.arguments.empty?
153
+ next lookahead.field.name if lookahead.arguments.empty?
74
154
 
75
155
  args = lookahead.arguments.map { |_1, _2| "#{_1}:#{traverse_argument(_2)}" }.sort.join(",")
76
- "#{field_name}(#{args})"
156
+ "#{lookahead.field.name}(#{args})"
77
157
  }.join("/")
78
158
  end
79
159
 
@@ -1,6 +1,6 @@
1
1
  require "ruby-next"
2
2
 
3
3
  require "ruby-next/language/setup"
4
- RubyNext::Language.setup_gem_load_path
4
+ RubyNext::Language.setup_gem_load_path(transpile: true)
5
5
 
6
6
  require "graphql/fragment_cache"
@@ -4,10 +4,11 @@ require "graphql"
4
4
 
5
5
  require "graphql/fragment_cache/ext/context_fragments"
6
6
  require "graphql/fragment_cache/ext/graphql_cache_key"
7
-
8
- require "graphql/fragment_cache/schema_patch"
9
7
  require "graphql/fragment_cache/object"
10
- require "graphql/fragment_cache/instrumentation"
8
+
9
+ require "graphql/fragment_cache/schema/patch"
10
+ require "graphql/fragment_cache/schema/tracer"
11
+ require "graphql/fragment_cache/schema/instrumentation"
11
12
 
12
13
  require "graphql/fragment_cache/memory_store"
13
14
 
@@ -22,8 +23,9 @@ module GraphQL
22
23
  def use(schema_defn, options = {})
23
24
  verify_interpreter!(schema_defn)
24
25
 
25
- schema_defn.instrument(:query, Instrumentation)
26
- schema_defn.extend(SchemaPatch)
26
+ schema_defn.tracer(Schema::Tracer)
27
+ schema_defn.instrument(:query, Schema::Instrumentation)
28
+ schema_defn.extend(Schema::Patch)
27
29
  end
28
30
 
29
31
  def cache_store=(store)
@@ -18,6 +18,77 @@ module GraphQL
18
18
  }.join(".")
19
19
  end
20
20
  end
21
+
22
+ refine ::GraphQL::Language::Nodes::AbstractNode do
23
+ def alias?(_)
24
+ false
25
+ end
26
+ end
27
+
28
+ refine ::GraphQL::Language::Nodes::Field do
29
+ def alias?(val)
30
+ self.alias == val
31
+ end
32
+ end
33
+
34
+ refine ::GraphQL::Execution::Lookahead do
35
+ def selection_with_alias(name, **kwargs)
36
+ return selection(name, **kwargs) if selects?(name, **kwargs)
37
+ alias_selection(name, **kwargs)
38
+ end
39
+
40
+ def alias_selection(name, selected_type: @selected_type, arguments: nil)
41
+ return alias_selections[name] if alias_selections.key?(name)
42
+
43
+ alias_node = lookup_alias_node(ast_nodes, name)
44
+ return ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD unless alias_node
45
+
46
+ next_field_name = alias_node.name
47
+
48
+ # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
49
+ next_field_defn = get_class_based_field(selected_type, next_field_name)
50
+
51
+ alias_selections[name] =
52
+ if next_field_defn
53
+ next_nodes = []
54
+ arguments = @query.arguments_for(alias_node, next_field_defn)
55
+ arguments = arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) ? arguments.keyword_arguments : arguments
56
+ @ast_nodes.each do |ast_node|
57
+ ast_node.selections.each do |selection|
58
+ find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
59
+ end
60
+ end
61
+
62
+ if next_nodes.any?
63
+ ::GraphQL::Execution::Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
64
+ else
65
+ ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
66
+ end
67
+ else
68
+ ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
69
+ end
70
+ end
71
+
72
+ def alias_selections
73
+ return @alias_selections if defined?(@alias_selections)
74
+ @alias_selections ||= {}
75
+ end
76
+
77
+ def lookup_alias_node(nodes, name)
78
+ return if nodes.empty?
79
+
80
+ nodes.find do |node|
81
+ if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
82
+ node = @query.fragments[node.name]
83
+ raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
84
+ end
85
+
86
+ return node if node.alias?(name)
87
+ child = lookup_alias_node(node.children, name)
88
+ return child if child
89
+ end
90
+ end
91
+ end
21
92
  })
22
93
 
23
94
  # Builds cache key for fragment
@@ -59,7 +130,12 @@ module GraphQL
59
130
 
60
131
  def selections_cache_key
61
132
  current_root =
62
- path.reduce(query.lookahead) { |lkhd, name| lkhd.selection(name) }
133
+ path.reduce(query.lookahead) { |lkhd, field_name|
134
+ # Handle cached fields inside collections:
135
+ next lkhd if field_name.is_a?(Integer)
136
+
137
+ lkhd.selection_with_alias(field_name)
138
+ }
63
139
 
64
140
  current_root.selections.to_selections_key
65
141
  end
@@ -68,12 +144,16 @@ module GraphQL
68
144
  lookahead = query.lookahead
69
145
 
70
146
  path.map { |field_name|
71
- lookahead = lookahead.selection(field_name)
147
+ # Handle cached fields inside collections:
148
+ next field_name if field_name.is_a?(Integer)
149
+
150
+ lookahead = lookahead.selection_with_alias(field_name)
151
+ raise "Failed to look ahead the field: #{field_name}" if lookahead.is_a?(::GraphQL::Execution::Lookahead::NullLookahead)
72
152
 
73
- next field_name if lookahead.arguments.empty?
153
+ next lookahead.field.name if lookahead.arguments.empty?
74
154
 
75
155
  args = lookahead.arguments.map { "#{_1}:#{traverse_argument(_2)}" }.sort.join(",")
76
- "#{field_name}(#{args})"
156
+ "#{lookahead.field.name}(#{args})"
77
157
  }.join("/")
78
158
  end
79
159
 
@@ -10,9 +10,7 @@ module GraphQL
10
10
  def call(query)
11
11
  return unless query.context.fragments?
12
12
 
13
- final_value = query.context.namespace(:interpreter)[:runtime].final_value
14
-
15
- query.context.fragments.each { _1.persist(final_value) }
13
+ query.context.fragments.each(&:persist)
16
14
  end
17
15
  end
18
16
  end
@@ -8,18 +8,26 @@ module GraphQL
8
8
  class Fragment
9
9
  attr_reader :options, :path, :context
10
10
 
11
+ attr_accessor :resolved_value
12
+
11
13
  def initialize(context, **options)
12
14
  @context = context
13
15
  @options = options
14
- @path = context.namespace(:interpreter)[:current_path]
16
+ @path = interpreter_context[:current_path]
15
17
  end
16
18
 
19
+ NIL_IN_CACHE = Object.new
20
+
17
21
  def read
18
- FragmentCache.cache_store.read(cache_key)
22
+ FragmentCache.cache_store.read(cache_key).tap do |cached|
23
+ return NIL_IN_CACHE if cached.nil? && FragmentCache.cache_store.exist?(cache_key)
24
+ end
19
25
  end
20
26
 
21
- def persist(final_value)
22
- value = resolve(final_value)
27
+ def persist
28
+ # Connections are not available from the runtime object, so
29
+ # we rely on Schema::Tracer to save it for us
30
+ value = resolved_value || resolve_from_runtime
23
31
  FragmentCache.cache_store.write(cache_key, value, **options)
24
32
  end
25
33
 
@@ -29,9 +37,17 @@ module GraphQL
29
37
  @cache_key ||= CacheKeyBuilder.call(path: path, query: context.query, **options)
30
38
  end
31
39
 
32
- def resolve(final_value)
40
+ def interpreter_context
41
+ context.namespace(:interpreter)
42
+ end
43
+
44
+ def resolve_from_runtime
33
45
  final_value.dig(*path)
34
46
  end
47
+
48
+ def final_value
49
+ @final_value ||= interpreter_context[:runtime].final_value
50
+ end
35
51
  end
36
52
  end
37
53
  end
@@ -23,6 +23,10 @@ module GraphQL
23
23
  @storage = {}
24
24
  end
25
25
 
26
+ def exist?(key)
27
+ storage.key?(key)
28
+ end
29
+
26
30
  def read(key)
27
31
  key = key.to_s
28
32
  storage[key]&.then do |entry|
@@ -8,21 +8,42 @@ module GraphQL
8
8
 
9
9
  # Adds #cache_fragment method
10
10
  module ObjectHelpers
11
+ extend Forwardable
12
+
11
13
  NO_OBJECT = Object.new
12
14
 
15
+ def_delegator :field, :connection?
16
+
13
17
  def cache_fragment(object_to_cache = NO_OBJECT, **options, &block)
14
18
  raise ArgumentError, "Block or argument must be provided" unless block_given? || object_to_cache != NO_OBJECT
15
19
 
16
20
  options[:object] = object_to_cache if object_to_cache != NO_OBJECT
21
+
17
22
  fragment = Fragment.new(context, options)
18
23
 
19
24
  if (cached = fragment.read)
20
- return raw_value(cached)
25
+ return nil if cached == Fragment::NIL_IN_CACHE
26
+ return restore_cached_value(cached)
27
+ end
28
+
29
+ (block_given? ? block.call : object_to_cache).tap do |resolved_value|
30
+ context.fragments << fragment
21
31
  end
32
+ end
33
+
34
+ private
22
35
 
23
- context.fragments << fragment
36
+ def restore_cached_value(cached)
37
+ # If we return connection object from resolver, Interpreter stops processing it
38
+ connection? ? cached : raw_value(cached)
39
+ end
40
+
41
+ def field
42
+ interpreter_context[:current_field]
43
+ end
24
44
 
25
- block_given? ? block.call : object_to_cache
45
+ def interpreter_context
46
+ @interpreter_context ||= context.namespace(:interpreter)
26
47
  end
27
48
  end
28
49
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/fragment_cache/cacher"
4
+
5
+ module GraphQL
6
+ module FragmentCache
7
+ module Schema
8
+ # Adds hook for saving cached values after query is resolved
9
+ module Instrumentation
10
+ module_function
11
+
12
+ def before_query(query)
13
+ end
14
+
15
+ def after_query(query)
16
+ return unless query.valid?
17
+
18
+ Cacher.call(query)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha1"
4
+
5
+ module GraphQL
6
+ module FragmentCache
7
+ module Schema
8
+ # Patches GraphQL::Schema to support fragment cache
9
+ module Patch
10
+ def schema_cache_key
11
+ @schema_cache_key ||= Digest::SHA1.hexdigest(to_definition)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ # Plugin definition
5
+ module FragmentCache
6
+ module Schema
7
+ class Tracer
8
+ using Ext
9
+
10
+ class << self
11
+ def trace(key, data)
12
+ yield.tap do |resolved_value|
13
+ next unless connection_to_cache?(key, data)
14
+
15
+ # We need to attach connection object to fragment and save it later
16
+ context = data[:query].context
17
+ verify_connections!(context)
18
+ cache_connection(resolved_value, context)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def connection_to_cache?(key, data)
25
+ key == "execute_field" && data[:field].connection?
26
+ end
27
+
28
+ def verify_connections!(context)
29
+ return if context.schema.new_connections?
30
+
31
+ raise StandardError,
32
+ "GraphQL::Pagination::Connections should be enabled for connection caching"
33
+ end
34
+
35
+ def cache_connection(resolved_value, context)
36
+ current_path = context.namespace(:interpreter)[:current_path]
37
+ fragment = context.fragments.find { |fragment| fragment.path == current_path }
38
+ fragment.resolved_value = resolved_value if fragment
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module FragmentCache
5
- VERSION = "0.1.4"
5
+ VERSION = "1.0.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-fragment_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-25 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.10.3
19
+ version: 1.10.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.10.3
26
+ version: 1.10.8
27
27
  - !ruby/object:Gem::Dependency
28
- name: ruby-next-core
28
+ name: ruby-next
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.5.1
33
+ version: 0.7.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.5.1
40
+ version: 0.7.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: combustion
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rake
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -121,7 +149,6 @@ files:
121
149
  - bin/console
122
150
  - bin/setup
123
151
  - lib/.rbnext/2.7/graphql/fragment_cache/cache_key_builder.rb
124
- - lib/.rbnext/2.7/graphql/fragment_cache/cacher.rb
125
152
  - lib/.rbnext/2.7/graphql/fragment_cache/ext/graphql_cache_key.rb
126
153
  - lib/graphql-fragment_cache.rb
127
154
  - lib/graphql/fragment_cache.rb
@@ -131,13 +158,14 @@ files:
131
158
  - lib/graphql/fragment_cache/ext/graphql_cache_key.rb
132
159
  - lib/graphql/fragment_cache/field_extension.rb
133
160
  - lib/graphql/fragment_cache/fragment.rb
134
- - lib/graphql/fragment_cache/instrumentation.rb
135
161
  - lib/graphql/fragment_cache/memory_store.rb
136
162
  - lib/graphql/fragment_cache/object.rb
137
163
  - lib/graphql/fragment_cache/object_helpers.rb
138
164
  - lib/graphql/fragment_cache/rails/cache_key_builder.rb
139
165
  - lib/graphql/fragment_cache/railtie.rb
140
- - lib/graphql/fragment_cache/schema_patch.rb
166
+ - lib/graphql/fragment_cache/schema/instrumentation.rb
167
+ - lib/graphql/fragment_cache/schema/patch.rb
168
+ - lib/graphql/fragment_cache/schema/tracer.rb
141
169
  - lib/graphql/fragment_cache/version.rb
142
170
  homepage: https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache
143
171
  licenses:
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQL
4
- module FragmentCache
5
- using Ext
6
-
7
- # Saves resolved fragment values to cache store
8
- module Cacher
9
- class << self
10
- def call(query)
11
- return unless query.context.fragments?
12
-
13
- final_value = query.context.namespace(:interpreter)[:runtime].final_value
14
-
15
- query.context.fragments.each { |_1| _1.persist(final_value) }
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "graphql/fragment_cache/cacher"
4
-
5
- module GraphQL
6
- module FragmentCache
7
- # Adds hook for saving cached values after query is resolved
8
- module Instrumentation
9
- module_function
10
-
11
- def before_query(query)
12
- end
13
-
14
- def after_query(query)
15
- return unless query.valid?
16
-
17
- Cacher.call(query)
18
- end
19
- end
20
- end
21
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "digest/sha1"
4
-
5
- module GraphQL
6
- module FragmentCache
7
- # Patches GraphQL::Schema to support fragment cache
8
- module SchemaPatch
9
- def schema_cache_key
10
- @schema_cache_key ||= Digest::SHA1.hexdigest(to_definition)
11
- end
12
- end
13
- end
14
- end