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 +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: []
|