isolator 1.0.1 → 1.1.1

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: 84829cfcac568cd691333a7d2e36d7413414c0aaf3c1980a5445725ee35b3506
4
+ data.tar.gz: 4cda5f918834344df2fa05ecec3e60869cc191d8802b5563f8e653d954ea01d7
5
5
  SHA512:
6
- metadata.gz: 1ad13d02cca26c6e0ae19e24be82e8bd08f53904c8adbb134ce0f4dc9faa7375c681c3fa62532d8284f104a97b3f51858e2e5f87c02b089108564e0064b3c5c4
7
- data.tar.gz: 3b02cb4f11b42f6ccfbae0717cf53d5661bc92e211a99bff80b17b4c82fca6cb37b7c905ae98e74b2370c99b7d7f83e1194966b9194c11319cc5473c2ee29ce4
6
+ metadata.gz: f152a5a36394be2a010535ac14511b66cafeaeaa65e079e05f8ab2b4849992a5dbbe07ef212a1b150fd6a5cd9297527dbbed671937839413ed8e6e26b946db7b
7
+ data.tar.gz: ef341ee673b9463893ac903a89b4ffb68967dc9fd8422f04d2717904a2e4338bc1a819157f3435749b5c1f65892b963454c05fd0a54908704e447bfc025701b5
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.1.1 (2025-03-12)
6
+
7
+ - Fix handling Rails 8 `enqueue_after_transaction_commit` logic. ([@palkan][])
8
+
9
+ ## 1.1.0 (2024-08-12)
10
+
11
+ - Add support for `ActiveJob::Base.enqueue_after_transaction_commit`. ([@joshuay03][])
12
+
13
+ - Add `ignore_on: (obj) -> bool` option for adapters. ([@palkan][])
14
+
15
+ - Add ActionCable adapter. ([@arthurWD][])
16
+
5
17
  ## 1.0.1 (2023-12-01) ❄️
6
18
 
7
19
  - Fix Rails 7.0 support. ([@palkan][])
@@ -141,3 +153,5 @@ This, for example, makes Isolator compatible with Rails multi-database apps.
141
153
  [@Mange]: https://github.com/Mange
142
154
  [@tomgi]: https://github.com/tomgi
143
155
  [@tagirahmad]: https://github.com/tagirahmad
156
+ [@arthurWD]: https://github.com/arthurWD
157
+ [@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,8 @@ 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 == true
14
+ }
@@ -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.1"
5
5
  end
data/lib/isolator.rb CHANGED
@@ -20,7 +20,7 @@ module Isolator
20
20
  class ThreadStateProxy
21
21
  attr_reader :prefix
22
22
 
23
- def initilize(prefix = "isolator_")
23
+ def initialize(prefix = "isolator_")
24
24
  @prefix = prefix
25
25
  end
26
26
 
@@ -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.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2025-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sniffer
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 5.10.0
89
+ version: '5.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 5.10.0
96
+ version: '5.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: sidekiq
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -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
@@ -344,7 +346,7 @@ 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
349
+ rubygems_version: 3.4.19
348
350
  signing_key:
349
351
  specification_version: 4
350
352
  summary: Detect non-atomic interactions within DB transactions