-
Notifications
You must be signed in to change notification settings - Fork 185
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prevent spurious SQL query execution via ActiveSupport::Cache events
When using a simple Rails view template like ```erb <% cache User.all do %> some content here <% end %> ``` we noticed that a spurious SQL query ```sql SELECT "users".* FROM "users" ``` was executed both on cache miss and on cache hit. Since the very point of [fragment caching][1] is to prevent this kind of queries, we investigated and found out that they were caused by `meta_request`. Rather than just stating the cache key used, events from `ActiveSupport::Cache` provide all original objects which contributed to the calculation of the cache key. This included `User.all` from the template. When `meta_request` checks whether this object is encodable to JSON ```ruby User.all.as_json(methods: [:duration]) ``` unintentionally triggers the spurious SQL query. We fix this by sanitizing the event payload and replacing the inputs of the cache key calculation with their final result. [1]: https://guides.rubyonrails.org/caching_with_rails.html#fragment-caching
- Loading branch information
Showing
3 changed files
with
64 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
inherit_from: .rubocop_todo.yml | ||
|
||
Metrics/BlockLength: | ||
ExcludedMethods: | ||
- describe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
RSpec.describe MetaRequest::Event do | ||
describe '.new' do | ||
context 'when transforming an event from ActiveSupport::Cache' do | ||
let(:active_support_cache_events) do | ||
%w[ | ||
cache_read.active_support | ||
cache_write.active_support | ||
] | ||
end | ||
|
||
let(:payload) do | ||
{ | ||
key: [ | ||
'views', | ||
'users/show:118c2da025706846afc6874e76b33a5c', | ||
active_record_relation | ||
] | ||
} | ||
end | ||
|
||
let(:active_record_relation) do | ||
double('ActiveRecord::Relation', cache_key: 'users/query-e06f359ccb226f3021b50c0c7e457f79') | ||
end | ||
|
||
let(:full_cache_key) do | ||
'views/users/show:118c2da025706846afc6874e76b33a5c/users/query-e06f359ccb226f3021b50c0c7e457f79' | ||
end | ||
|
||
it 'replaces the cache key with its String representation and does not trigger SQL queries' do | ||
# This would result in an SQL query being executed | ||
expect(active_record_relation).to_not receive(:as_json) | ||
|
||
event = described_class.new( | ||
active_support_cache_events.sample, | ||
Time.parse('2023-08-02 23:10:00.759479575 +0200'), | ||
Time.parse('2023-08-02 23:10:00.761230028 +0200'), | ||
SecureRandom.hex(10), | ||
payload | ||
) | ||
|
||
expect(event.payload[:key]).to eq(full_cache_key) | ||
end | ||
end | ||
end | ||
end |