graphql-fragment_cache 1.9.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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