prosopite 1.0.0 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3df6a0299972911e48ea44330995864e2cd2191ec66c199296ba324a5fa8e639
4
- data.tar.gz: 4f9ee347a8cf52fd742ee66586c7e4b601c8436a4bcabe1b1afdef5e09293f44
3
+ metadata.gz: 66728f096f4aafd32cf868f6b24ce88daae9d282b21d2c8b95ed0b732a299d2c
4
+ data.tar.gz: 4259b7a737bc367742efc158d425a57c1e24c435991f3ad4bd57dbd7a6c195d4
5
5
  SHA512:
6
- metadata.gz: 668bc7e58bcabd77231adc831054d56ca572e1e9857f87736d1fd06048c1eeaac9c0c0ab970c6ed6f8ce70670ae51277c3c4f56012d0ec61240c0e728c1f3795
7
- data.tar.gz: '0341920f4f1beddc2b9c46553f9284724ecddfe50f30579a7cc9627c93fdf2d3c714bb57fd453dd7a4783a86951b9dd2cb0a79e721189bce3b89eda0c119c8bf'
6
+ metadata.gz: 3fc7f6c647ebfcbce614c0ef7c51a2e9a69b6da7090d889e65dd535891c93a33b07e4228f2d877951a26a06f8bd53687567bf86fed2b77f9558b84a0c24eaa4f
7
+ data.tar.gz: 139a0047ea3aed0f99a0900bf8c2bf235d5fe1723563859c85bd887daae96a8d65c2b21e5f9ad350384de6424c2ef8a3f7ea1df9d66d8bfb33af2009133f0eb4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prosopite (0.2.1)
4
+ prosopite (1.0.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -127,11 +127,12 @@ Prosopite auto-detection can be enabled on all controllers:
127
127
  ```ruby
128
128
  class ApplicationController < ActionController::Base
129
129
  unless Rails.env.production?
130
- before_action do
130
+ around_action :n_plus_one_detection
131
+
132
+ def n_plus_one_detection
131
133
  Prosopite.scan
132
- end
133
-
134
- after_action do
134
+ yield
135
+ ensure
135
136
  Prosopite.finish
136
137
  end
137
138
  end
@@ -194,6 +195,31 @@ Prosopite.scan
194
195
  Prosopite.finish
195
196
  ```
196
197
 
198
+ or
199
+
200
+ ```ruby
201
+ Prosopite.scan do
202
+ <code to scan>
203
+ end
204
+ ```
205
+
206
+ ## Pausing and resuming scans
207
+
208
+ Scans can be paused:
209
+
210
+ ```ruby
211
+ Prosopite.scan
212
+ # <code to scan>
213
+ Prosopite.pause
214
+ # <code that has n+1s>
215
+ Prosopite.resume
216
+ # <code to scan>
217
+ Prosopite.finish
218
+ ```
219
+
220
+ An example of when you might use this is if you are [testing Active Jobs inline](https://guides.rubyonrails.org/testing.html#testing-jobs),
221
+ 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.
222
+
197
223
  ## Contributing
198
224
 
199
225
  Bug reports and pull requests are welcome on GitHub at https://github.com/charkost/prosopite.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Prosopite
4
- VERSION = "1.0.0"
4
+ VERSION = "1.0.4"
5
5
  end
data/lib/prosopite.rb CHANGED
@@ -1,5 +1,7 @@
1
1
 
2
2
  module Prosopite
3
+ DEFAULT_ALLOW_LIST = %w(active_record/associations/preloader active_record/validations/uniqueness)
4
+
3
5
  class NPlusOneQueriesError < StandardError; end
4
6
  class << self
5
7
  attr_writer :raise,
@@ -21,12 +23,29 @@ module Prosopite
21
23
  @allow_list ||= []
22
24
 
23
25
  tc[:prosopite_scan] = true
26
+
27
+ if block_given?
28
+ begin
29
+ yield
30
+ finish
31
+ ensure
32
+ tc[:prosopite_scan] = false
33
+ end
34
+ end
24
35
  end
25
36
 
26
37
  def tc
27
38
  Thread.current
28
39
  end
29
40
 
41
+ def pause
42
+ tc[:prosopite_scan] = false
43
+ end
44
+
45
+ def resume
46
+ tc[:prosopite_scan] = true
47
+ end
48
+
30
49
  def scan?
31
50
  tc[:prosopite_scan]
32
51
  end
@@ -53,14 +72,14 @@ module Prosopite
53
72
  end
54
73
  end
55
74
 
75
+ next unless fingerprints.uniq.size == 1
76
+
56
77
  kaller = tc[:prosopite_query_caller][location_key]
57
78
 
58
- if fingerprints.uniq.size == 1 && !kaller.any? { |f| @allow_list.any? { |s| f.include?(s) } }
79
+ is_allowed = kaller.any? { |f| @allow_list.concat(DEFAULT_ALLOW_LIST).any? { |s| f.include?(s) } }
80
+ unless is_allowed
59
81
  queries = tc[:prosopite_query_holder][location_key]
60
-
61
- unless kaller.any? { |f| f.include?('active_record/validations/uniqueness') }
62
- tc[:prosopite_notifications][queries] = kaller
63
- end
82
+ tc[:prosopite_notifications][queries] = kaller
64
83
  end
65
84
  end
66
85
  end
@@ -105,7 +124,7 @@ module Prosopite
105
124
 
106
125
  query.gsub!(/\btrue\b|\bfalse\b/i, "?")
107
126
 
108
- query.gsub!(/[0-9+-][0-9a-f.xb+-]*/, "?")
127
+ query.gsub!(/[0-9+-][0-9a-f.x+-]*/, "?")
109
128
  query.gsub!(/[xb.+-]\?/, "?")
110
129
 
111
130
  query.strip!
@@ -166,9 +185,9 @@ module Prosopite
166
185
  return if @subscribed
167
186
 
168
187
  ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, _, _, _, data|
169
- sql = data[:sql]
188
+ sql, name = data[:sql], data[:name]
170
189
 
171
- if scan? && sql.include?('SELECT') && data[:cached].nil?
190
+ if scan? && name != "SCHEMA" && sql.include?('SELECT') && data[:cached].nil?
172
191
  location_key = Digest::SHA1.hexdigest(caller.join)
173
192
 
174
193
  tc[:prosopite_query_counter][location_key] += 1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prosopite
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mpampis Kostas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-17 00:00:00.000000000 Z
11
+ date: 2021-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry