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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +11 -3
- data/lib/isolator/adapter_builder.rb +4 -1
- data/lib/isolator/adapters/background_jobs/active_job.rb +5 -1
- data/lib/isolator/adapters/base.rb +8 -0
- data/lib/isolator/adapters/websockets/action_cable.rb +11 -0
- data/lib/isolator/adapters/websockets.rb +7 -0
- data/lib/isolator/adapters.rb +1 -0
- data/lib/isolator/errors.rb +4 -0
- data/lib/isolator/version.rb +1 -1
- data/lib/isolator.rb +5 -5
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84829cfcac568cd691333a7d2e36d7413414c0aaf3c1980a5445725ee35b3506
|
4
|
+
data.tar.gz: 4cda5f918834344df2fa05ecec3e60869cc191d8802b5563f8e653d954ea01d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
80
|
+
```rb
|
81
|
+
require "active_job/base"
|
82
|
+
Isolator.adapters.active_job.disable!
|
83
|
+
```
|
81
84
|
|
82
|
-
4)
|
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}.
|
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
|
+
}
|
data/lib/isolator/adapters.rb
CHANGED
data/lib/isolator/errors.rb
CHANGED
@@ -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
|
data/lib/isolator/version.rb
CHANGED
data/lib/isolator.rb
CHANGED
@@ -20,7 +20,7 @@ module Isolator
|
|
20
20
|
class ThreadStateProxy
|
21
21
|
attr_reader :prefix
|
22
22
|
|
23
|
-
def
|
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.
|
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:
|
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.
|
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.
|
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.
|
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
|