isolator 1.0.1 → 1.1.0

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: 8a0299bddb8abe783af8113fcd57b0e9926a1e6f714d29a6ed258b876c9c7062
4
- data.tar.gz: 06551a9aab8237dccf214eae3cf841d96f15c61c4e26b4f623979711ba5e8ddc
3
+ metadata.gz: 0c72b8d090e9f2d9f0aa40981298f62bb562d5a1064868f771c2e5cd8af029bc
4
+ data.tar.gz: 7aef3385898b9db409b4251becfc85f3bb7004d411be4240d8126bb9d9c4d5b7
5
5
  SHA512:
6
- metadata.gz: 1ad13d02cca26c6e0ae19e24be82e8bd08f53904c8adbb134ce0f4dc9faa7375c681c3fa62532d8284f104a97b3f51858e2e5f87c02b089108564e0064b3c5c4
7
- data.tar.gz: 3b02cb4f11b42f6ccfbae0717cf53d5661bc92e211a99bff80b17b4c82fca6cb37b7c905ae98e74b2370c99b7d7f83e1194966b9194c11319cc5473c2ee29ce4
6
+ metadata.gz: eaeff564dc8bb7288b3249325144c60096e35066b994b8ebb7365d8ee949a5b44b47d276eedbcb8580c0d460fa5c46a9d1529e002c0904f04452e96bb02069fc
7
+ data.tar.gz: 6d068fab30b04a15e58afddc1ee23a2a0492051b0d3b9d20784da421aced0d2e1aa548b3ea74b4d9e395c84ff275660baf8ab0fd6825f9f8e9b9c947220b7be3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.0 (2024-08-12)
6
+
7
+ - Add support for `ActiveJob::Base.enqueue_after_transaction_commit`. ([@joshuay03][])
8
+
9
+ - Add `ignore_on: (obj) -> bool` option for adapters. ([@palkan][])
10
+
11
+ - Add ActionCable adapter. ([@arthurWD][])
12
+
5
13
  ## 1.0.1 (2023-12-01) ❄️
6
14
 
7
15
  - Fix Rails 7.0 support. ([@palkan][])
@@ -141,3 +149,5 @@ This, for example, makes Isolator compatible with Rails multi-database apps.
141
149
  [@Mange]: https://github.com/Mange
142
150
  [@tomgi]: https://github.com/tomgi
143
151
  [@tagirahmad]: https://github.com/tagirahmad
152
+ [@arthurWD]: https://github.com/arthurWD
153
+ [@joshuay03]: https://github.com/joshuay03
data/README.md CHANGED
@@ -75,11 +75,16 @@ However, there are some potential caveats:
75
75
 
76
76
  1) Isolator tries to detect the environment automatically and includes only necessary adapters. Thus the order of loading gems matters: make sure that `isolator` is required in the end (NOTE: in Rails, all adapters loaded after application initialization).
77
77
 
78
- 2) Isolator does not distinguish framework-level adapters. For example, `:active_job` spy doesn't take into account which AJ adapter you use; if you are using a safe one (e.g. `Que`) just disable the `:active_job` adapter to avoid false negatives (i.e. `Isolator.adapters.active_job.disable!`).
78
+ 2) Isolator does not distinguish framework-level adapters. For example, `:active_job` spy doesn't take into account which AJ adapter you use; if you are using a safe one (e.g. `Que`) just disable the `:active_job` adapter to avoid false negatives. You can do this by adding an initializer:
79
79
 
80
- 3) Isolator tries to detect the `test` environment and slightly change its behavior: first, it respect _transactional tests_; secondly, error raising is turned on by default (see [below](#configuration)).
80
+ ```rb
81
+ require "active_job/base"
82
+ Isolator.adapters.active_job.disable!
83
+ ```
81
84
 
82
- 4) Experimental [multiple databases](https://guides.rubyonrails.org/active_record_multiple_databases.html) has been added in v0.7.0. Please, let us know if you encounter any issues.
85
+ 4) Isolator tries to detect the `test` environment and slightly change its behavior: first, it respect _transactional tests_; secondly, error raising is turned on by default (see [below](#configuration)).
86
+
87
+ 5) Experimental [multiple databases](https://guides.rubyonrails.org/active_record_multiple_databases.html) has been added in v0.7.0. Please, let us know if you encounter any issues.
83
88
 
84
89
  ### Configuration
85
90
 
@@ -160,6 +165,7 @@ Isolator has a bunch of built-in adapters:
160
165
  - `:sucker_punch`
161
166
  - `:mailer`
162
167
  - `:webmock` – track mocked HTTP requests (unseen by Sniffer) in tests
168
+ - `:action_cable`
163
169
 
164
170
  You can dynamically enable/disable adapters, e.g.:
165
171
 
@@ -172,6 +178,8 @@ Isolator.adapters.http.disable!
172
178
  Isolator.adapters.http.enable!
173
179
  ```
174
180
 
181
+ For `active_job`, be sure to first `require "active_job/base"`.
182
+
175
183
  ### Fix Offenses
176
184
 
177
185
  For the actions that should be executed only after successful transaction commit (which is mostly always so), you can try to use the `after_commit` callback from [after_commit_everywhere] gem (or use native AR callback in models if it's applicable).
@@ -13,6 +13,9 @@ module Isolator
13
13
  self.exception_class = options[:exception_class] if options.key?(:exception_class)
14
14
  self.exception_message = options[:exception_message] if options.key?(:exception_message)
15
15
  self.details_message = options[:details_message] if options.key?(:details_message)
16
+ if options.key?(:ignore_on)
17
+ define_singleton_method(:ignore_on?, &options[:ignore_on])
18
+ end
16
19
  end
17
20
 
18
21
  mod = build_mod(method_name, adapter)
@@ -39,7 +42,7 @@ module Isolator
39
42
  module_eval <<~RUBY, __FILE__, __LINE__ + 1
40
43
  def #{method_name}(...)
41
44
  # check if we are even notifying before calling `caller`, which is well known to be slow
42
- #{adapter_name}.notify(caller, self, ...) if #{adapter_name}.notify?(...)
45
+ #{adapter_name}.notify(caller, self, ...) if #{adapter_name}.notify_on?(self, ...)
43
46
  super
44
47
  end
45
48
  RUBY
@@ -7,4 +7,9 @@ Isolator.isolate :active_job,
7
7
  details_message: ->(obj) {
8
8
  "#{obj.class.name}" \
9
9
  "#{obj.arguments.any? ? " (#{obj.arguments.join(", ")})" : ""}"
10
- }
10
+ },
11
+ ignore_on: ->(job) {
12
+ config = job.class.try(:enqueue_after_transaction_commit)
13
+ config == :always || (config == :default &&
14
+ ActiveJob::Base.queue_adapter.try(:enqueue_after_transaction_commit?) == true)
15
+ }
@@ -27,6 +27,10 @@ module Isolator
27
27
  Isolator.notify(exception: build_exception(obj, args, kwargs), backtrace: backtrace)
28
28
  end
29
29
 
30
+ def notify_on?(obj, *args, **kwargs)
31
+ !ignore_on?(obj) && notify?(*args, **kwargs)
32
+ end
33
+
30
34
  def notify?(...)
31
35
  enabled? && Isolator.enabled? && Isolator.within_transaction? && !ignored?(...)
32
36
  end
@@ -43,6 +47,10 @@ module Isolator
43
47
  ignores.any? { |block| block.call(*args, **kwargs) }
44
48
  end
45
49
 
50
+ def ignore_on?(_obj)
51
+ false
52
+ end
53
+
46
54
  private
47
55
 
48
56
  def build_exception(obj, args, kwargs = {})
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Isolator.isolate :action_cable,
4
+ target: ActionCable::Server::Base,
5
+ method_name: :broadcast,
6
+ exception_class: Isolator::WebsocketError,
7
+ details_message: ->(_obj, args) {
8
+ channel = args.first
9
+
10
+ "Broadcasting to #{channel}"
11
+ }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActiveSupport)
4
+ ActiveSupport.on_load(:action_cable) do
5
+ require "isolator/adapters/websockets/action_cable"
6
+ end
7
+ end
@@ -3,4 +3,5 @@
3
3
  require "isolator/adapters/http"
4
4
  require "isolator/adapters/background_jobs"
5
5
  require "isolator/adapters/mailers"
6
+ require "isolator/adapters/websockets"
6
7
  require "isolator/adapters/after_commit" if defined?(::TestAfterCommit)
@@ -22,4 +22,8 @@ module Isolator # :nodoc: all
22
22
  class MailerError < UnsafeOperationError
23
23
  MESSAGE = "You are trying to send email inside db transaction."
24
24
  end
25
+
26
+ class WebsocketError < UnsafeOperationError
27
+ MESSAGE = "You are trying to broadcast to a websocket connection inside db transaction. "
28
+ end
25
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Isolator
4
- VERSION = "1.0.1"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/isolator.rb CHANGED
@@ -111,20 +111,20 @@ module Isolator
111
111
 
112
112
  def incr_thresholds!
113
113
  self.default_threshold += 1
114
+ debug!("Thresholds were incremented")
115
+
114
116
  return unless state[:thresholds]
115
117
 
116
118
  state[:thresholds].transform_values!(&:succ)
117
-
118
- debug!("Thresholds were incremented")
119
119
  end
120
120
 
121
121
  def decr_thresholds!
122
122
  self.default_threshold -= 1
123
+ debug!("Thresholds were incremented")
124
+
123
125
  return unless state[:thresholds]
124
126
 
125
127
  state[:thresholds].transform_values!(&:pred)
126
-
127
- debug!("Thresholds were decremented")
128
128
  end
129
129
 
130
130
  def incr_transactions!(connection_id = default_connection_id.call)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isolator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sniffer
@@ -302,6 +302,8 @@ files:
302
302
  - lib/isolator/adapters/http/webmock.rb
303
303
  - lib/isolator/adapters/mailers.rb
304
304
  - lib/isolator/adapters/mailers/mail.rb
305
+ - lib/isolator/adapters/websockets.rb
306
+ - lib/isolator/adapters/websockets/action_cable.rb
305
307
  - lib/isolator/callbacks.rb
306
308
  - lib/isolator/configuration.rb
307
309
  - lib/isolator/database_cleaner_support.rb
@@ -329,7 +331,7 @@ metadata:
329
331
  homepage_uri: http://github.com/palkan/isolator
330
332
  source_code_uri: http://github.com/palkan/isolator
331
333
  funding_uri: https://github.com/sponsors/palkan
332
- post_install_message:
334
+ post_install_message:
333
335
  rdoc_options: []
334
336
  require_paths:
335
337
  - lib
@@ -344,8 +346,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
344
346
  - !ruby/object:Gem::Version
345
347
  version: '0'
346
348
  requirements: []
347
- rubygems_version: 3.4.20
348
- signing_key:
349
+ rubygems_version: 3.4.19
350
+ signing_key:
349
351
  specification_version: 4
350
352
  summary: Detect non-atomic interactions within DB transactions
351
353
  test_files: []