Skip to content

Commit a838df6

Browse files
authored
Merge branch 'DmitryTsepelev:master' into master
2 parents 87cddfb + 845c826 commit a838df6

34 files changed

+474
-243
lines changed

.github/workflows/rspec.yml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@ jobs:
1919
strategy:
2020
fail-fast: false
2121
matrix:
22-
ruby: [2.6, 2.7, '3.0', 3.1, 3.2]
22+
ruby: [3.1, 3.2, 3.3, 3.4]
2323
gemfile: [
24-
"gemfiles/graphql_1_12_0.gemfile",
25-
"gemfiles/graphql_1_13_7.gemfile",
26-
"gemfiles/graphql_2_0_0.gemfile",
27-
"gemfiles/graphql_2_0_14.gemfile",
24+
"gemfiles/graphql_2_1_4.gemfile",
25+
"gemfiles/graphql_2_3_0.gemfile",
26+
"gemfiles/graphql_2_3_11.gemfile",
27+
"gemfiles/graphql_2_4_8.gemfile",
2828
"gemfiles/graphql_master.gemfile"
2929
]
30+
exclude:
31+
- ruby: "3.1"
32+
gemfile: gemfiles/graphql_2_3_0.gemfile
33+
- ruby: "3.1"
34+
gemfile: gemfiles/graphql_2_3_11.gemfile
35+
- ruby: "3.1"
36+
gemfile: gemfiles/graphql_master.gemfile
3037

3138
steps:
3239
- uses: actions/checkout@v2
@@ -36,8 +43,6 @@ jobs:
3643
bundler-cache: true
3744
bundler: 2.2.0
3845
cache-version: 1
39-
- name: Run Ruby Next
40-
run: bundle exec rake nextify
4146
- name: Run RSpec
4247
run: |
4348
bundle exec rake spec

.github/workflows/rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- uses: actions/checkout@v2
1515
- uses: ruby/setup-ruby@v1
1616
with:
17-
ruby-version: 2.7
17+
ruby-version: 3.1
1818
bundler-cache: true
1919
bundler: 2.2.0
2020
- name: Lint Ruby code with RuboCop

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Gemfile.lock
1010
.DS_Store
1111
.rbnext/
1212
*.sqlite3
13+
*.sqlite3-*
1314
spec/internal/log/*.log
1415
.idea/
1516
.ruby-version

.rbnextrc

Lines changed: 0 additions & 2 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,49 @@
22

33
## master
44

5+
## 1.22.0 (2025-02-20)
6+
7+
- [PR#134](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/134) Add possibility to include and exclude arguments from generated cache key ([@mgruner][])
8+
9+
## 1.21.0 (2025-02-01)
10+
11+
- [PR#130](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/130) Dataloader support ([@DmitryTsepelev][])
12+
- [PR#125](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/125) Introduce cache lookup instrumentation hook ([@danielhartnell][])
13+
14+
## 1.20.5 (2024-11-02)
15+
16+
- [PR#120](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/120) Fix warning on ActiveSupport::Cache.format_version ([@Drowze][])
17+
18+
## 1.20.4 (2024-10-05)
19+
20+
- [PR#119](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/119) Fix Rails cache_format_version deprecation ([@noma4i][])
21+
22+
## 1.20.3 (2024-09-06)
23+
24+
- [PR#117](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/117) Deprecate old ruby and gql versions ([@DmitryTsepelev][])
25+
- [PR#116](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/116) Migrate CompiledQueries instrumentation to tracer ([@DmitryTsepelev][])
26+
27+
## 1.20.2 (2024-06-01)
28+
29+
- [PR#115](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/115) Fix deprecation warning for cache_format_version in Rails 7.1 ([@rince][])
30+
31+
## 1.20.1 (2024-04-03)
32+
33+
- [PR#112](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/112) fix tracer deprecation warnings ([@diegofigueroa][])
34+
- [PR#109](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/109) Remove `Lookahead` patch in modern versions of graphql-ruby ([@DmitryTsepelev][])
35+
36+
## 1.20.0 (2024-03-02)
37+
38+
- [PR#108](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/108) Use trace_with instead of deprecated instrument method ([@camero2734][])
39+
40+
## 1.19.0 (2023-11-03)
41+
42+
- [PR#104](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/104) Support graphql-ruby 2.1.4 ([@DmitryTsepelev][])
43+
44+
## 1.18.2 (2023-02-21)
45+
46+
- [PR#100](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/100) Fix an error when `path_cache_key` is nil ([@rince][])
47+
548
## 1.18.1 (2023-01-06)
649

750
- [PR#96](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/96) Properly pass arguments to `write_multi` ([@DmitryTsepelev][])
@@ -172,3 +215,10 @@
172215
[@daukadolt]: https://github.com/daukadolt
173216
[@frostmark]: https://github.com/frostmark
174217
[@KTSCode]: https://github.com/KTSCode
218+
[@rince]: https://github.com/rince
219+
[@camero2734]: https://github.com/camero2734
220+
[@diegofigueroa]: https://github.com/diegofigueroa
221+
[@noma4i]: https://github.com/noma4i
222+
[@Drowze]: https://github.com/Drowze
223+
[@danielhartnell]: https://github.com/danielhartnell
224+
[@mgruner]: https://github.com/mgruner

Makefile

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
default: test
22

3-
nextify:
4-
bundle exec rake nextify
5-
6-
test: nextify
3+
test:
74
bundle exec rake
85
CI=true bundle exec rake
96

README.md

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class PostType < BaseObject
99
end
1010
```
1111

12+
You can support my open–source work [here](https://boosty.to/dmitry_tsepelev).
13+
1214
## Getting started
1315

1416
Add the gem to your Gemfile `gem 'graphql-fragment_cache'` and add the plugin to your schema class:
@@ -145,6 +147,34 @@ class QueryType < BaseObject
145147
end
146148
```
147149

150+
### Query arguments processing
151+
152+
You can influence the way that graphql arguments are include in the cache key.
153+
154+
A use case might be a `:renew_cache` parameter that can be used to force a cache rewrite,
155+
but should not be included with the cache key itself. Use `cache_key: { exclude_arguments: […]}`
156+
to specify a list of arguments to be excluded from the implicit cache key.
157+
158+
```ruby
159+
class QueryType < BaseObject
160+
field :post, PostType, null: true do
161+
argument :id, ID, required: true
162+
argument :renew_cache, Boolean, required: false
163+
end
164+
165+
def post(id:, renew_cache: false)
166+
if renew_cache
167+
context.scoped_set!(:renew_cache, true)
168+
end
169+
cache_fragment(cache_key: {exclude_arguments: [:renew_cache]}) { Post.find(id) }
170+
end
171+
end
172+
```
173+
174+
Likewise, you can use `cache_key: { include_arguments: […] }` to specify an allowlist of arguments
175+
to be included in the cache key. In this case all arguments for the cache key must be specified, including
176+
parent arguments of nested fields.
177+
148178
### User-provided cache key (custom key)
149179

150180
In most cases you want your cache key to depend on the resolved object (say, `ActiveRecord` model). You can do that by passing an argument to the `#cache_fragment` method in a similar way to Rails views [`#cache` method](https://guides.rubyonrails.org/caching_with_rails.html#fragment-caching):
@@ -379,6 +409,34 @@ class QueryType < BaseObject
379409
end
380410
```
381411

412+
## Dataloader
413+
414+
If you are using [Dataloader](https://graphql-ruby.org/dataloader/overview.html), you will need to let the gem know using `dataloader: true`:
415+
416+
```ruby
417+
class PostType < BaseObject
418+
field :author, User, null: false
419+
420+
def author
421+
cache_fragment(dataloader: true) do
422+
dataloader.with(AuthorDataloaderSource).load(object.id)
423+
end
424+
end
425+
end
426+
427+
# or
428+
429+
class PostType < BaseObject
430+
field :author, User, null: false, cache_fragment: {dataloader: true}
431+
432+
def author
433+
dataloader.with(AuthorDataloaderSource).load(object.id)
434+
end
435+
end
436+
```
437+
438+
The problem is that I didn't find a way to detect that dataloader (and, therefore, Fiber) is used, and the block is forced to resolve, causing the N+1 inside the Dataloader Source class.
439+
382440
## How to use `#cache_fragment` in extensions (and other places where context is not available)
383441

384442
If you want to call `#cache_fragment` from places other that fields or resolvers, you'll need to pass `context` explicitly and turn on `raw_value` support. For instance, let's take a look at this extension:
@@ -444,6 +502,30 @@ Cache processing can be disabled if needed. For example:
444502
GraphQL::FragmentCache.enabled = false if Rails.env.test?
445503
```
446504

505+
## Cache lookup monitoring
506+
507+
It may be useful to capture cache lookup events. When monitoring is enabled, the `cache_key`, `operation_name`, `path` and a boolean indicating a cache hit or miss will be sent to a `cache_lookup_event` method. This method can be implemented in your application to handle the event.
508+
509+
Example handler defined in a Rails initializer:
510+
511+
```ruby
512+
module GraphQL
513+
module FragmentCache
514+
class Fragment
515+
def self.cache_lookup_event(**args)
516+
# Monitoring such as incrementing a cache hit counter metric
517+
end
518+
end
519+
end
520+
end
521+
```
522+
523+
Like managing caching itself, monitoring can be enabled if needed. It is disabled by default. For example:
524+
525+
```ruby
526+
GraphQL::FragmentCache.monitoring_enabled = true
527+
```
528+
447529
## Limitations
448530

449531
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:
@@ -469,13 +551,13 @@ def cached_author_inside_batch
469551
end
470552
```
471553

472-
2. Caching does not work for Union types, because of the `Lookahead` implementation: it requires the exact type to be passed to the `selection` method (you can find the [discussion](https://github.com/rmosolgo/graphql-ruby/pull/3007) here). This method is used for cache key building, and I haven't found a workaround yet ([PR in progress](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/30)). If you get `Failed to look ahead the field` error — please pass `query_cache_key` explicitly:
554+
2. Caching does not work for Union types, because of the `Lookahead` implementation: it requires the exact type to be passed to the `selection` method (you can find the [discussion](https://github.com/rmosolgo/graphql-ruby/pull/3007) here). This method is used for cache key building, and I haven't found a workaround yet ([PR in progress](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/30)). If you get `Failed to look ahead the field` error — please pass `path_cache_key` explicitly:
473555

474556
```ruby
475557
field :cached_avatar_url, String, null: false
476558

477559
def cached_avatar_url
478-
cache_fragment(query_cache_key: "post_avatar_url(#{object.id})") { object.avatar_url }
560+
cache_fragment(path_cache_key: "post_avatar_url(#{object.id})") { object.avatar_url }
479561
end
480562
```
481563

Rakefile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ require "rspec/core/rake_task"
33

44
RSpec::Core::RakeTask.new(:spec)
55

6-
desc "Run Ruby Next nextify"
7-
task :nextify do
8-
sh "bundle exec ruby-next nextify ./lib -V"
9-
end
10-
116
desc "Run specs without Rails"
127
RSpec::Core::RakeTask.new("spec:norails") do |task|
138
task.exclude_pattern = "**/rails/**"
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
source "https://rubygems.org"
22

3-
gem "graphql", "~> 2.0.0"
3+
gem "graphql", "~> 2.1.4"
44

55
gemspec path: "../"
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
source "https://rubygems.org"
22

3-
gem "graphql", "~> 2.0.14"
3+
gem "graphql", "~> 2.3.0"
44

55
gemspec path: "../"

0 commit comments

Comments
 (0)