graphql-fragment_cache 1.9.1 → 1.12.0

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: 120cfa12166d6db93a1aa709916694555f102d9c8ebeca53ccaba76182360c27
4
- data.tar.gz: ae01a7172430cbe6993ec0c8fabaa7024ab5786000869df42c95bd544f1e73f3
3
+ metadata.gz: fb58b8735fa1b7a92dae359467252e366bf34da888f46ef98db0737db7b6dfc4
4
+ data.tar.gz: 037dd3a8c61ed1f359b50d6ae0e4ae7f169d825fb5c6da8cf0ee8968c6e1b9b4
5
5
  SHA512:
6
- metadata.gz: 39ecafa948ec5b2a5c4954520e3d68709dafcaae53a4f12b5748ecedd7576f40e0e73705f7abdcb5e39f66e3e07506493547a3ed19a2e6d3f19246e53a6d5f23
7
- data.tar.gz: 9bb830762f4c155d70b068409fa8b1ddd49b34ebab0b4ce156d2e00a05127b1abd229dec4a61b029b6a60557254b6e0c650c7bc34b82bd713512acd6fcae4a63
6
+ metadata.gz: 6eef1102518837f505b077f515b7a6e38a6e37993f072921193e30a2a877aec2e67899e8d256b23738cabda2bddf7a8e99967743c14b504afcedd389e2d23734
7
+ data.tar.gz: cb110783f67fb0674065fae17ff860e6c2a81a2fde04f5800634c689f2a1bcf01a54d5183e0ffbf5359d709a9b5493d967be39809abccf91fb5701b00eac7f7f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.11.0 (2022-02-26)
6
+
7
+ - [PR#70](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/70), [PR#82](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/82) Add #read_multi for fragments ([@daukadolt][], [@frostmark][])
8
+ - [PR#79](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/79) Support graphql-ruby 2.0.0 ([@DmitryTsepelev][])
9
+
10
+ ## 1.10.0 (2022-01-30)
11
+
12
+ - [PR#77](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/77) Drop Ruby 2.5 support, add Ruby 3.0 ([@DmitryTsepelev][])
13
+
5
14
  ## 1.9.1 (2021-11-28)
6
15
 
7
16
  - [PR#76](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/76) Freeze parser version ([@DmitryTsepelev][])
@@ -120,3 +129,5 @@
120
129
  [@bbugh]: https://github.com/bbugh
121
130
  [@jeromedalbert]: https://github.com/jeromedalbert
122
131
  [@mretzak]: https://github.com/mretzak
132
+ [@daukadolt]: https://github.com/daukadolt
133
+ [@frostmark]: https://github.com/frostmark
data/README.md CHANGED
@@ -17,13 +17,10 @@ end
17
17
 
18
18
  ## Getting started
19
19
 
20
- Add the gem to your Gemfile `gem 'graphql-fragment_cache'` and add the plugin to your schema class (make sure to turn interpreter mode on with AST analysis!):
20
+ Add the gem to your Gemfile `gem 'graphql-fragment_cache'` and add the plugin to your schema class:
21
21
 
22
22
  ```ruby
23
23
  class GraphqSchema < GraphQL::Schema
24
- use GraphQL::Execution::Interpreter
25
- use GraphQL::Analysis::AST
26
-
27
24
  use GraphQL::FragmentCache
28
25
 
29
26
  query QueryType
@@ -69,15 +66,6 @@ class QueryType < BaseObject
69
66
  end
70
67
  ```
71
68
 
72
- 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:
73
-
74
- ```ruby
75
- class GraphqSchema < GraphQL::Schema
76
- # ...
77
- use GraphQL::Pagination::Connections
78
- end
79
- ```
80
-
81
69
  ## Cache key generation
82
70
 
83
71
  Cache keys consist of the following parts: namespace, implicit key, and explicit key.
@@ -62,7 +62,12 @@ module GraphQL
62
62
  next_field_name = alias_node.name
63
63
 
64
64
  # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
65
- next_field_defn = get_class_based_field(selected_type, next_field_name)
65
+ next_field_defn =
66
+ if GraphQL::FragmentCache.graphql_ruby_before_2_0?
67
+ get_class_based_field(selected_type, next_field_name)
68
+ else
69
+ @query.get_field(selected_type, next_field_name)
70
+ end
66
71
 
67
72
  alias_selections[name] =
68
73
  if next_field_defn
@@ -62,7 +62,12 @@ module GraphQL
62
62
  next_field_name = alias_node.name
63
63
 
64
64
  # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
65
- next_field_defn = get_class_based_field(selected_type, next_field_name)
65
+ next_field_defn =
66
+ if GraphQL::FragmentCache.graphql_ruby_before_2_0?
67
+ get_class_based_field(selected_type, next_field_name)
68
+ else
69
+ @query.get_field(selected_type, next_field_name)
70
+ end
66
71
 
67
72
  alias_selections[name] =
68
73
  if next_field_defn
@@ -62,7 +62,12 @@ module GraphQL
62
62
  next_field_name = alias_node.name
63
63
 
64
64
  # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
65
- next_field_defn = get_class_based_field(selected_type, next_field_name)
65
+ next_field_defn =
66
+ if GraphQL::FragmentCache.graphql_ruby_before_2_0?
67
+ get_class_based_field(selected_type, next_field_name)
68
+ else
69
+ @query.get_field(selected_type, next_field_name)
70
+ end
66
71
 
67
72
  alias_selections[name] =
68
73
  if next_field_defn
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/fragment_cache/schema/lazy_cache_resolver"
4
+
3
5
  module GraphQL
4
6
  module FragmentCache
5
7
  # Wraps resolver with cache method
@@ -8,19 +8,41 @@ module GraphQL
8
8
 
9
9
  # Represents a single fragment to cache
10
10
  class Fragment
11
+ NIL_IN_CACHE = Object.new
12
+
13
+ class << self
14
+ def read_multi(fragments)
15
+ unless FragmentCache.cache_store.respond_to?(:read_multi)
16
+ return fragments.map { |f| [f, f.read] }.to_h
17
+ end
18
+
19
+ fragments_to_cache_keys = fragments
20
+ .map { |f| [f, f.cache_key] }.to_h
21
+
22
+ cache_keys = fragments_to_cache_keys.values
23
+
24
+ cache_keys_to_values = FragmentCache.cache_store.read_multi(*cache_keys)
25
+
26
+ fetched_fragments_to_values = cache_keys_to_values
27
+ .map { |key, val| [fragments_to_cache_keys.key(key), val] }
28
+ .to_h
29
+
30
+ fetched_fragments_to_values
31
+ end
32
+ end
33
+
11
34
  attr_reader :options, :path, :context
12
35
 
13
36
  def initialize(context, **options)
14
37
  @context = context
38
+ @keep_in_context = options.delete(:keep_in_context)
15
39
  @options = options
16
40
  @path = interpreter_context[:current_path]
17
41
  end
18
42
 
19
- NIL_IN_CACHE = Object.new
20
-
21
- def read(keep_in_context = false)
43
+ def read
22
44
  return nil if context[:renew_cache] == true
23
- return read_from_context { value_from_cache } if keep_in_context
45
+ return read_from_context { value_from_cache } if @keep_in_context
24
46
 
25
47
  value_from_cache
26
48
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "graphql/fragment_cache/fragment"
4
+ require "graphql/fragment_cache/schema/lazy_cache_resolver"
4
5
 
5
6
  module GraphQL
6
7
  module FragmentCache
@@ -44,14 +45,7 @@ module GraphQL
44
45
 
45
46
  fragment = Fragment.new(context_to_use, **options)
46
47
 
47
- keep_in_context = options.delete(:keep_in_context)
48
- if (cached = fragment.read(keep_in_context))
49
- return cached == Fragment::NIL_IN_CACHE ? nil : raw_value(cached)
50
- end
51
-
52
- (block_given? ? block.call : object_to_cache).tap do |resolved_value|
53
- context_to_use.fragments << fragment
54
- end
48
+ GraphQL::FragmentCache::Schema::LazyCacheResolver.new(fragment, context_to_use, object_to_cache, &block)
55
49
  end
56
50
  end
57
51
  end
@@ -0,0 +1,41 @@
1
+ require "graphql/fragment_cache/fragment"
2
+
3
+ module GraphQL
4
+ module FragmentCache
5
+ module Schema
6
+ using Ext
7
+ class LazyCacheResolver
8
+ def initialize(fragment, query_ctx, object_to_cache, &block)
9
+ @fragment = fragment
10
+ @query_ctx = query_ctx
11
+ @object_to_cache = object_to_cache
12
+ @lazy_state = query_ctx[:lazy_cache_resolver_statez] ||= {
13
+ pending_fragments: Set.new,
14
+ resolved_fragments: {}
15
+ }
16
+ @block = block
17
+
18
+ @lazy_state[:pending_fragments] << @fragment
19
+ end
20
+
21
+ def resolve
22
+ unless @lazy_state[:resolved_fragments].key?(@fragment)
23
+ resolved_fragments = Fragment.read_multi(@lazy_state[:pending_fragments].to_a)
24
+ @lazy_state[:pending_fragments].clear
25
+ resolved_fragments.each { |key, value| @lazy_state[:resolved_fragments][key] = value }
26
+ end
27
+
28
+ cached = @lazy_state[:resolved_fragments][@fragment]
29
+
30
+ if cached
31
+ return cached == Fragment::NIL_IN_CACHE ? nil : GraphQL::Execution::Interpreter::RawValue.new(cached)
32
+ end
33
+
34
+ (@block ? @block.call : @object_to_cache).tap do |resolved_value|
35
+ @query_ctx.fragments << @fragment
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -23,7 +23,7 @@ module GraphQL
23
23
  end
24
24
 
25
25
  def verify_connections!(context)
26
- return if GraphQL::FragmentCache.graphql_ruby_1_12_or_later? || context.schema.new_connections?
26
+ return if context.schema.new_connections?
27
27
 
28
28
  raise StandardError,
29
29
  "GraphQL::Pagination::Connections should be enabled for connection caching"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module FragmentCache
5
- VERSION = "1.9.1"
5
+ VERSION = "1.12.0"
6
6
  end
7
7
  end
@@ -11,6 +11,7 @@ require "graphql/fragment_cache/connections/patch"
11
11
  require "graphql/fragment_cache/schema/patch"
12
12
  require "graphql/fragment_cache/schema/tracer"
13
13
  require "graphql/fragment_cache/schema/instrumentation"
14
+ require "graphql/fragment_cache/schema/lazy_cache_resolver"
14
15
 
15
16
  require "graphql/fragment_cache/memory_store"
16
17
 
@@ -30,6 +31,7 @@ module GraphQL
30
31
  schema_defn.tracer(Schema::Tracer)
31
32
  schema_defn.instrument(:query, Schema::Instrumentation)
32
33
  schema_defn.extend(Schema::Patch)
34
+ schema_defn.lazy_resolve(Schema::LazyCacheResolver, :resolve)
33
35
 
34
36
  GraphQL::Pagination::Connections.prepend(Connections::Patch)
35
37
  end
@@ -50,29 +52,20 @@ module GraphQL
50
52
  @cache_store = store
51
53
  end
52
54
 
53
- def graphql_ruby_1_12_or_later?
54
- Gem::Dependency.new("graphql", ">= 1.12.0").match?("graphql", GraphQL::VERSION)
55
+ def graphql_ruby_before_2_0?
56
+ Gem::Dependency.new("graphql", "< 2.0.0").match?("graphql", GraphQL::VERSION)
55
57
  end
56
58
 
57
59
  private
58
60
 
59
61
  def verify_interpreter_and_analysis!(schema_defn)
60
- if graphql_ruby_1_12_or_later?
61
- unless schema_defn.interpreter?
62
- raise StandardError,
63
- "GraphQL::Execution::Execute should not be enabled for fragment caching"
64
- end
65
-
66
- unless schema_defn.analysis_engine == GraphQL::Analysis::AST
67
- raise StandardError,
68
- "GraphQL::Analysis should not be enabled for fragment caching"
69
- end
70
- else
62
+ if graphql_ruby_before_2_0?
71
63
  unless schema_defn.interpreter?
72
64
  raise StandardError,
73
65
  "GraphQL::Execution::Interpreter should be enabled for fragment caching"
74
66
  end
75
67
 
68
+ puts "schema_defn.analysis_engine #{schema_defn.analysis_engine}"
76
69
  unless schema_defn.analysis_engine == GraphQL::Analysis::AST
77
70
  raise StandardError,
78
71
  "GraphQL::Analysis::AST should be enabled for fragment caching"
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: 1.9.1
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-28 00:00:00.000000000 Z
11
+ date: 2022-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.10.8
19
+ version: 1.12.0
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.8
26
+ version: 1.12.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ruby-next
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -209,6 +209,7 @@ files:
209
209
  - lib/graphql/fragment_cache/rails/cache_key_builder.rb
210
210
  - lib/graphql/fragment_cache/railtie.rb
211
211
  - lib/graphql/fragment_cache/schema/instrumentation.rb
212
+ - lib/graphql/fragment_cache/schema/lazy_cache_resolver.rb
212
213
  - lib/graphql/fragment_cache/schema/patch.rb
213
214
  - lib/graphql/fragment_cache/schema/tracer.rb
214
215
  - lib/graphql/fragment_cache/version.rb
@@ -227,14 +228,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
227
228
  requirements:
228
229
  - - ">="
229
230
  - !ruby/object:Gem::Version
230
- version: '2.5'
231
+ version: '2.6'
231
232
  required_rubygems_version: !ruby/object:Gem::Requirement
232
233
  requirements:
233
234
  - - ">="
234
235
  - !ruby/object:Gem::Version
235
236
  version: '0'
236
237
  requirements: []
237
- rubygems_version: 3.2.31
238
+ rubygems_version: 3.3.3
238
239
  signing_key:
239
240
  specification_version: 4
240
241
  summary: Fragment cache for graphql-ruby