isolator 0.6.0 → 0.8.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 +35 -0
- data/LICENSE.txt +1 -1
- data/README.md +36 -16
- data/lib/isolator/adapters/background_jobs/active_job.rb +7 -7
- data/lib/isolator/adapters/background_jobs/resque.rb +6 -6
- data/lib/isolator/adapters/background_jobs/resque_scheduler.rb +6 -6
- data/lib/isolator/adapters/background_jobs/sidekiq.rb +8 -8
- data/lib/isolator/adapters/background_jobs/sucker_punch.rb +6 -6
- data/lib/isolator/adapters/base.rb +2 -2
- data/lib/isolator/adapters/http/sniffer.rb +1 -1
- data/lib/isolator/adapters/http/webmock.rb +4 -4
- data/lib/isolator/configuration.rb +11 -5
- data/lib/isolator/ignorer.rb +41 -21
- data/lib/isolator/isolate.rb +1 -1
- data/lib/isolator/orm_adapters/active_support_subscriber.rb +3 -2
- data/lib/isolator/railtie.rb +12 -5
- data/lib/isolator/version.rb +1 -1
- data/lib/isolator.rb +132 -18
- metadata +85 -51
- data/.gitignore +0 -13
- data/.rubocop.yml +0 -70
- data/.travis.yml +0 -35
- data/Gemfile +0 -20
- data/Rakefile +0 -8
- data/bin/console +0 -7
- data/bin/setup +0 -8
- data/gemfiles/activerecord42.gemfile +0 -7
- data/gemfiles/jruby.gemfile +0 -8
- data/gemfiles/rails6.gemfile +0 -7
- data/gemfiles/railsmaster.gemfile +0 -7
- data/gemfiles/ruby_2.2.2.gemfile +0 -8
- data/isolator.gemspec +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c40700b0b2f7e5025ed7cbfb80580ac9ee1516a1295146bf0fa9db1de6e2a7f
|
4
|
+
data.tar.gz: 7d605d3790733c0b1bcd44e6188c30050900879042ef604950cc38b36d6214d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3a05d4ccad1f80171a67f0f124cb2d37548803a5451338cb9d821c16042dc94c407f9a4a155597742268cbf8ee939594a166c49835f35f5f4d2ec4d1d9a0567
|
7
|
+
data.tar.gz: a287d291ca6465f3c8acfc8cb8c1c5ba898315c6aae80156855153d13a3c7c763864d97127ef38b04331bb7c99b23b417783eada86afdf8c26282c694dfe22bd
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,39 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.8.0 (2021-12-29)
|
6
|
+
|
7
|
+
- Drop Ruby 2.5 support.
|
8
|
+
|
9
|
+
- Add .isolator_ignore.yml configuration file for Rails application.
|
10
|
+
|
11
|
+
## 0.7.0 (2020-09-25)
|
12
|
+
|
13
|
+
- Add debug mode. ([@palkan][])
|
14
|
+
|
15
|
+
Use `ISOLATOR_DEBUG=true` to turn on debug mode, which prints some useful information: when a transaction is tracked,
|
16
|
+
thresholds are changed, etc.
|
17
|
+
|
18
|
+
- Track transactions for different connections independently. ([@mquan][], [@palkan][])
|
19
|
+
|
20
|
+
This, for example, makes Isolator compatible with Rails multi-database apps.
|
21
|
+
|
22
|
+
- Allow custom ignorer usage. ([@iiwo][])
|
23
|
+
|
24
|
+
- `Isolator.load_ignore_config` is deprecated in favor of `Isolator::Ignorer.prepare`. ([@iiwo][])
|
25
|
+
|
26
|
+
## 0.6.2 (2020-03-20)
|
27
|
+
|
28
|
+
- Make Sniffer version requirement open-ended. ([@palkan][])
|
29
|
+
|
30
|
+
- **Support Ruby 2.5+** ([@palkan][])
|
31
|
+
|
32
|
+
## 0.6.1 (2019-09-06)
|
33
|
+
|
34
|
+
- Fix Sniffer integration. ([@palkan][])
|
35
|
+
|
36
|
+
Fixes [#21](https://github.com/palkan/isolator/issues/21).
|
37
|
+
|
5
38
|
## 0.6.0 (2019-04-12) 🚀
|
6
39
|
|
7
40
|
- Add support for exceptions message details. ([@palkan][])
|
@@ -64,3 +97,5 @@
|
|
64
97
|
[@Envek]: https://github.com/Envek
|
65
98
|
[@DmitryTsepelev]: https://github.com/DmitryTsepelev
|
66
99
|
[@shivanshgaur]: https://github.com/shivanshgaur
|
100
|
+
[@iiwo]: https://github.com/iiwo
|
101
|
+
[@mquan]: https://github.com/mquan
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2018 Vladimir Dementyev
|
3
|
+
Copyright (c) 2018-2020 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
@@ -1,6 +1,6 @@
|
|
1
1
|
[](http://cultofmartians.com/tasks/isolator.html)
|
2
2
|
[](https://badge.fury.io/rb/isolator)
|
3
|
-
|
3
|
+

|
4
4
|
|
5
5
|
# Isolator
|
6
6
|
|
@@ -79,6 +79,8 @@ However, there are some potential caveats:
|
|
79
79
|
|
80
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)).
|
81
81
|
|
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.
|
83
|
+
|
82
84
|
### Configuration
|
83
85
|
|
84
86
|
```ruby
|
@@ -95,10 +97,14 @@ Isolator.configure do |config|
|
|
95
97
|
# Customize backtrace filtering (provide a callable)
|
96
98
|
# By default, just takes the top-5 lines
|
97
99
|
config.backtrace_filter = ->(backtrace) { backtrace.take(5) }
|
100
|
+
|
101
|
+
# Define a custom ignorer class (must implement .prepare)
|
102
|
+
# uses a row number based list from the .isolator_todo.yml file
|
103
|
+
config.ignorer = Isolator::Ignorer
|
98
104
|
end
|
99
105
|
```
|
100
106
|
|
101
|
-
Isolator
|
107
|
+
Isolator relies on [uniform_notifier][] to send custom notifications.
|
102
108
|
|
103
109
|
**NOTE:** `uniform_notifier` should be installed separately (i.e., added to Gemfile).
|
104
110
|
|
@@ -109,13 +115,13 @@ Isolator relys on [uniform_notifier][] to send custom notifications.
|
|
109
115
|
|
110
116
|
### Supported ORMs
|
111
117
|
|
112
|
-
- `ActiveRecord` >= 4.
|
113
|
-
- `ROM::SQL` (only if Active Support instrumentation
|
118
|
+
- `ActiveRecord` >= 5.1 (4.2 likely till works, but we do not test against it anymore)
|
119
|
+
- `ROM::SQL` (only if Active Support instrumentation extension is loaded)
|
114
120
|
|
115
121
|
### Adapters
|
116
122
|
|
117
123
|
Isolator has a bunch of built-in adapters:
|
118
|
-
- `:http` –
|
124
|
+
- `:http` – built on top of [Sniffer][]
|
119
125
|
- `:active_job`
|
120
126
|
- `:sidekiq`
|
121
127
|
- `:resque`
|
@@ -155,7 +161,7 @@ You can add as many _ignores_ as you want, the offense is registered iff all of
|
|
155
161
|
|
156
162
|
### Using with legacy Rails codebases
|
157
163
|
|
158
|
-
If you already have a huge Rails project it can be
|
164
|
+
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:
|
159
165
|
|
160
166
|
```
|
161
167
|
sidekiq:
|
@@ -165,9 +171,11 @@ sidekiq:
|
|
165
171
|
|
166
172
|
All the exceptions raised in the listed lines will be ignored.
|
167
173
|
|
174
|
+
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)
|
175
|
+
|
168
176
|
### Using with legacy Ruby codebases
|
169
177
|
|
170
|
-
If you are not using Rails, you'll have to load ignores from file manually, using `Isolator
|
178
|
+
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")`
|
171
179
|
|
172
180
|
## Custom Adapters
|
173
181
|
|
@@ -183,23 +191,23 @@ Suppose that you have a class `Danger` with a method `#explode`, which is not sa
|
|
183
191
|
# the third one is a method name.
|
184
192
|
Isolator.isolate :danger, Danger, :explode, options
|
185
193
|
|
186
|
-
# NOTE: if you want to isolate a class method, use
|
194
|
+
# NOTE: if you want to isolate a class method, use singleton_class instead
|
187
195
|
Isolator.isolate :danger, Danger.singleton_class, :explode, options
|
188
196
|
```
|
189
197
|
|
190
198
|
Possible `options` are:
|
191
199
|
- `exception_class` – an exception class to raise in case of offense
|
192
200
|
- `exception_message` – custom exception message (could be specified without a class)
|
193
|
-
- `details_message` – a block to generate additional
|
201
|
+
- `details_message` – a block to generate additional exception message information:
|
194
202
|
|
195
203
|
```ruby
|
196
204
|
Isolator.isolate :active_job,
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
205
|
+
target: ActiveJob::Base,
|
206
|
+
method_name: :enqueue,
|
207
|
+
exception_class: Isolator::BackgroundJobError,
|
208
|
+
details_message: ->(obj, _args) {
|
209
|
+
"#{obj.class.name}(#{obj.arguments})"
|
210
|
+
}
|
203
211
|
```
|
204
212
|
|
205
213
|
You can also add some callbacks to be run before and after the transaction:
|
@@ -210,10 +218,22 @@ Isolator.before_isolate do
|
|
210
218
|
end
|
211
219
|
|
212
220
|
Isolator.after_isolate do
|
213
|
-
# right after the transaction has been committed/
|
221
|
+
# right after the transaction has been committed/rolled back
|
214
222
|
end
|
215
223
|
```
|
216
224
|
|
225
|
+
## Troubleshooting
|
226
|
+
|
227
|
+
### Verbose output
|
228
|
+
|
229
|
+
In most cases, turning on verbose output for Isolator helps to identify the issue. To do that, you can either specify `ISOLATOR_DEBUG=true` environment variable or set `Isolator.debug_enabled` manually.
|
230
|
+
|
231
|
+
### Tests failing after upgrading to Rails 6.0.3 while using [Combustion](https://github.com/pat/combustion)
|
232
|
+
|
233
|
+
The reason is that Rails started using a [separate connection pool for advisory locks](https://github.com/rails/rails/pull/38235) since 6.0.3. Since Combustion usually applies migrations for every test run, this pool becomse visible to [test fixtures](https://github.com/rails/rails/blob/b738f1930f3c82f51741ef7241c1fee691d7deb2/activerecord/lib/active_record/test_fixtures.rb#L123-L127), which resulted in 2 transactional commits tracked by Isolator, which only expects one. That leads to false negatives.
|
234
|
+
|
235
|
+
To fix this disable migrations advisory locks by adding `advisory_locks: false` to your database configuration in `(spec|test)/internal/config/database.yml`.
|
236
|
+
|
217
237
|
## Contributing
|
218
238
|
|
219
239
|
Bug reports and pull requests are welcome on GitHub at https://github.com/palkan/isolator.
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Isolator.isolate :active_job,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
target: ActiveJob::Base,
|
5
|
+
method_name: :enqueue,
|
6
|
+
exception_class: Isolator::BackgroundJobError,
|
7
|
+
details_message: ->(obj, _args) {
|
8
|
+
"#{obj.class.name}" \
|
9
|
+
"#{obj.arguments.any? ? " (#{obj.arguments.join(", ")})" : ""}"
|
10
|
+
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Isolator.isolate :resque,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
target: Resque.singleton_class,
|
5
|
+
method_name: :enqueue,
|
6
|
+
exception_class: Isolator::BackgroundJobError,
|
7
|
+
details_message: ->(_obj, args) {
|
8
|
+
args.join(", ")
|
9
|
+
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Isolator.isolate :resque_scheduler,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
target: Resque.singleton_class,
|
5
|
+
method_name: :enqueue_at,
|
6
|
+
exception_class: Isolator::BackgroundJobError,
|
7
|
+
details_message: ->(_obj, (ts, *args)) {
|
8
|
+
"#{args.join(", ")} (at #{ts})"
|
9
|
+
}
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Isolator.isolate :sidekiq,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
target: Sidekiq::Client,
|
5
|
+
method_name: :raw_push,
|
6
|
+
exception_class: Isolator::BackgroundJobError,
|
7
|
+
details_message: ->(_obj, args) {
|
8
|
+
args.first.map do |job|
|
9
|
+
"#{job["class"]} (#{job["args"]})"
|
10
|
+
end.join("\n")
|
11
|
+
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Isolator.isolate :sucker_punch,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
target: SuckerPunch::Queue.singleton_class,
|
5
|
+
method_name: :find_or_create,
|
6
|
+
exception_class: Isolator::BackgroundJobError,
|
7
|
+
details_message: ->(_obj, args) {
|
8
|
+
args.compact.join(", ")
|
9
|
+
}
|
@@ -10,7 +10,7 @@ Isolator.isolate :http, target: Sniffer.singleton_class,
|
|
10
10
|
exception_class: Isolator::HTTPError,
|
11
11
|
details_message: ->(_obj, args) {
|
12
12
|
req = args.first.request
|
13
|
-
"#{req
|
13
|
+
"#{req.method} #{req.host}:#{req.port}#{req.query}"
|
14
14
|
}
|
15
15
|
|
16
16
|
Isolator.before_isolate do
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
adapter = Isolator.isolate :webmock,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
exception_class: Isolator::HTTPError,
|
5
|
+
details_message: ->(obj, _args) {
|
6
|
+
"#{obj.method.to_s.upcase} #{obj.uri}"
|
7
|
+
}
|
8
8
|
|
9
9
|
WebMock.after_request do |*args|
|
10
10
|
adapter.notify(caller, *args)
|
@@ -5,25 +5,31 @@ module Isolator
|
|
5
5
|
#
|
6
6
|
# - `raise_exceptions` - whether to raise an exception in case of offense;
|
7
7
|
# defaults to true in test env and false otherwise.
|
8
|
-
# NOTE: env is
|
8
|
+
# NOTE: env is inferred from RACK_ENV and RAILS_ENV.
|
9
9
|
#
|
10
10
|
# - `logger` - logger instance (nil by default)
|
11
11
|
#
|
12
12
|
# - `send_notifications` - whether to send notifications (through uniform_notifier);
|
13
|
-
#
|
13
|
+
# defaults to false
|
14
|
+
#
|
15
|
+
# - `backtrace_filter` - define a custom backtrace filtering (provide a callable)
|
16
|
+
#
|
17
|
+
# - `ignorer` - define a custom ignorer (must implement .prepare)
|
18
|
+
#
|
14
19
|
class Configuration
|
15
20
|
attr_accessor :raise_exceptions, :logger, :send_notifications,
|
16
|
-
|
21
|
+
:backtrace_filter, :ignorer
|
17
22
|
|
18
23
|
def initialize
|
19
24
|
@logger = nil
|
20
25
|
@raise_exceptions = test_env?
|
21
26
|
@send_notifications = false
|
22
27
|
@backtrace_filter = ->(backtrace) { backtrace.take(5) }
|
28
|
+
@ignorer = Isolator::Ignorer
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
31
|
+
alias_method :raise_exceptions?, :raise_exceptions
|
32
|
+
alias_method :send_notifications?, :send_notifications
|
27
33
|
|
28
34
|
def test_env?
|
29
35
|
ENV["RACK_ENV"] == "test" || ENV["RAILS_ENV"] == "test"
|
data/lib/isolator/ignorer.rb
CHANGED
@@ -1,39 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Isolator
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
return unless File.exist?(path)
|
4
|
+
# Handle ignoring isolator errors using a yml file
|
5
|
+
class Ignorer
|
6
|
+
TODO_PATH = ".isolator_todo.yml"
|
8
7
|
|
9
|
-
|
8
|
+
class << self
|
9
|
+
def prepare(path: TODO_PATH, regex_string: "^.*(#ignores#):.*$")
|
10
|
+
return unless File.exist?(path)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
todos = YAML.load_file(path)
|
13
|
+
|
14
|
+
Isolator.adapters.each do |id, adapter|
|
15
|
+
ignored_paths = todos.fetch(id, [])
|
16
|
+
AdapterIgnore.new(adapter: adapter, ignored_paths: ignored_paths, regex_string: regex_string).prepare
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
private
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
class AdapterIgnore
|
24
|
+
def initialize(adapter:, ignored_paths:, regex_string:)
|
25
|
+
self.adapter = adapter
|
26
|
+
self.ignored_paths = ignored_paths
|
27
|
+
self.regex_string = regex_string
|
28
|
+
end
|
29
|
+
|
30
|
+
def prepare
|
31
|
+
return if ignores.blank?
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
33
|
+
adapter.ignore_if { caller.any? { |row| regex =~ row } }
|
34
|
+
end
|
26
35
|
|
27
|
-
|
28
|
-
ignored_paths.each_with_object([]) do |path, result|
|
29
|
-
ignored_files = Dir[path]
|
36
|
+
private
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
38
|
+
attr_accessor :adapter, :ignored_paths, :regex_string
|
39
|
+
|
40
|
+
def ignores
|
41
|
+
return @ignores if defined? @ignores
|
42
|
+
|
43
|
+
@ignores = ignored_paths.each_with_object([]) do |path, result|
|
44
|
+
ignored_files = Dir[path]
|
45
|
+
|
46
|
+
if ignored_files.blank?
|
47
|
+
result << path.to_s
|
48
|
+
else
|
49
|
+
result.concat(ignored_files)
|
50
|
+
end
|
35
51
|
end
|
36
52
|
end
|
53
|
+
|
54
|
+
def regex
|
55
|
+
Regexp.new(regex_string.gsub("#ignores#", ignores.join("|")))
|
56
|
+
end
|
37
57
|
end
|
38
58
|
end
|
39
59
|
end
|
data/lib/isolator/isolate.rb
CHANGED
@@ -5,7 +5,7 @@ module Isolator
|
|
5
5
|
module Isolate
|
6
6
|
def isolate(id, **options)
|
7
7
|
raise "Adapter already registered: #{id}" if Isolator.adapters.key?(id.to_s)
|
8
|
-
adapter = AdapterBuilder.call(options)
|
8
|
+
adapter = AdapterBuilder.call(**options)
|
9
9
|
Isolator.adapters[id.to_s] = adapter
|
10
10
|
end
|
11
11
|
end
|
@@ -9,8 +9,9 @@ module Isolator
|
|
9
9
|
|
10
10
|
def self.subscribe!(event)
|
11
11
|
::ActiveSupport::Notifications.subscribe(event) do |_name, _start, _finish, _id, query|
|
12
|
-
|
13
|
-
Isolator.
|
12
|
+
connection_id = query[:connection_id] || query[:connection]&.object_id || 0
|
13
|
+
Isolator.incr_transactions!(connection_id) if START_PATTERN.match?(query[:sql])
|
14
|
+
Isolator.decr_transactions!(connection_id) if FINISH_PATTERN.match?(query[:sql])
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
data/lib/isolator/railtie.rb
CHANGED
@@ -2,12 +2,21 @@
|
|
2
2
|
|
3
3
|
module Isolator
|
4
4
|
class Railtie < ::Rails::Railtie # :nodoc:
|
5
|
+
initializer "isolator.backtrace_cleaner" do
|
6
|
+
ActiveSupport.on_load(:active_record) do
|
7
|
+
Isolator.backtrace_cleaner = lambda do |locations|
|
8
|
+
::Rails.backtrace_cleaner.clean(locations)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
config.after_initialize do
|
6
14
|
# Forec load adapters after application initialization
|
7
15
|
# (when all deps are likely to be loaded).
|
8
16
|
load File.join(__dir__, "adapters.rb")
|
9
17
|
|
10
|
-
Isolator.
|
18
|
+
Isolator.config.ignorer&.prepare
|
19
|
+
Isolator.config.ignorer&.prepare(path: ".isolator_ignore.yml")
|
11
20
|
|
12
21
|
next unless Rails.env.test?
|
13
22
|
|
@@ -18,14 +27,12 @@ module Isolator
|
|
18
27
|
super
|
19
28
|
return unless run_in_transaction?
|
20
29
|
|
21
|
-
|
22
|
-
Isolator.transactions_threshold += open_count
|
30
|
+
Isolator.incr_thresholds!
|
23
31
|
end
|
24
32
|
|
25
33
|
def teardown_fixtures(*)
|
26
34
|
if run_in_transaction?
|
27
|
-
|
28
|
-
Isolator.transactions_threshold -= open_count
|
35
|
+
Isolator.decr_thresholds!
|
29
36
|
end
|
30
37
|
super
|
31
38
|
end
|
data/lib/isolator/version.rb
CHANGED
data/lib/isolator.rb
CHANGED
@@ -17,7 +17,25 @@ require "isolator/ext/thread_fetch"
|
|
17
17
|
module Isolator
|
18
18
|
using Isolator::ThreadFetch
|
19
19
|
|
20
|
+
class ThreadStateProxy
|
21
|
+
attr_reader :prefix
|
22
|
+
|
23
|
+
def initilize(prefix = "isolator_")
|
24
|
+
@prefix = prefix
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
Thread.current[:"#{prefix}#{key}"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def []=(key, value)
|
32
|
+
Thread.current[:"#{prefix}#{key}"] = value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
20
36
|
class << self
|
37
|
+
attr_accessor :default_threshold, :default_connection_id
|
38
|
+
|
21
39
|
def config
|
22
40
|
@config ||= Configuration.new
|
23
41
|
end
|
@@ -31,11 +49,11 @@ module Isolator
|
|
31
49
|
end
|
32
50
|
|
33
51
|
def enable!
|
34
|
-
|
52
|
+
state[:disabled] = false
|
35
53
|
end
|
36
54
|
|
37
55
|
def disable!
|
38
|
-
|
56
|
+
state[:disabled] = true
|
39
57
|
end
|
40
58
|
|
41
59
|
# Accepts block and disable Isolator within
|
@@ -64,32 +82,84 @@ module Isolator
|
|
64
82
|
res
|
65
83
|
end
|
66
84
|
|
67
|
-
def transactions_threshold
|
68
|
-
|
85
|
+
def transactions_threshold=(val)
|
86
|
+
set_connection_threshold(val)
|
69
87
|
end
|
70
88
|
|
71
|
-
def transactions_threshold=
|
72
|
-
|
89
|
+
def transactions_threshold(connection_id = default_connection_id.call)
|
90
|
+
connection_threshold(connection_id)
|
73
91
|
end
|
74
92
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
93
|
+
def current_transactions(connection_id = default_connection_id.call)
|
94
|
+
state[:transactions]&.[](connection_id) || 0
|
95
|
+
end
|
96
|
+
|
97
|
+
def set_connection_threshold(val, connection_id = default_connection_id.call)
|
98
|
+
state[:thresholds] ||= Hash.new { |h, k| h[k] = Isolator.default_threshold }
|
99
|
+
state[:thresholds][connection_id] = val
|
100
|
+
|
101
|
+
debug!("Threshold value was changed for connection #{connection_id}: #{val}")
|
102
|
+
end
|
103
|
+
|
104
|
+
def incr_thresholds!
|
105
|
+
self.default_threshold += 1
|
106
|
+
return unless state[:thresholds]
|
107
|
+
|
108
|
+
state[:thresholds].transform_values!(&:succ)
|
109
|
+
|
110
|
+
debug!("Thresholds were incremented")
|
111
|
+
end
|
112
|
+
|
113
|
+
def decr_thresholds!
|
114
|
+
self.default_threshold -= 1
|
115
|
+
return unless state[:thresholds]
|
116
|
+
|
117
|
+
state[:thresholds].transform_values!(&:pred)
|
118
|
+
|
119
|
+
debug!("Thresholds were decremented")
|
120
|
+
end
|
121
|
+
|
122
|
+
def incr_transactions!(connection_id = default_connection_id.call)
|
123
|
+
state[:transactions] ||= Hash.new { |h, k| h[k] = 0 }
|
124
|
+
state[:transactions][connection_id] += 1
|
125
|
+
|
126
|
+
# Workaround to track threshold changes made before opening a connection
|
127
|
+
pending_threshold = state[:thresholds]&.delete(0)
|
128
|
+
if pending_threshold
|
129
|
+
state[:thresholds][connection_id] = pending_threshold
|
130
|
+
end
|
131
|
+
|
132
|
+
debug!("Transaction opened for connection #{connection_id} (total: #{state[:transactions][connection_id]}, threshold: #{state[:thresholds]&.fetch(connection_id, default_threshold)})")
|
133
|
+
|
134
|
+
start! if current_transactions(connection_id) == connection_threshold(connection_id)
|
79
135
|
end
|
80
136
|
|
81
|
-
def decr_transactions!
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
+
|
145
|
+
state[:transactions][connection_id] -= 1
|
146
|
+
|
147
|
+
finish! if current_transactions(connection_id) == (connection_threshold(connection_id) - 1)
|
148
|
+
|
149
|
+
state[:transactions].delete(connection_id) if state[:transactions][connection_id].zero?
|
150
|
+
|
151
|
+
debug!("Transaction closed for connection #{connection_id} (total: #{state[:transactions][connection_id]}, threshold: #{state[:thresholds]&.[](connection_id) || default_threshold})")
|
85
152
|
end
|
86
153
|
|
87
154
|
def clear_transactions!
|
88
|
-
|
155
|
+
state[:transactions]&.clear
|
89
156
|
end
|
90
157
|
|
91
158
|
def within_transaction?
|
92
|
-
|
159
|
+
state[:transactions]&.each do |connection_id, transaction_count|
|
160
|
+
return true if transaction_count >= connection_threshold(connection_id)
|
161
|
+
end
|
162
|
+
false
|
93
163
|
end
|
94
164
|
|
95
165
|
def enabled?
|
@@ -97,17 +167,61 @@ module Isolator
|
|
97
167
|
end
|
98
168
|
|
99
169
|
def disabled?
|
100
|
-
|
170
|
+
state[:disabled] == true
|
101
171
|
end
|
102
172
|
|
103
173
|
def adapters
|
104
174
|
@adapters ||= Isolator::SimpleHashie.new
|
105
175
|
end
|
106
176
|
|
177
|
+
def load_ignore_config(path)
|
178
|
+
warn "[DEPRECATION] `load_ignore_config` is deprecated. Please use `Isolator::Ignorer.prepare` instead."
|
179
|
+
Isolator::Ignorer.prepare(path: path)
|
180
|
+
end
|
181
|
+
|
107
182
|
include Isolator::Isolate
|
108
183
|
include Isolator::Callbacks
|
109
|
-
|
184
|
+
|
185
|
+
attr_accessor :debug_enabled, :backtrace_cleaner, :backtrace_length
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
attr_accessor :state
|
190
|
+
|
191
|
+
def connection_threshold(connection_id)
|
192
|
+
state[:thresholds]&.[](connection_id) || default_threshold
|
193
|
+
end
|
194
|
+
|
195
|
+
def debug!(msg)
|
196
|
+
return unless debug_enabled
|
197
|
+
msg = "[ISOLATOR DEBUG] #{msg}"
|
198
|
+
|
199
|
+
if backtrace_cleaner && backtrace_length.positive?
|
200
|
+
source = extract_source_location(caller)
|
201
|
+
|
202
|
+
msg = "#{msg}\n ↳ #{source.join("\n")}" unless source.empty?
|
203
|
+
end
|
204
|
+
|
205
|
+
$stdout.puts(colorize_debug(msg))
|
206
|
+
end
|
207
|
+
|
208
|
+
def extract_source_location(locations)
|
209
|
+
backtrace_cleaner.call(locations.lazy)
|
210
|
+
.take(backtrace_length).to_a
|
211
|
+
end
|
212
|
+
|
213
|
+
def colorize_debug(msg)
|
214
|
+
return msg unless $stdout.tty?
|
215
|
+
|
216
|
+
"\u001b[31;1m#{msg}\u001b[0m"
|
217
|
+
end
|
110
218
|
end
|
219
|
+
|
220
|
+
self.state = ThreadStateProxy.new
|
221
|
+
self.default_threshold = 1
|
222
|
+
self.default_connection_id = -> { ActiveRecord::Base.connected? ? ActiveRecord::Base.connection.object_id : 0 }
|
223
|
+
self.debug_enabled = ENV["ISOLATOR_DEBUG"] == "true"
|
224
|
+
self.backtrace_length = ENV.fetch("ISOLATOR_BACKTRACE_LENGTH", 1).to_i
|
111
225
|
end
|
112
226
|
|
113
227
|
require "isolator/orm_adapters"
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isolator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.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: 2021-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sniffer
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.3.1
|
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
26
|
version: 0.3.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '13.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '13.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,14 +70,14 @@ dependencies:
|
|
70
70
|
name: rspec-rails
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '3.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
@@ -95,77 +95,77 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 5.10.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: sidekiq
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: '5.0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: '5.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: webmock
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '3.1'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '3.1'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: test_after_commit
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '1.1'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '1.1'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: resque
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- - "
|
143
|
+
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
145
|
+
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- - "
|
150
|
+
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
152
|
+
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: fakeredis
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- - "
|
157
|
+
- - ">="
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: '
|
159
|
+
version: '0'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- - "
|
164
|
+
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
166
|
+
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name: resque
|
168
|
+
name: resque-scheduler
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
171
|
- - ">="
|
@@ -179,7 +179,7 @@ dependencies:
|
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
182
|
+
name: sucker_punch
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
185
|
- - ">="
|
@@ -193,7 +193,7 @@ dependencies:
|
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
196
|
+
name: database_cleaner
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
199
|
- - ">="
|
@@ -207,7 +207,7 @@ dependencies:
|
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
|
-
name:
|
210
|
+
name: database_cleaner-active_record
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
213
|
- - ">="
|
@@ -221,7 +221,49 @@ dependencies:
|
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
|
-
name:
|
224
|
+
name: after_commit_everywhere
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: uniform_notifier
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
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
|
225
267
|
requirement: !ruby/object:Gem::Requirement
|
226
268
|
requirements:
|
227
269
|
- - ">="
|
@@ -241,22 +283,9 @@ executables: []
|
|
241
283
|
extensions: []
|
242
284
|
extra_rdoc_files: []
|
243
285
|
files:
|
244
|
-
- ".gitignore"
|
245
|
-
- ".rubocop.yml"
|
246
|
-
- ".travis.yml"
|
247
286
|
- CHANGELOG.md
|
248
|
-
- Gemfile
|
249
287
|
- LICENSE.txt
|
250
288
|
- README.md
|
251
|
-
- Rakefile
|
252
|
-
- bin/console
|
253
|
-
- bin/setup
|
254
|
-
- gemfiles/activerecord42.gemfile
|
255
|
-
- gemfiles/jruby.gemfile
|
256
|
-
- gemfiles/rails6.gemfile
|
257
|
-
- gemfiles/railsmaster.gemfile
|
258
|
-
- gemfiles/ruby_2.2.2.gemfile
|
259
|
-
- isolator.gemspec
|
260
289
|
- lib/isolator.rb
|
261
290
|
- lib/isolator/adapter_builder.rb
|
262
291
|
- lib/isolator/adapters.rb
|
@@ -291,8 +320,13 @@ files:
|
|
291
320
|
homepage: https://github.com/palkan/isolator
|
292
321
|
licenses:
|
293
322
|
- MIT
|
294
|
-
metadata:
|
295
|
-
|
323
|
+
metadata:
|
324
|
+
bug_tracker_uri: http://github.com/palkan/isolator/issues
|
325
|
+
changelog_uri: https://github.com/palkan/isolator/blob/master/CHANGELOG.md
|
326
|
+
documentation_uri: http://github.com/palkan/isolator
|
327
|
+
homepage_uri: http://github.com/palkan/isolator
|
328
|
+
source_code_uri: http://github.com/palkan/isolator
|
329
|
+
post_install_message:
|
296
330
|
rdoc_options: []
|
297
331
|
require_paths:
|
298
332
|
- lib
|
@@ -300,15 +334,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
300
334
|
requirements:
|
301
335
|
- - ">="
|
302
336
|
- !ruby/object:Gem::Version
|
303
|
-
version: 2.
|
337
|
+
version: 2.6.0
|
304
338
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
305
339
|
requirements:
|
306
340
|
- - ">="
|
307
341
|
- !ruby/object:Gem::Version
|
308
342
|
version: '0'
|
309
343
|
requirements: []
|
310
|
-
rubygems_version: 3.
|
311
|
-
signing_key:
|
344
|
+
rubygems_version: 3.2.22
|
345
|
+
signing_key:
|
312
346
|
specification_version: 4
|
313
347
|
summary: Detect non-atomic interactions within DB transactions
|
314
348
|
test_files: []
|
data/.gitignore
DELETED
data/.rubocop.yml
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require:
|
2
|
-
- rubocop-md
|
3
|
-
|
4
|
-
AllCops:
|
5
|
-
Include:
|
6
|
-
- 'lib/**/*.rb'
|
7
|
-
- 'lib/**/*.rake'
|
8
|
-
- 'spec/**/*.rb'
|
9
|
-
Exclude:
|
10
|
-
- 'bin/**/*'
|
11
|
-
- 'gemfiles/**/*'
|
12
|
-
- 'spec/dummy/**/*'
|
13
|
-
- 'vendor/**/*'
|
14
|
-
- 'tmp/**/*'
|
15
|
-
- 'Rakefile'
|
16
|
-
- 'Gemfile'
|
17
|
-
- '*.gemspec'
|
18
|
-
DisplayCopNames: true
|
19
|
-
StyleGuideCopsOnly: false
|
20
|
-
TargetRubyVersion: 2.2.2
|
21
|
-
|
22
|
-
Rails:
|
23
|
-
Enabled: false
|
24
|
-
|
25
|
-
Bundler/OrderedGems:
|
26
|
-
Enabled: false
|
27
|
-
|
28
|
-
Naming/UncommunicativeMethodParamName:
|
29
|
-
Enabled: false
|
30
|
-
|
31
|
-
Style/SymbolArray:
|
32
|
-
Enabled: false
|
33
|
-
|
34
|
-
Style/Documentation:
|
35
|
-
Exclude:
|
36
|
-
- 'spec/**/*.rb'
|
37
|
-
|
38
|
-
Style/StringLiterals:
|
39
|
-
EnforcedStyle: double_quotes
|
40
|
-
|
41
|
-
Style/RegexpLiteral:
|
42
|
-
Enabled: false
|
43
|
-
|
44
|
-
Style/Lambda:
|
45
|
-
Enabled: false
|
46
|
-
|
47
|
-
Style/BlockDelimiters:
|
48
|
-
Exclude:
|
49
|
-
- 'spec/**/*.rb'
|
50
|
-
|
51
|
-
Style/NumericPredicate:
|
52
|
-
Enabled: false
|
53
|
-
|
54
|
-
Layout/SpaceInsideStringInterpolation:
|
55
|
-
EnforcedStyle: no_space
|
56
|
-
|
57
|
-
Lint/AmbiguousRegexpLiteral:
|
58
|
-
Enabled: false
|
59
|
-
|
60
|
-
Metrics/LineLength:
|
61
|
-
Max: 100
|
62
|
-
Exclude:
|
63
|
-
- 'spec/**/*.rb'
|
64
|
-
|
65
|
-
Metrics/BlockLength:
|
66
|
-
Exclude:
|
67
|
-
- 'spec/**/*.rb'
|
68
|
-
|
69
|
-
Style/MutableConstant:
|
70
|
-
Enabled: false
|
data/.travis.yml
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
cache: bundler
|
4
|
-
rvm:
|
5
|
-
- 2.5.3
|
6
|
-
|
7
|
-
notifications:
|
8
|
-
email: false
|
9
|
-
|
10
|
-
before_install:
|
11
|
-
- (ruby -v | grep '2.2.2') || gem update --system
|
12
|
-
- gem install bundler -v '< 2'
|
13
|
-
|
14
|
-
matrix:
|
15
|
-
fast_finish: true
|
16
|
-
include:
|
17
|
-
- rvm: ruby-head
|
18
|
-
gemfile: gemfiles/railsmaster.gemfile
|
19
|
-
- rvm: jruby-9.1.0.0
|
20
|
-
gemfile: gemfiles/jruby.gemfile
|
21
|
-
- rvm: 2.6.1
|
22
|
-
gemfile: gemfiles/rails6.gemfile
|
23
|
-
- rvm: 2.5.0
|
24
|
-
gemfile: Gemfile
|
25
|
-
- rvm: 2.4.3
|
26
|
-
gemfile: Gemfile
|
27
|
-
- rvm: 2.3.1
|
28
|
-
gemfile: gemfiles/activerecord42.gemfile
|
29
|
-
- rvm: 2.2.2
|
30
|
-
gemfile: gemfiles/ruby_2.2.2.gemfile
|
31
|
-
allow_failures:
|
32
|
-
- rvm: ruby-head
|
33
|
-
gemfile: gemfiles/railsmaster.gemfile
|
34
|
-
- rvm: jruby-9.1.0.0
|
35
|
-
gemfile: gemfiles/jruby.gemfile
|
data/Gemfile
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
|
-
|
5
|
-
# Specify your gem's dependencies in isolator.gemspec
|
6
|
-
gemspec
|
7
|
-
|
8
|
-
gem "pry-byebug"
|
9
|
-
|
10
|
-
gem "sqlite3", "~> 1.3.0"
|
11
|
-
|
12
|
-
local_gemfile = File.join(__dir__, "Gemfile.local")
|
13
|
-
|
14
|
-
if File.exist?(local_gemfile)
|
15
|
-
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
|
16
|
-
else
|
17
|
-
gem "rails", "~> 5.0"
|
18
|
-
end
|
19
|
-
|
20
|
-
gem 'uniform_notifier', '~> 1.11'
|
data/Rakefile
DELETED
data/bin/console
DELETED
data/bin/setup
DELETED
data/gemfiles/jruby.gemfile
DELETED
data/gemfiles/rails6.gemfile
DELETED
data/gemfiles/ruby_2.2.2.gemfile
DELETED
data/isolator.gemspec
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
lib = File.expand_path("../lib", __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require "isolator/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "isolator"
|
7
|
-
spec.version = Isolator::VERSION
|
8
|
-
spec.authors = ["Vladimir Dementyev"]
|
9
|
-
spec.email = ["dementiev.vm@gmail.com"]
|
10
|
-
|
11
|
-
spec.summary = "Detect non-atomic interactions within DB transactions"
|
12
|
-
spec.description = "Detect non-atomic interactions within DB transactions"
|
13
|
-
spec.homepage = "https://github.com/palkan/isolator"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.required_ruby_version = ">= 2.2.2"
|
17
|
-
|
18
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
-
f.match(%r{^(test|spec|features)/})
|
20
|
-
end
|
21
|
-
spec.require_paths = ["lib"]
|
22
|
-
|
23
|
-
spec.add_runtime_dependency "sniffer", "~> 0.3.1"
|
24
|
-
|
25
|
-
spec.add_development_dependency "bundler", ">= 1.16"
|
26
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
-
spec.add_development_dependency "rspec-rails", "~> 3.0"
|
29
|
-
spec.add_development_dependency "minitest", "~> 5.10.0"
|
30
|
-
spec.add_development_dependency "rubocop", "~> 0.56.0"
|
31
|
-
spec.add_development_dependency "rubocop-md", "~> 0.2"
|
32
|
-
|
33
|
-
spec.add_development_dependency "sidekiq", "~> 5.0"
|
34
|
-
spec.add_development_dependency "webmock", "~> 3.1"
|
35
|
-
spec.add_development_dependency "test_after_commit", "~> 1.1"
|
36
|
-
spec.add_development_dependency "resque"
|
37
|
-
spec.add_development_dependency "fakeredis"
|
38
|
-
spec.add_development_dependency "resque-scheduler"
|
39
|
-
spec.add_development_dependency "sucker_punch"
|
40
|
-
spec.add_development_dependency "database_cleaner"
|
41
|
-
end
|