Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,30 @@ Cache processing can be disabled if needed. For example:
GraphQL::FragmentCache.enabled = false if Rails.env.test?
```

## Cache lookup monitoring

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.

Example handler defined in a Rails initializer:

```ruby
module GraphQL
module FragmentCache
class Fragment
def self.cache_lookup_event(**args)
# Monitoring such as incrementing a cache hit counter metric
end
end
end
end
```

Like managing caching itself, monitoring can be enabled if needed. It is disabled by default. For example:

```ruby
GraphQL::FragmentCache.monitoring_enabled = true
```

## Limitations

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:
Expand Down
2 changes: 2 additions & 0 deletions lib/graphql/fragment_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module FragmentCache
class << self
attr_reader :cache_store
attr_accessor :enabled
attr_accessor :monitoring_enabled
attr_accessor :namespace
attr_accessor :default_options

Expand Down Expand Up @@ -87,6 +88,7 @@ def verify_interpreter_and_analysis!(schema_defn)

self.cache_store = MemoryStore.new
self.enabled = true
self.monitoring_enabled = false
self.namespace = "graphql"
self.default_options = {}
self.skip_cache_when_query_has_errors = false
Expand Down
20 changes: 20 additions & 0 deletions lib/graphql/fragment_cache/fragment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ def read_multi(fragments)
FragmentCache.cache_store.read_multi(*cache_keys)
end

if GraphQL::FragmentCache.monitoring_enabled
begin
fragments.map do |fragment|
cache_lookup_event(
cache_key: fragment.cache_key,
operation_name: fragment.context.query.operation_name,
path: fragment.path,
cache_hit: cache_keys_to_values.key?(fragment.cache_key)
)
end
rescue
# Allow cache_lookup_event to fail when we do not have all of the requested attributes
end
end

# Fragmenst without values or with renew_cache: true in their context will have nil values like the read method
fragments_to_cache_keys
.map { |fragment, cache_key| [fragment, cache_keys_to_values[cache_key]] }.to_h
Expand Down Expand Up @@ -87,6 +102,11 @@ def interpreter_context
def final_value
@final_value ||= context.query.result["data"]
end

def cache_lookup_event(**args)
# This method can be implemented in your application
# This provides a mechanism to monitor cache hits for a fragment
end
end
end
end
Loading