isolator 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +11 -3
- data/lib/isolator/adapter_builder.rb +4 -1
- data/lib/isolator/adapters/background_jobs/active_job.rb +6 -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 +4 -4
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c72b8d090e9f2d9f0aa40981298f62bb562d5a1064868f771c2e5cd8af029bc
|
4
|
+
data.tar.gz: 7aef3385898b9db409b4251becfc85f3bb7004d411be4240d8126bb9d9c4d5b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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,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
|
+
}
|
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
@@ -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
|
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:
|
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.
|
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: []
|