graphql-fragment_cache 1.14.0 → 1.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +28 -2
- data/lib/graphql/fragment_cache/cacher.rb +31 -1
- data/lib/graphql/fragment_cache/field_extension.rb +2 -0
- data/lib/graphql/fragment_cache/object_helpers.rb +3 -0
- data/lib/graphql/fragment_cache/schema/instrumentation.rb +6 -1
- data/lib/graphql/fragment_cache/version.rb +1 -1
- data/lib/graphql/fragment_cache.rb +8 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bcaf1bb938f830b5ae34b7b034e2ccbf8ce139e5da10db08e8ca52b658c0ed3
|
4
|
+
data.tar.gz: 5842f5166dc9cf69a276b3dee9836a43b757485ffe46f54031ce42341dfe797a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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 = "
|
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
|
-
|
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
|
|
@@ -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
|
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
|
@@ -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.
|
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-
|
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.
|
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: []
|