Skip to content

Commit 2cffc00

Browse files
danielhartnellDaniel Hartnell
andauthored
Introduce cache lookup instrumentation hook (#125)
* Introduce hook to monitor cache hits * Fixes failing specs when query context is missing * Support any number of named arguments * fix: address rubocop violation * Introduce option to enable cache lookup monitoring * Adds documentation for cache monitoring --------- Co-authored-by: Daniel Hartnell <[email protected]>
1 parent 8796342 commit 2cffc00

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,30 @@ Cache processing can be disabled if needed. For example:
446446
GraphQL::FragmentCache.enabled = false if Rails.env.test?
447447
```
448448

449+
## Cache lookup monitoring
450+
451+
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.
452+
453+
Example handler defined in a Rails initializer:
454+
455+
```ruby
456+
module GraphQL
457+
module FragmentCache
458+
class Fragment
459+
def self.cache_lookup_event(**args)
460+
# Monitoring such as incrementing a cache hit counter metric
461+
end
462+
end
463+
end
464+
end
465+
```
466+
467+
Like managing caching itself, monitoring can be enabled if needed. It is disabled by default. For example:
468+
469+
```ruby
470+
GraphQL::FragmentCache.monitoring_enabled = true
471+
```
472+
449473
## Limitations
450474

451475
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:

lib/graphql/fragment_cache.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module FragmentCache
2525
class << self
2626
attr_reader :cache_store
2727
attr_accessor :enabled
28+
attr_accessor :monitoring_enabled
2829
attr_accessor :namespace
2930
attr_accessor :default_options
3031

@@ -87,6 +88,7 @@ def verify_interpreter_and_analysis!(schema_defn)
8788

8889
self.cache_store = MemoryStore.new
8990
self.enabled = true
91+
self.monitoring_enabled = false
9092
self.namespace = "graphql"
9193
self.default_options = {}
9294
self.skip_cache_when_query_has_errors = false

lib/graphql/fragment_cache/fragment.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ def read_multi(fragments)
3030
FragmentCache.cache_store.read_multi(*cache_keys)
3131
end
3232

33+
if GraphQL::FragmentCache.monitoring_enabled
34+
begin
35+
fragments.map do |fragment|
36+
cache_lookup_event(
37+
cache_key: fragment.cache_key,
38+
operation_name: fragment.context.query.operation_name,
39+
path: fragment.path,
40+
cache_hit: cache_keys_to_values.key?(fragment.cache_key)
41+
)
42+
end
43+
rescue
44+
# Allow cache_lookup_event to fail when we do not have all of the requested attributes
45+
end
46+
end
47+
3348
# Fragmenst without values or with renew_cache: true in their context will have nil values like the read method
3449
fragments_to_cache_keys
3550
.map { |fragment, cache_key| [fragment, cache_keys_to_values[cache_key]] }.to_h
@@ -87,6 +102,11 @@ def interpreter_context
87102
def final_value
88103
@final_value ||= context.query.result["data"]
89104
end
105+
106+
def cache_lookup_event(**args)
107+
# This method can be implemented in your application
108+
# This provides a mechanism to monitor cache hits for a fragment
109+
end
90110
end
91111
end
92112
end

0 commit comments

Comments
 (0)