Skip to content

Commit

Permalink
Add min_n_queries & ignore_pauses config options
Browse files Browse the repository at this point in the history
  • Loading branch information
charkost committed Oct 27, 2022
1 parent 39bcf82 commit 511a745
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Or install it yourself as:

The preferred type of notifications can be configured with:

* `Prosopite.min_n_queries`: Minimum number of N queries to report per N+1 case. Defaults to 2.
* `Prosopite.raise = true`: Raise warnings as exceptions
* `Prosopite.rails_logger = true`: Send warnings to the Rails log
* `Prosopite.prosopite_logger = true`: Send warnings to `log/prosopite.log`
Expand Down Expand Up @@ -269,6 +270,8 @@ end
Prosopite.finish
```

Pauses can be ignored with `Prosopite.ignore_pauses = true` in case you want to remember their N+1 queries.

An example of when you might use this is if you are [testing Active Jobs inline](https://guides.rubyonrails.org/testing.html#testing-jobs),
and don't want to run Prosopite on background job code, just foreground app code. In that case you could write an [Active Job callback](https://edgeguides.rubyonrails.org/active_job_basics.html#callbacks) that pauses the scan while the job is running.

Expand Down
12 changes: 10 additions & 2 deletions lib/prosopite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class << self
:prosopite_logger,
:custom_logger,
:allow_stack_paths,
:ignore_queries
:ignore_queries,
:ignore_pauses,
:min_n_queries

def allow_list=(value)
puts "Prosopite.allow_list= is deprecated. Use Prosopite.allow_stack_paths= instead."
Expand All @@ -29,6 +31,8 @@ def scan
tc[:prosopite_query_caller] = {}

@allow_stack_paths ||= []
@ignore_pauses ||= false
@min_n_queries ||= 2

tc[:prosopite_scan] = true

Expand All @@ -48,6 +52,10 @@ def tc
end

def pause
if @ignore_pauses
return block_given? ? yield : nil
end

if block_given?
begin
previous = tc[:prosopite_scan]
Expand Down Expand Up @@ -83,7 +91,7 @@ def create_notifications
tc[:prosopite_notifications] = {}

tc[:prosopite_query_counter].each do |location_key, count|
if count > 1
if count >= @min_n_queries
fingerprints = tc[:prosopite_query_holder][location_key].map do |q|
begin
fingerprint(q)
Expand Down
33 changes: 33 additions & 0 deletions test/test_queries.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ def test_pause_with_no_error_after_resume
assert_no_n_plus_ones
end

def test_pause_with_ignore_pauses
# 20 chairs, 4 legs each
chairs = create_list(:chair, 20)
chairs.each { |c| create_list(:leg, 4, chair: c) }

Prosopite.ignore_pauses = true
Prosopite.scan

Prosopite.pause
Chair.last(20).each do |c|
c.legs.last
end

Prosopite.resume
Prosopite.ignore_pauses = false

assert_n_plus_one
end

def test_pause_with_error_after_resume
# 20 chairs, 4 legs each
chairs = create_list(:chair, 20)
Expand Down Expand Up @@ -348,6 +367,20 @@ def test_ignore_queries_with_incorrect_query_match
assert_n_plus_one
end

def test_min_n_queries
chairs = create_list(:chair, 4)
chairs.each { |c| create_list(:leg, 4, chair: c) }

Prosopite.min_n_queries = 5

Prosopite.scan
Chair.last(4).each do |c|
c.legs.last
end

assert_no_n_plus_ones
end

private
def assert_n_plus_one
assert_raises(Prosopite::NPlusOneQueriesError) do
Expand Down

0 comments on commit 511a745

Please sign in to comment.