graphql-fragment_cache 1.14.0 → 1.16.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: 44be1de2fded16cfd021afebe96ce647616225fdbe5de8b140099d2c1bb16f94
4
- data.tar.gz: 94fb9a82b527c9786d81fed29e821416038c0b20a63f33fe765fc76abf0a9c24
3
+ metadata.gz: 3bcaf1bb938f830b5ae34b7b034e2ccbf8ce139e5da10db08e8ca52b658c0ed3
4
+ data.tar.gz: 5842f5166dc9cf69a276b3dee9836a43b757485ffe46f54031ce42341dfe797a
5
5
  SHA512:
6
- metadata.gz: c10be9f09dcddd09f175452f86071330fe3cb72e9d5875169e20c000372a88ec44e9c9830154e5d2016af177e55852ccf3ae2594e5069e939be4ab0a43676a24
7
- data.tar.gz: 5ded87b46c9757d28ac95028d16f2e2e71c3ed3d5252285898cc033dff835e61bff6aa7777633b8798eed6fb9dcecacf78d0e0623f1952f74139be8b66a9beee
6
+ metadata.gz: e218c2d46cb5cc545d0374c86c64f46380b82a4c31dd67d0dcb06890e23c4156ed16cef838d3965ae54283e28ea7ba155d965920dbc1c9a722a64fff7c174b69
7
+ data.tar.gz: caa35cd10a7c657b838088b0ffd449b981ee3565483691619af1c839a184febccacf19620c31bfee26f434929218e2ecd4478a6edbca7bf97ae3a68245bbe316
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.16.0 (2022-11-06)
6
+
7
+ - [PR#42](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/42) Raise helpful errors when write or write_multi fails ([@DmitryTsepelev][])
8
+ - [PR#86](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/86) Support passing Procs to `cache_key:` ([@jeromedalbert][])
9
+ - [PR#90](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/90) Add option to disable the cache ([@jeromedalbert][])
10
+ - [PR#89](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/89) Use a "graphql" cache namespace by default ([@jeromedalbert][])
11
+
12
+ ## 1.15.0 (2022-10-27)
13
+
14
+ - [PR#43](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/43) Implement `skip_cache_when_query_has_errors` option to skip caching when query was resolved with errors ([@DmitryTsepelev][])
15
+
5
16
  ## 1.14.0 (2022-10-26)
6
17
 
7
18
  - [PR#85](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/85) Support passing Symbols to `if:` and `unless:` ([@palkan][])
data/README.md CHANGED
@@ -72,10 +72,10 @@ Cache keys consist of the following parts: namespace, implicit key, and explicit
72
72
 
73
73
  ### Cache namespace
74
74
 
75
- You can optionally define a namespace that will be prefixed to every cache key:
75
+ The namespace is prefixed to every cached key. The default namespace is `graphql`, which is configurable:
76
76
 
77
77
  ```ruby
78
- GraphQL::FragmentCache.namespace = "my-prefix"
78
+ GraphQL::FragmentCache.namespace = "graphql"
79
79
  ```
80
80
 
81
81
  ### Implicit cache key
@@ -237,6 +237,14 @@ def post(id:)
237
237
  end
238
238
  ```
239
239
 
240
+ If you need more control, you can set `cache_key:` to any custom code:
241
+
242
+ ```ruby
243
+ field :posts,
244
+ Types::Objects::PostType.connection_type,
245
+ cache_fragment: {cache_key: -> { object.posts.maximum(:created_at) }}
246
+ ```
247
+
240
248
  The way cache key part is generated for the passed argument is the following:
241
249
 
242
250
  - Use `object_cache_key: "some_cache_key"` if passed to `cache_fragment`
@@ -424,6 +432,24 @@ end
424
432
 
425
433
  This can reduce a number of cache calls but _increase_ memory usage, because the value returned from cache will be kept in the GraphQL context until the query is fully resolved.
426
434
 
435
+ ## Execution errors and caching
436
+
437
+ Sometimes errors happen during query resolving and it might make sense to skip caching for such queries (for instance, imagine a situation when client has no access to the requested field and the backend returns `{ data: {}, errors: ["you need a permission to fetch orders"] }`). This is how this behavior can be turned on (_it's off by default!_):
438
+
439
+ ```ruby
440
+ GraphQL::FragmentCache.skip_cache_when_query_has_errors = true
441
+ ```
442
+
443
+ As a result, caching will be skipped when `errors` array is not empty.
444
+
445
+ ## Disabling the cache
446
+
447
+ Cache processing can be disabled if needed. For example:
448
+
449
+ ```ruby
450
+ GraphQL::FragmentCache.enabled = false if Rails.env.test?
451
+ ```
452
+
427
453
  ## Limitations
428
454
 
429
455
  1. `Schema#execute`, [graphql-batch](https://github.com/Shopify/graphql-batch) and _graphql-ruby-fragment_cache_ do not [play well](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/issues/45) together. The problem appears when `cache_fragment` is _inside_ the `.then` block:
@@ -4,6 +4,29 @@ module GraphQL
4
4
  module FragmentCache
5
5
  using Ext
6
6
 
7
+ class WriteError < StandardError
8
+ attr_reader :key, :value, :original_error
9
+
10
+ def initialize(original_error, key, value)
11
+ @original_error = original_error
12
+ @key = key
13
+ @value = value
14
+
15
+ super(original_error.message)
16
+ end
17
+ end
18
+
19
+ class WriteMultiError < StandardError
20
+ attr_reader :values, :original_error
21
+
22
+ def initialize(original_error, values)
23
+ @original_error = original_error
24
+ @values = values
25
+
26
+ super(original_error.message)
27
+ end
28
+ end
29
+
7
30
  # Saves resolved fragment values to cache store
8
31
  module Cacher
9
32
  class << self
@@ -22,13 +45,20 @@ module GraphQL
22
45
  def batched_persist(query)
23
46
  select_valid_fragments(query).group_by(&:options).each do |options, group|
24
47
  hash = group.map { |fragment| [fragment.cache_key, fragment.value] }.to_h
25
- FragmentCache.cache_store.write_multi(hash, **options)
48
+
49
+ begin
50
+ FragmentCache.cache_store.write_multi(hash, **options)
51
+ rescue => e
52
+ raise WriteMultiError.new(e, hash)
53
+ end
26
54
  end
27
55
  end
28
56
 
29
57
  def persist(query)
30
58
  select_valid_fragments(query).each do |fragment|
31
59
  FragmentCache.cache_store.write(fragment.cache_key, fragment.value, **fragment.options)
60
+ rescue => e
61
+ raise WriteError.new(e, fragment.cache_key, fragment.value)
32
62
  end
33
63
  end
34
64
 
@@ -70,6 +70,8 @@ module GraphQL
70
70
  object.object
71
71
  elsif @cache_key == :value
72
72
  resolved_value = yield(object, arguments)
73
+ elsif @cache_key.is_a?(Proc)
74
+ object.instance_exec(&@cache_key)
73
75
  end
74
76
 
75
77
  cache_fragment_options = @cache_options.merge(object: object_for_key)
@@ -25,6 +25,9 @@ module GraphQL
25
25
 
26
26
  def cache_fragment(object_to_cache = NO_OBJECT, **options, &block)
27
27
  raise ArgumentError, "Block or argument must be provided" unless block_given? || object_to_cache != NO_OBJECT
28
+ unless GraphQL::FragmentCache.enabled
29
+ return block_given? ? block.call : object_to_cache
30
+ end
28
31
 
29
32
  unless options.delete(:default_options_merged)
30
33
  options = GraphQL::FragmentCache.default_options.merge(options)
@@ -13,10 +13,15 @@ module GraphQL
13
13
  end
14
14
 
15
15
  def after_query(query)
16
- return unless query.valid?
16
+ return if skip_caching?(query)
17
17
 
18
18
  Cacher.call(query)
19
19
  end
20
+
21
+ def skip_caching?(query)
22
+ !query.valid? ||
23
+ GraphQL::FragmentCache.skip_cache_when_query_has_errors? && query.context.errors.any?
24
+ end
20
25
  end
21
26
  end
22
27
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module FragmentCache
5
- VERSION = "1.14.0"
5
+ VERSION = "1.16.0"
6
6
  end
7
7
  end
@@ -22,9 +22,12 @@ module GraphQL
22
22
  module FragmentCache
23
23
  class << self
24
24
  attr_reader :cache_store
25
+ attr_accessor :enabled
25
26
  attr_accessor :namespace
26
27
  attr_accessor :default_options
27
28
 
29
+ attr_accessor :skip_cache_when_query_has_errors
30
+
28
31
  def use(schema_defn, options = {})
29
32
  verify_interpreter_and_analysis!(schema_defn)
30
33
 
@@ -52,6 +55,8 @@ module GraphQL
52
55
  @cache_store = store
53
56
  end
54
57
 
58
+ alias skip_cache_when_query_has_errors? skip_cache_when_query_has_errors
59
+
55
60
  def graphql_ruby_before_2_0?
56
61
  check_graphql_version "< 2.0.0"
57
62
  end
@@ -83,7 +88,10 @@ module GraphQL
83
88
  end
84
89
 
85
90
  self.cache_store = MemoryStore.new
91
+ self.enabled = true
92
+ self.namespace = "graphql"
86
93
  self.default_options = {}
94
+ self.skip_cache_when_query_has_errors = false
87
95
  end
88
96
  end
89
97
 
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.14.0
4
+ version: 1.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-26 00:00:00.000000000 Z
11
+ date: 2022-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -220,7 +220,7 @@ metadata:
220
220
  homepage_uri: https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache
221
221
  source_code_uri: https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache
222
222
  changelog_uri: https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/CHANGELOG.md
223
- post_install_message:
223
+ post_install_message:
224
224
  rdoc_options: []
225
225
  require_paths:
226
226
  - lib
@@ -235,8 +235,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
235
  - !ruby/object:Gem::Version
236
236
  version: '0'
237
237
  requirements: []
238
- rubygems_version: 3.1.6
239
- signing_key:
238
+ rubygems_version: 3.2.33
239
+ signing_key:
240
240
  specification_version: 4
241
241
  summary: Fragment cache for graphql-ruby
242
242
  test_files: []