isolator 0.6.0 → 0.8.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 +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
|
[![Cult Of Martians](http://cultofmartians.com/assets/badges/badge.svg)](http://cultofmartians.com/tasks/isolator.html)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/isolator.svg)](https://badge.fury.io/rb/isolator)
|
3
|
-
|
3
|
+
![Build](https://github.com/palkan/isolator/workflows/Build/badge.svg)
|
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
|