Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support rails 7.2 #35

Merged
merged 6 commits into from
Aug 8, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@v4

- name: Start containers
run: docker-compose -f docker-compose.yml up -d
run: docker compose -f docker-compose.yml up -d

- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
Expand All @@ -43,4 +43,4 @@ jobs:

- name: Stop containers
if: always()
run: docker-compose -f "docker-compose.yml" down
run: docker compose -f "docker-compose.yml" down
6 changes: 5 additions & 1 deletion Appraisals
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
appraisals = [
"6.1.7.8",
"7.0.8.4",
"7.1.3.4"
"7.1.3.4",
]

if RUBY_VERSION >= "3.1"
appraisals << "7.2.0.rc1"
end

appraisals.each do |rails_version|
%w(4.0 5.0).each do |redis_version|
appraise "activesupport-#{rails_version}-redis-#{redis_version}" do
Expand Down
54 changes: 37 additions & 17 deletions lib/time_bandits/monkey_patches/active_record/runtime_registry.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
# This file monkey patches class ActiveRecord::RuntimeRegistry to
# additionally store call counts and cache hits and subscribes an
# event listener to manage those counters.
# event listener to manage those counters. It is used if the active
# record version is 7.1.0 or higher.

require "active_record/runtime_registry"

module ActiveRecord
module RuntimeRegistry

def self.call_count
ActiveSupport::IsolatedExecutionState[:active_record_sql_call_count] ||= 0
end
if respond_to?(:queries_count)
alias_method :call_count, :queries_count
alias_method :call_count=, :queries_count=
else
def self.call_count
ActiveSupport::IsolatedExecutionState[:active_record_sql_call_count] ||= 0
end

def self.call_count=(value)
ActiveSupport::IsolatedExecutionState[:active_record_sql_call_count] = value
def self.call_count=(value)
ActiveSupport::IsolatedExecutionState[:active_record_sql_call_count] = value
end
end

def self.query_cache_hits
ActiveSupport::IsolatedExecutionState[:active_record_sql_query_cache_hits] ||= 0
end
if respond_to?(:cached_queries_count)
alias_method :query_cache_hits, :cached_queries_count
alias_method :query_cache_hits=, :cached_queries_count=
else
def self.query_cache_hits
ActiveSupport::IsolatedExecutionState[:active_record_sql_query_cache_hits] ||= 0
end

def self.query_cache_hits=(value)
ActiveSupport::IsolatedExecutionState[:active_record_sql_query_cache_hits] = value
end
def self.query_cache_hits=(value)
ActiveSupport::IsolatedExecutionState[:active_record_sql_query_cache_hits] = value
end
end

alias_method :reset_runtime, :reset
if respond_to?(:reset_runtimes)
alias_method :reset_runtime, :reset_runtimes
else
alias_method :reset_runtime, :reset
end
alias_method :runtime, :sql_runtime
alias_method :runtime=, :sql_runtime=

Expand All @@ -42,9 +57,14 @@ def self.reset_query_cache_hits
end
end

require "active_support/notifications"

ActiveSupport::Notifications.subscribe("sql.active_record") do |event|
ActiveRecord::RuntimeRegistry.call_count += 1
ActiveRecord::RuntimeRegistry.query_cache_hits += 1 if event.payload[:cached]
# Rails 7.2 already collects query counts and cache hits, so we no
# longer need our own event handler.
unless ActiveRecord::RuntimeRegistry.respond_to?(:queries_count)
require "active_support/notifications"

ActiveSupport::Notifications.monotonic_subscribe("sql.active_record") do |event|
ActiveRecord::RuntimeRegistry.call_count += 1
ActiveRecord::RuntimeRegistry.query_cache_hits += 1 if event.payload[:cached]
end
end
21 changes: 17 additions & 4 deletions test/unit/database_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def teardown

test "accessing current runtime" do
metrics_store.runtime += 1.234
assert_equal 1.234, metrics_store.runtime
assert_equal 1.234, bandit.current_runtime
assert_equal 1.234, TimeBandits.consumed
assert_equal 0, metrics_store.runtime
metrics_store.runtime += 4.0
Expand All @@ -66,20 +68,31 @@ def teardown
ActiveRecord::Base.connection.execute "SELECT 1"
bandit.consumed
assert(bandit.current_runtime > 0)
# 2 calls, because one configures the connection
assert_equal 2, bandit.calls
if ActiveRecord::VERSION::STRING =~ /\A7.2\..*\Z/
# registry ingores schema calls now
assert_equal 1, bandit.calls
else
# 2 calls, because one configures the connection
assert_equal 2, bandit.calls
end
assert_equal 0, bandit.sql_query_cache_hits
end

test "instrumentation records runtimes at log level error" do
skip if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("7.1.0")
ActiveRecord::Base.logger.level = Logger::ERROR
ActiveRecord::LogSubscriber.expects(:sql).never
assert_equal 0, bandit.calls
ActiveRecord::Base.connection.execute "SELECT 1"
bandit.consumed
assert(bandit.current_runtime > 0)
# 2 calls, because one configures the connection
assert_equal 2, bandit.calls
if ActiveRecord::VERSION::STRING =~ /\A7.2\..*\Z/
# registry ingores schema calls now
assert_equal 1, bandit.calls
else
# 2 calls, because one configures the connection
assert_equal 2, bandit.calls
end
assert_equal 0, bandit.sql_query_cache_hits
end

Expand Down
2 changes: 2 additions & 0 deletions time_bandits.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ Gem::Specification.new do |s|

s.add_runtime_dependency("thread_variables")
s.add_runtime_dependency("activesupport", [">= 5.2.0"])
s.add_runtime_dependency("base64")
s.add_runtime_dependency("mutex_m")
end