Skip to content

Commit

Permalink
Disable ActiveRecord instrumentation (#68)
Browse files Browse the repository at this point in the history
* Fetch rather than delete options for easier defaults

* Allow AR instrumentation to be disabled

We want the cache queries to be fast and instrumentation can slow things
down. Additionally you might not want the SolidCache queries showing up
in your logs.

Instrumentation is enabled by default but can we disabled with:

```ruby
  config.cache_store = [ :solid_cache_store, active_record_instrumentation: false ]
```

* Disable instrumentation only in async
  • Loading branch information
djmb committed Sep 14, 2023
1 parent a8e6f8c commit a19a436
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 29 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Solid cache supports these options in addition to the universal `ActiveSupport::
- `max_entries` - the maximum number of entries allowed in the cache (default: `2.weeks.to_i`)
- `cluster` - a Hash of options for the cache database cluster, e.g { shards: [:database1, :database2, :database3] }
- `clusters` - and Array of Hashes for separate cache clusters (ignored if `:cluster` is set)
- `active_record_instrumentation` - whether to instrument the cache's queries (default: `true`)

For more information on cache clusters see [Sharding the cache](#sharding-the-cache)
### Cache trimming
Expand Down
10 changes: 10 additions & 0 deletions app/models/solid_cache/record.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
module SolidCache
class Record < ActiveRecord::Base
NULL_INSTRUMENTER = ActiveSupport::Notifications::Instrumenter.new(ActiveSupport::Notifications::Fanout.new)

self.abstract_class = true

connects_to **SolidCache.connects_to if SolidCache.connects_to

class << self
def disable_instrumentation
connection.with_instrumenter(NULL_INSTRUMENTER) do
yield
end
end
end
end
end

Expand Down
67 changes: 44 additions & 23 deletions lib/solid_cache/cluster/connection_handling.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ module ConnectionHandling

def initialize(options = {})
super(options)
@async_writes = options.delete(:async_writes)
@shard_options = options.delete(:shards)
@async_writes = options.fetch(:async_writes, false)
@shard_options = options.fetch(:shards, nil)
@active_record_instrumentation = options.fetch(:active_record_instrumentation, true)

if [Hash, Array, NilClass].none? { |klass| @shard_options.is_a? klass }
raise ArgumentError, "`shards` is a `#{shards.class.name}`, it should be one of Array, Hash or nil"
Expand Down Expand Up @@ -57,19 +58,17 @@ def writing_all_shards
return enum_for(:writing_all_shards) unless block_given?

shards.each do |shard|
with_shard(shard) do
async_if_required { yield }
with_shard(shard, async: async_writes) do
yield
end
end
end

def writing_across_shards(list:, trim: false)
across_shards(list:) do |list|
async_if_required do
result = yield list
trim(list.size) if trim
result
end
across_shards(list:, async: async_writes) do |list|
result = yield list
trim(list.size) if trim
result
end
end

Expand All @@ -78,33 +77,37 @@ def reading_across_shards(list:)
end

def writing_shard(normalized_key:, trim: false)
with_shard(shard_for_normalized_key(normalized_key)) do
async_if_required do
result = yield
trim(1) if trim
result
end
with_shard(shard_for_normalized_key(normalized_key), async: async_writes) do
result = yield
trim(1) if trim
result
end
end

def reading_shard(normalized_key:)
with_shard(shard_for_normalized_key(normalized_key)) { yield }
end

def active_record_instrumentation?
@active_record_instrumentation
end

private
attr_reader :consistent_hash

def with_shard(shard)
def with_shard(shard, async: false)
if shard
Record.connected_to(shard: shard) { yield }
Record.connected_to(shard: shard) do
configure_for_query(async: async) { yield }
end
else
yield
configure_for_query(async: async) { yield }
end
end

def across_shards(list:)
def across_shards(list:, async: false)
in_shards(list).map do |shard, list|
with_shard(shard) { yield list }
with_shard(shard, async: async) { yield list }
end
end

Expand All @@ -123,13 +126,31 @@ def shard_for_normalized_key(normalized_key)
nodes[node]
end

def async_if_required
if async_writes
def configure_for_query(async:)
async_if_required(async) do
disable_active_record_instrumentation_if_required do
yield
end
end
end

def async_if_required(required)
if required
async { yield }
else
yield
end
end

def disable_active_record_instrumentation_if_required
if active_record_instrumentation?
yield
else
Record.disable_instrumentation do
yield
end
end
end
end
end
end
6 changes: 3 additions & 3 deletions lib/solid_cache/cluster/trimming.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ module Trimming

def initialize(options = {})
super(options)
@trim_batch_size = options.delete(:trim_batch_size) || 100
@max_age = options.delete(:max_age) || 2.weeks.to_i
@max_entries = options.delete(:max_entries)
@trim_batch_size = options.fetch(:trim_batch_size, 100)
@max_age = options.fetch(:max_age, 2.weeks.to_i)
@max_entries = options.fetch(:max_entries, nil)
end

def trim(write_count)
Expand Down
5 changes: 2 additions & 3 deletions lib/solid_cache/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ def self.supports_cache_versioning?
def initialize(options = {})
super(options)
@max_key_bytesize = MAX_KEY_BYTESIZE
@error_handler = options.delete(:error_handler) || DEFAULT_ERROR_HANDLER
@error_handler = options.fetch(:error_handler, DEFAULT_ERROR_HANDLER)

clusters_options = options.key?(:cluster) ? [options.delete(:cluster)] : options.delete(:clusters)
clusters_options ||= [{}]
clusters_options = options.fetch(:clusters) { [options.fetch(:cluster, {})] }

@clusters = clusters_options.map.with_index do |cluster_options, index|
Cluster.new(options.merge(cluster_options).merge(async_writes: index != 0))
Expand Down

0 comments on commit a19a436

Please sign in to comment.