isolator 0.7.0 → 0.9.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +1 -1
- data/README.md +69 -7
- data/lib/isolator/adapter_builder.rb +27 -17
- data/lib/isolator/adapters/background_jobs/active_job.rb +1 -1
- data/lib/isolator/adapters/base.rb +28 -9
- data/lib/isolator/adapters/http/webmock.rb +1 -1
- data/lib/isolator/adapters/mailers/mail.rb +1 -1
- data/lib/isolator/configuration.rb +2 -2
- data/lib/isolator/ignorer.rb +19 -4
- data/lib/isolator/isolate.rb +7 -1
- data/lib/isolator/notifier.rb +3 -3
- data/lib/isolator/railtie.rb +13 -1
- data/lib/isolator/version.rb +1 -1
- data/lib/isolator.rb +11 -0
- metadata +38 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 529433e0e838e663f335a5fb493f51d10f16fbde2168c89be72e92c968709593
|
4
|
+
data.tar.gz: ef33db058e25204e615fae7ee945c738e516e8ae6d63bb93f9660e6e117cb632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cb63aa9a96f5931425267193590550cac0614dd15d272bd7d33f7e2aeaad0b7b37a19f5a6f7d8617dce992e946b92c42c3df5829177cbd51b41d8919abdc8c5
|
7
|
+
data.tar.gz: b4997855a9d813a961491235097a42eee75d55598fb7d33d53bb4f7e3828f486ea0a2fb788edd028237e39518a2d8e962824b08a3f4cbed2ce3ac22acdfee9c3
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.9.0 (2023-05-18)
|
6
|
+
|
7
|
+
- Support keyword arguments to isolated method in Ruby 3.0. ([@Mange][])
|
8
|
+
- Raise an error when an ignore file does not parse to a hash. ([@bobbymcwho][])
|
9
|
+
- Log all filtered backtrace lines to the logger ([@bobbymcwho][])
|
10
|
+
- Add support for removing dynamic adapters. ([@Mange][])
|
11
|
+
- Allow aliases in .isolator_todo.yml and .isolator_ignore.yml ([@tomgi][])
|
12
|
+
|
13
|
+
## 0.8.0 (2021-12-29)
|
14
|
+
|
15
|
+
- Drop Ruby 2.5 support.
|
16
|
+
|
17
|
+
- Add .isolator_ignore.yml configuration file for Rails application.
|
18
|
+
|
5
19
|
## 0.7.0 (2020-09-25)
|
6
20
|
|
7
21
|
- Add debug mode. ([@palkan][])
|
@@ -93,3 +107,5 @@ This, for example, makes Isolator compatible with Rails multi-database apps.
|
|
93
107
|
[@shivanshgaur]: https://github.com/shivanshgaur
|
94
108
|
[@iiwo]: https://github.com/iiwo
|
95
109
|
[@mquan]: https://github.com/mquan
|
110
|
+
[@bobbymcwho]: https://github.com/bobbymcwho
|
111
|
+
[@Mange]: https://github.com/Mange
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2018-
|
3
|
+
Copyright (c) 2018-2023 Vladimir Dementyev
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -104,24 +104,24 @@ Isolator.configure do |config|
|
|
104
104
|
end
|
105
105
|
```
|
106
106
|
|
107
|
-
Isolator
|
107
|
+
Isolator relies on [uniform_notifier][] to send custom notifications.
|
108
108
|
|
109
109
|
**NOTE:** `uniform_notifier` should be installed separately (i.e., added to Gemfile).
|
110
110
|
|
111
111
|
### Transactional tests support
|
112
112
|
|
113
|
-
- Rails' baked-in [use_transactional_tests](api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html#class-ActiveRecord::FixtureSet-label-Transactional+Tests)
|
113
|
+
- Rails' baked-in [use_transactional_tests](https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html#class-ActiveRecord::FixtureSet-label-Transactional+Tests)
|
114
114
|
- [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner) gem. Make sure that you require isolator _after_ database_cleaner.
|
115
115
|
|
116
116
|
### Supported ORMs
|
117
117
|
|
118
|
-
- `ActiveRecord` >= 4.
|
118
|
+
- `ActiveRecord` >= 5.1 (4.2 likely till works, but we do not test against it anymore)
|
119
119
|
- `ROM::SQL` (only if Active Support instrumentation extension is loaded)
|
120
120
|
|
121
121
|
### Adapters
|
122
122
|
|
123
123
|
Isolator has a bunch of built-in adapters:
|
124
|
-
- `:http` –
|
124
|
+
- `:http` – built on top of [Sniffer][]
|
125
125
|
- `:active_job`
|
126
126
|
- `:sidekiq`
|
127
127
|
- `:resque`
|
@@ -159,9 +159,32 @@ Isolator.adapters.sidekiq.ignore_if { Thread.current[:sidekiq_postpone] }
|
|
159
159
|
|
160
160
|
You can add as many _ignores_ as you want, the offense is registered iff all of them return false.
|
161
161
|
|
162
|
+
|
163
|
+
### Using with sidekiq/testing
|
164
|
+
|
165
|
+
If you require sidekiq/testing in your tests after isolator is required then it will blow away isolator's hooks, so you need to require isolator after requiring sidekiq/testing.
|
166
|
+
|
167
|
+
If you're using Rails and want to use isolator in development and staging, then here is a way to do this.
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
|
171
|
+
# Gemfile
|
172
|
+
gem "isolator", require: false # so it delays loading till after sidekiq/testing
|
173
|
+
|
174
|
+
# config/initializers/isolator.rb
|
175
|
+
require "sidekiq/testing" if Rails.env.test?
|
176
|
+
|
177
|
+
unless Rails.env.production? # so we get it in staging too
|
178
|
+
require "isolator"
|
179
|
+
Isolator.configure do |config|
|
180
|
+
config.send_notifications = true # ...
|
181
|
+
end
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
162
185
|
### Using with legacy Rails codebases
|
163
186
|
|
164
|
-
If you already have a huge Rails project it can be
|
187
|
+
If you already have a huge Rails project it can be tricky to turn Isolator on because you'll immediately get a lot of failed specs. If you want to fix detected issues one by one, you can list all of them in the special files `.isolator_todo.yml` and `.isolator_ignore.yml` in the following way:
|
165
188
|
|
166
189
|
```
|
167
190
|
sidekiq:
|
@@ -169,8 +192,20 @@ sidekiq:
|
|
169
192
|
- app/models/sales/**/*.rb
|
170
193
|
```
|
171
194
|
|
195
|
+
You can ignore the same files in multiple adapters using YML aliases in the following way:
|
196
|
+
|
197
|
+
```
|
198
|
+
http_common: &http_common
|
199
|
+
- app/models/user.rb:20
|
200
|
+
|
201
|
+
http: *http_common
|
202
|
+
webmock: *http_common
|
203
|
+
```
|
204
|
+
|
172
205
|
All the exceptions raised in the listed lines will be ignored.
|
173
206
|
|
207
|
+
The `.isolator_todo.yml` file is intended to point to the code that should be fixed later, and `.isolator_ignore.yml` points to the code that for some reasons is not expected to be fixed. (See https://github.com/palkan/isolator/issues/40)
|
208
|
+
|
174
209
|
### Using with legacy Ruby codebases
|
175
210
|
|
176
211
|
If you are not using Rails, you'll have to load ignores from file manually, using `Isolator::Ignorer.prepare(path:)`, for instance `Isolator::Ignorer.prepare(path: "./config/.isolator_todo.yml")`
|
@@ -196,16 +231,43 @@ Isolator.isolate :danger, Danger.singleton_class, :explode, options
|
|
196
231
|
Possible `options` are:
|
197
232
|
- `exception_class` – an exception class to raise in case of offense
|
198
233
|
- `exception_message` – custom exception message (could be specified without a class)
|
199
|
-
- `details_message` – a block to generate additional
|
234
|
+
- `details_message` – a block to generate additional exception message information:
|
200
235
|
|
201
236
|
```ruby
|
202
237
|
Isolator.isolate :active_job,
|
203
238
|
target: ActiveJob::Base,
|
204
239
|
method_name: :enqueue,
|
205
240
|
exception_class: Isolator::BackgroundJobError,
|
206
|
-
details_message: ->(obj
|
241
|
+
details_message: ->(obj) {
|
207
242
|
"#{obj.class.name}(#{obj.arguments})"
|
208
243
|
}
|
244
|
+
|
245
|
+
Isolator.isolate :promoter,
|
246
|
+
target: UserPromoter,
|
247
|
+
method_name: :call,
|
248
|
+
details_message: ->(obj_, args, kwargs) {
|
249
|
+
# UserPromoter.call(user, role, by: nil)
|
250
|
+
user, role = args
|
251
|
+
by = kwargs[:by]
|
252
|
+
"#{user.name} promoted to #{role} by #{by&.name || "system"})"
|
253
|
+
}
|
254
|
+
```
|
255
|
+
|
256
|
+
Trying to register the same adapter name twice will raise an error. You can guard for it, or remove old adapters before in order to replace them.
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
unless Isolator.has_adapter?(:promoter)
|
260
|
+
Isolator.isolate(:promoter, *rest)
|
261
|
+
end
|
262
|
+
```
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
# Handle code reloading
|
266
|
+
class Messager
|
267
|
+
end
|
268
|
+
|
269
|
+
Isolator.remove_adapter(:messager)
|
270
|
+
Isolator.isolate(:messager, target: Messager, **rest)
|
209
271
|
```
|
210
272
|
|
211
273
|
You can also add some callbacks to be run before and after the transaction:
|
@@ -5,29 +5,39 @@ require "isolator/adapters/base"
|
|
5
5
|
module Isolator
|
6
6
|
# Builds adapter from provided params
|
7
7
|
module AdapterBuilder
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
class << self
|
9
|
+
def call(target: nil, method_name: nil, **options)
|
10
|
+
adapter = Module.new do
|
11
|
+
extend Isolator::Adapters::Base
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
self.exception_class = options[:exception_class] if options.key?(:exception_class)
|
14
|
+
self.exception_message = options[:exception_message] if options.key?(:exception_message)
|
15
|
+
self.details_message = options[:details_message] if options.key?(:details_message)
|
16
|
+
end
|
17
|
+
|
18
|
+
mod = build_mod(method_name, adapter)
|
19
|
+
if target && mod
|
20
|
+
target.prepend(mod)
|
21
|
+
adapter.define_singleton_method(:restore) do
|
22
|
+
mod.remove_method(method_name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
adapter
|
15
27
|
end
|
16
28
|
|
17
|
-
|
18
|
-
|
19
|
-
adapter
|
20
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def build_mod(method_name, adapter)
|
32
|
+
return nil unless method_name
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
34
|
+
Module.new do
|
35
|
+
define_method method_name do |*args, **kwargs, &block|
|
36
|
+
adapter.notify(caller, self, *args, **kwargs)
|
37
|
+
super(*args, **kwargs, &block)
|
38
|
+
end
|
27
39
|
end
|
28
40
|
end
|
29
|
-
|
30
|
-
base.prepend mod
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end
|
@@ -4,7 +4,7 @@ Isolator.isolate :active_job,
|
|
4
4
|
target: ActiveJob::Base,
|
5
5
|
method_name: :enqueue,
|
6
6
|
exception_class: Isolator::BackgroundJobError,
|
7
|
-
details_message: ->(obj
|
7
|
+
details_message: ->(obj) {
|
8
8
|
"#{obj.class.name}" \
|
9
9
|
"#{obj.arguments.any? ? " (#{obj.arguments.join(", ")})" : ""}"
|
10
10
|
}
|
@@ -22,13 +22,13 @@ module Isolator
|
|
22
22
|
@disabled == true
|
23
23
|
end
|
24
24
|
|
25
|
-
def notify(backtrace, obj, *args)
|
26
|
-
return unless notify?(*args)
|
27
|
-
Isolator.notify(exception: build_exception(obj, args), backtrace: backtrace)
|
25
|
+
def notify(backtrace, obj, *args, **kwargs)
|
26
|
+
return unless notify?(*args, **kwargs)
|
27
|
+
Isolator.notify(exception: build_exception(obj, args, kwargs), backtrace: backtrace)
|
28
28
|
end
|
29
29
|
|
30
|
-
def notify?(*args)
|
31
|
-
enabled? && Isolator.enabled? && Isolator.within_transaction? && !ignored?(*args)
|
30
|
+
def notify?(*args, **kwargs)
|
31
|
+
enabled? && Isolator.enabled? && Isolator.within_transaction? && !ignored?(*args, **kwargs)
|
32
32
|
end
|
33
33
|
|
34
34
|
def ignore_if(&block)
|
@@ -39,17 +39,36 @@ module Isolator
|
|
39
39
|
@ignores ||= []
|
40
40
|
end
|
41
41
|
|
42
|
-
def ignored?(*args)
|
43
|
-
ignores.any? { |block| block.call(*args) }
|
42
|
+
def ignored?(*args, **kwargs)
|
43
|
+
ignores.any? { |block| block.call(*args, **kwargs) }
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
-
def build_exception(obj, args)
|
48
|
+
def build_exception(obj, args, kwargs = {})
|
49
49
|
klass = exception_class || Isolator::UnsafeOperationError
|
50
|
-
details =
|
50
|
+
details = build_details(obj, args, kwargs)
|
51
51
|
klass.new(exception_message, details: details)
|
52
52
|
end
|
53
|
+
|
54
|
+
def build_details(obj, args, kwargs)
|
55
|
+
return nil unless details_message
|
56
|
+
|
57
|
+
case details_message.arity
|
58
|
+
when 2, -2
|
59
|
+
# Older users of details_message expected only two arguments. Add
|
60
|
+
# kwargs hash as last argument, like in older Ruby.
|
61
|
+
details_message.call(obj, args + [kwargs])
|
62
|
+
when 3, -3
|
63
|
+
# New signature separates args from kwargs
|
64
|
+
details_message.call(obj, args, kwargs)
|
65
|
+
when 1
|
66
|
+
# Callback does not care about any args
|
67
|
+
details_message.call(obj)
|
68
|
+
else
|
69
|
+
raise "Unexpected arity (#{details_message.arity}) for #{details_message.inspect}"
|
70
|
+
end
|
71
|
+
end
|
53
72
|
end
|
54
73
|
end
|
55
74
|
end
|
@@ -28,8 +28,8 @@ module Isolator
|
|
28
28
|
@ignorer = Isolator::Ignorer
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
alias_method :raise_exceptions?, :raise_exceptions
|
32
|
+
alias_method :send_notifications?, :send_notifications
|
33
33
|
|
34
34
|
def test_env?
|
35
35
|
ENV["RACK_ENV"] == "test" || ENV["RAILS_ENV"] == "test"
|
data/lib/isolator/ignorer.rb
CHANGED
@@ -3,16 +3,31 @@
|
|
3
3
|
module Isolator
|
4
4
|
# Handle ignoring isolator errors using a yml file
|
5
5
|
class Ignorer
|
6
|
-
|
6
|
+
class ParseError < StandardError
|
7
|
+
def initialize(file_path, klass)
|
8
|
+
@file_path = file_path
|
9
|
+
@klass = klass
|
10
|
+
end
|
11
|
+
|
12
|
+
def message
|
13
|
+
"Unable to parse ignore config file #{@file_path}. Expected Hash, got #{@klass}."
|
14
|
+
end
|
15
|
+
end
|
7
16
|
|
8
17
|
class << self
|
9
|
-
def prepare(path
|
18
|
+
def prepare(path:, regex_string: "^.*(#ignores#):.*$")
|
10
19
|
return unless File.exist?(path)
|
11
20
|
|
12
|
-
|
21
|
+
ignores = begin
|
22
|
+
YAML.load_file(path, aliases: true)
|
23
|
+
rescue ArgumentError # support for older rubies https://github.com/rails/rails/commit/179d0a1f474ada02e0030ac3bd062fc653765dbe
|
24
|
+
YAML.load_file(path)
|
25
|
+
end
|
26
|
+
|
27
|
+
raise ParseError.new(path, ignores.class) unless ignores.respond_to?(:fetch)
|
13
28
|
|
14
29
|
Isolator.adapters.each do |id, adapter|
|
15
|
-
ignored_paths =
|
30
|
+
ignored_paths = ignores.fetch(id, [])
|
16
31
|
AdapterIgnore.new(adapter: adapter, ignored_paths: ignored_paths, regex_string: regex_string).prepare
|
17
32
|
end
|
18
33
|
end
|
data/lib/isolator/isolate.rb
CHANGED
@@ -4,9 +4,15 @@ module Isolator
|
|
4
4
|
# Add .isolate function to build and register adapters
|
5
5
|
module Isolate
|
6
6
|
def isolate(id, **options)
|
7
|
-
raise "Adapter already registered: #{id}" if Isolator.
|
7
|
+
raise "Adapter already registered: #{id}" if Isolator.has_adapter?(id)
|
8
8
|
adapter = AdapterBuilder.call(**options)
|
9
9
|
Isolator.adapters[id.to_s] = adapter
|
10
10
|
end
|
11
|
+
|
12
|
+
def remove_adapter(id)
|
13
|
+
if (adapter = Isolator.adapters.delete(id.to_s))
|
14
|
+
adapter.restore if adapter.respond_to?(:restore)
|
15
|
+
end
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
data/lib/isolator/notifier.rb
CHANGED
@@ -29,12 +29,12 @@ module Isolator
|
|
29
29
|
def log_exception
|
30
30
|
return unless Isolator.config.logger
|
31
31
|
|
32
|
-
offense_line = filtered_backtrace.first
|
33
|
-
|
34
32
|
msg = "[ISOLATOR EXCEPTION]\n" \
|
35
33
|
"#{exception.message}"
|
36
34
|
|
37
|
-
|
35
|
+
filtered_backtrace.each do |offense_line|
|
36
|
+
msg += "\n ↳ #{offense_line}"
|
37
|
+
end
|
38
38
|
|
39
39
|
Isolator.config.logger.warn(msg)
|
40
40
|
end
|
data/lib/isolator/railtie.rb
CHANGED
@@ -15,7 +15,19 @@ module Isolator
|
|
15
15
|
# (when all deps are likely to be loaded).
|
16
16
|
load File.join(__dir__, "adapters.rb")
|
17
17
|
|
18
|
-
|
18
|
+
# Try to load Rails base classes to trigger their load hooks
|
19
|
+
begin
|
20
|
+
::ActionMailer::Base
|
21
|
+
rescue NameError
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
::ActiveJob::Base
|
26
|
+
rescue NameError
|
27
|
+
end
|
28
|
+
|
29
|
+
Isolator.config.ignorer&.prepare(path: ".isolator_todo.yml")
|
30
|
+
Isolator.config.ignorer&.prepare(path: ".isolator_ignore.yml")
|
19
31
|
|
20
32
|
next unless Rails.env.test?
|
21
33
|
|
data/lib/isolator/version.rb
CHANGED
data/lib/isolator.rb
CHANGED
@@ -135,6 +135,13 @@ module Isolator
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def decr_transactions!(connection_id = default_connection_id.call)
|
138
|
+
current = state[:transactions]&.[](connection_id) || 0
|
139
|
+
|
140
|
+
if current <= 0
|
141
|
+
warn "Trying to finalize an untracked transaction"
|
142
|
+
return
|
143
|
+
end
|
144
|
+
|
138
145
|
state[:transactions][connection_id] -= 1
|
139
146
|
|
140
147
|
finish! if current_transactions(connection_id) == (connection_threshold(connection_id) - 1)
|
@@ -167,6 +174,10 @@ module Isolator
|
|
167
174
|
@adapters ||= Isolator::SimpleHashie.new
|
168
175
|
end
|
169
176
|
|
177
|
+
def has_adapter?(id)
|
178
|
+
adapters.key?(id.to_s)
|
179
|
+
end
|
180
|
+
|
170
181
|
def load_ignore_config(path)
|
171
182
|
warn "[DEPRECATION] `load_ignore_config` is deprecated. Please use `Isolator::Ignorer.prepare` instead."
|
172
183
|
Isolator::Ignorer.prepare(path: path)
|
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: 0.
|
4
|
+
version: 0.9.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: 2023-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sniffer
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.5.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.5.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -248,6 +248,34 @@ dependencies:
|
|
248
248
|
- - ">="
|
249
249
|
- !ruby/object:Gem::Version
|
250
250
|
version: '0'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: webrick
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - ">="
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: net-smtp
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
251
279
|
description: Detect non-atomic interactions within DB transactions
|
252
280
|
email:
|
253
281
|
- dementiev.vm@gmail.com
|
@@ -298,7 +326,8 @@ metadata:
|
|
298
326
|
documentation_uri: http://github.com/palkan/isolator
|
299
327
|
homepage_uri: http://github.com/palkan/isolator
|
300
328
|
source_code_uri: http://github.com/palkan/isolator
|
301
|
-
|
329
|
+
funding_uri: https://github.com/sponsors/palkan
|
330
|
+
post_install_message:
|
302
331
|
rdoc_options: []
|
303
332
|
require_paths:
|
304
333
|
- lib
|
@@ -306,15 +335,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
306
335
|
requirements:
|
307
336
|
- - ">="
|
308
337
|
- !ruby/object:Gem::Version
|
309
|
-
version: 2.
|
338
|
+
version: 2.6.0
|
310
339
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
311
340
|
requirements:
|
312
341
|
- - ">="
|
313
342
|
- !ruby/object:Gem::Version
|
314
343
|
version: '0'
|
315
344
|
requirements: []
|
316
|
-
rubygems_version: 3.
|
317
|
-
signing_key:
|
345
|
+
rubygems_version: 3.4.8
|
346
|
+
signing_key:
|
318
347
|
specification_version: 4
|
319
348
|
summary: Detect non-atomic interactions within DB transactions
|
320
349
|
test_files: []
|