isolator 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6416346eed42fd67e5cc8e6801f983fee64666e21547e603e0c137f9e6fffad6
4
- data.tar.gz: b8e18e6b741c1fb19726957e99f4e04b83cb70e008cf1100db9c4fab5737250f
3
+ metadata.gz: d5c027f6c2e795b8aeb009340efd8a920556cfb47553a06d93f4feab8d7c79de
4
+ data.tar.gz: 3ae481ffdf7eba4d080402d44c7355c558363b0228053091ca96edc55bd26847
5
5
  SHA512:
6
- metadata.gz: 821a71fc3afe8425b7eb7aef194c43213de681b7b2f9b468968a6dcb8479a114797451894e49ff9ea4da40f1594957e555a9c752ade26b7b76c8a80cc3eba653
7
- data.tar.gz: 6440b717a3caa57454f1a6c6a5803717641e9dc32e7ef397572f131acf37f716d9f3f573ce3796c0b064fac2f0edcbdfd60ea3dec8e4b8712eca225782a9ba4d
6
+ metadata.gz: '008f26a3b4e3d059332e25a0b193dcec4586a17b6d6df9259b8b13e94a85e214e2c16aa37197a5490e92ba3cc288ce656c3ae1e1061e7ae7968ff4b967d327f1'
7
+ data.tar.gz: 2a4237282734486458d04f45474eee2a75367724808f8079801645ffe978981725f6d46e6db1de041d8c36d2cd1a5832b7f09f44e2773c609013560bd9ee5904
@@ -41,6 +41,9 @@ Style/StringLiterals:
41
41
  Style/RegexpLiteral:
42
42
  Enabled: false
43
43
 
44
+ Style/Lambda:
45
+ Enabled: false
46
+
44
47
  Style/BlockDelimiters:
45
48
  Exclude:
46
49
  - 'spec/**/*.rb'
@@ -56,6 +59,8 @@ Lint/AmbiguousRegexpLiteral:
56
59
 
57
60
  Metrics/LineLength:
58
61
  Max: 100
62
+ Exclude:
63
+ - 'spec/**/*.rb'
59
64
 
60
65
  Metrics/BlockLength:
61
66
  Exclude:
@@ -1,11 +1,16 @@
1
1
  sudo: false
2
2
  language: ruby
3
+ cache: bundler
3
4
  rvm:
4
- - 2.5.0
5
+ - 2.5.3
5
6
 
6
7
  notifications:
7
8
  email: false
8
9
 
10
+ before_install:
11
+ - (ruby -v | grep '2.2.2') || gem update --system
12
+ - gem install bundler -v '< 2'
13
+
9
14
  matrix:
10
15
  fast_finish: true
11
16
  include:
@@ -13,6 +18,8 @@ matrix:
13
18
  gemfile: gemfiles/railsmaster.gemfile
14
19
  - rvm: jruby-9.1.0.0
15
20
  gemfile: gemfiles/jruby.gemfile
21
+ - rvm: 2.6.1
22
+ gemfile: gemfiles/rails6.gemfile
16
23
  - rvm: 2.5.0
17
24
  gemfile: Gemfile
18
25
  - rvm: 2.4.3
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.6.0 (2019-04-12) 🚀
6
+
7
+ - Add support for exceptions message details. ([@palkan][])
8
+
9
+ Make it possible to provide more information about the cause of the failure
10
+ (for example, job class and arguments for background jobs, URL for HTTP).
11
+
12
+ - Change backtrace filtering behaviour. ([@palkan][])
13
+
14
+ The default behaviour is to take the top five lines.
15
+ You can customize it via `Isolator.config.backtrace_filter`.
16
+
5
17
  ## 0.5.0 (2018-08-29)
6
18
 
7
19
  - [PR [#19](https://github.com/palkan/isolator/pull/19)] Adding support for ruby version 2.2.2. ([@shivanshgaur][])
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gemspec
7
7
 
8
8
  gem "pry-byebug"
9
9
 
10
- gem "sqlite3"
10
+ gem "sqlite3", "~> 1.3.0"
11
11
 
12
12
  local_gemfile = File.join(__dir__, "Gemfile.local")
13
13
 
data/README.md CHANGED
@@ -91,6 +91,10 @@ Isolator.configure do |config|
91
91
 
92
92
  # Send notifications to uniform_notifier
93
93
  config.send_notifications = false
94
+
95
+ # Customize backtrace filtering (provide a callable)
96
+ # By default, just takes the top-5 lines
97
+ config.backtrace_filter = ->(backtrace) { backtrace.take(5) }
94
98
  end
95
99
  ```
96
100
 
@@ -186,6 +190,17 @@ Isolator.isolate :danger, Danger.singleton_class, :explode, options
186
190
  Possible `options` are:
187
191
  - `exception_class` – an exception class to raise in case of offense
188
192
  - `exception_message` – custom exception message (could be specified without a class)
193
+ - `details_message` – a block to generate additional exceptin message information:
194
+
195
+ ```ruby
196
+ Isolator.isolate :active_job,
197
+ target: ActiveJob::Base,
198
+ method_name: :enqueue,
199
+ exception_class: Isolator::BackgroundJobError,
200
+ details_message: ->(obj, _args) {
201
+ "#{obj.class.name}(#{obj.arguments})"
202
+ }
203
+ ```
189
204
 
190
205
  You can also add some callbacks to be run before and after the transaction:
191
206
 
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 4.2"
4
- gem "sqlite3"
4
+ gem "sqlite3", "~> 1.3.0"
5
5
  gem 'uniform_notifier', '~> 1.11'
6
6
 
7
7
  gemspec path: ".."
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "6.0.0.beta3"
4
+ gem "sqlite3", "~> 1.3"
5
+ gem 'uniform_notifier', '~> 1.11'
6
+
7
+ gemspec path: ".."
@@ -1,6 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "arel", github: "rails/arel"
4
3
  gem "rails", github: "rails/rails"
5
4
  gem "sqlite3"
6
5
  gem 'uniform_notifier', '~> 1.11'
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 4.2"
4
- gem "sqlite3"
4
+ gem "sqlite3", "~> 1.3.0"
5
5
  gem 'uniform_notifier', '1.11'
6
6
  gem 'anyway_config', '1.2'
7
7
 
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_runtime_dependency "sniffer", "~> 0.3.1"
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "bundler", ">= 1.16"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
28
  spec.add_development_dependency "rspec-rails", "~> 3.0"
@@ -11,6 +11,7 @@ module Isolator
11
11
 
12
12
  self.exception_class = options[:exception_class] if options.key?(:exception_class)
13
13
  self.exception_message = options[:exception_message] if options.key?(:exception_message)
14
+ self.details_message = options[:details_message] if options.key?(:details_message)
14
15
  end
15
16
 
16
17
  add_patch_method(adapter, target, method_name) if
@@ -21,7 +22,7 @@ module Isolator
21
22
  def self.add_patch_method(adapter, base, method_name)
22
23
  mod = Module.new do
23
24
  define_method method_name do |*args, &block|
24
- adapter.notify(caller, *args)
25
+ adapter.notify(caller, self, *args)
25
26
  super(*args, &block)
26
27
  end
27
28
  end
@@ -3,4 +3,8 @@
3
3
  Isolator.isolate :active_job,
4
4
  target: ActiveJob::Base,
5
5
  method_name: :enqueue,
6
- exception_class: Isolator::BackgroundJobError
6
+ exception_class: Isolator::BackgroundJobError,
7
+ details_message: ->(obj, _args) {
8
+ "#{obj.class.name}" \
9
+ "#{obj.arguments.any? ? " (#{obj.arguments.join(', ')})" : ''}"
10
+ }
@@ -3,4 +3,7 @@
3
3
  Isolator.isolate :resque,
4
4
  target: Resque.singleton_class,
5
5
  method_name: :enqueue,
6
- exception_class: Isolator::BackgroundJobError
6
+ exception_class: Isolator::BackgroundJobError,
7
+ details_message: ->(_obj, args) {
8
+ args.join(", ")
9
+ }
@@ -3,4 +3,7 @@
3
3
  Isolator.isolate :resque_scheduler,
4
4
  target: Resque.singleton_class,
5
5
  method_name: :enqueue_at,
6
- exception_class: Isolator::BackgroundJobError
6
+ exception_class: Isolator::BackgroundJobError,
7
+ details_message: ->(_obj, (ts, *args)) {
8
+ "#{args.join(', ')} (at #{ts})"
9
+ }
@@ -3,4 +3,9 @@
3
3
  Isolator.isolate :sidekiq,
4
4
  target: Sidekiq::Client,
5
5
  method_name: :raw_push,
6
- exception_class: Isolator::BackgroundJobError
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
+ }
@@ -3,4 +3,7 @@
3
3
  Isolator.isolate :sucker_punch,
4
4
  target: SuckerPunch::Queue.singleton_class,
5
5
  method_name: :find_or_create,
6
- exception_class: Isolator::BackgroundJobError
6
+ exception_class: Isolator::BackgroundJobError,
7
+ details_message: ->(_obj, args) {
8
+ args.compact.join(", ")
9
+ }
@@ -4,7 +4,7 @@ module Isolator
4
4
  module Adapters
5
5
  # Used as a "template" for adapters
6
6
  module Base
7
- attr_accessor :exception_class, :exception_message
7
+ attr_accessor :exception_class, :exception_message, :details_message
8
8
 
9
9
  def disable!
10
10
  @disabled = true
@@ -22,9 +22,9 @@ module Isolator
22
22
  @disabled == true
23
23
  end
24
24
 
25
- def notify(backtrace, *args)
25
+ def notify(backtrace, obj, *args)
26
26
  return unless notify?(*args)
27
- Isolator.notify(exception: build_exception, backtrace: backtrace)
27
+ Isolator.notify(exception: build_exception(obj, args), backtrace: backtrace)
28
28
  end
29
29
 
30
30
  def notify?(*args)
@@ -45,9 +45,10 @@ module Isolator
45
45
 
46
46
  private
47
47
 
48
- def build_exception
48
+ def build_exception(obj, args)
49
49
  klass = exception_class || Isolator::UnsafeOperationError
50
- klass.new(exception_message)
50
+ details = details_message.call(obj, args) if details_message
51
+ klass.new(exception_message, details: details)
51
52
  end
52
53
  end
53
54
  end
@@ -7,7 +7,11 @@ Sniffer::Config.defaults["logger"] = nil
7
7
 
8
8
  Isolator.isolate :http, target: Sniffer.singleton_class,
9
9
  method_name: :store,
10
- exception_class: Isolator::HTTPError
10
+ exception_class: Isolator::HTTPError,
11
+ details_message: ->(_obj, args) {
12
+ req = args.first.request
13
+ "#{req[:method]} #{req[:host]}/#{req[:query]}"
14
+ }
11
15
 
12
16
  Isolator.before_isolate do
13
17
  next if Isolator.adapters.http.disabled?
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- adapter = Isolator.isolate :webmock, exception_class: Isolator::HTTPError
3
+ adapter = Isolator.isolate :webmock,
4
+ exception_class: Isolator::HTTPError,
5
+ details_message: ->(obj, _args) {
6
+ "#{obj.method.to_s.upcase} #{obj.uri}"
7
+ }
4
8
 
5
9
  WebMock.after_request do |*args|
6
10
  adapter.notify(caller, *args)
@@ -1,4 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Isolator.isolate :mailer, target: Mail::Message, method_name: :deliver,
4
- exception_class: Isolator::MailerError
3
+ Isolator.isolate :mailer, target: Mail::Message,
4
+ method_name: :deliver,
5
+ exception_class: Isolator::MailerError,
6
+ details_message: ->(obj, _args) {
7
+ "From: #{obj.from}\n" \
8
+ "To: #{obj.to}\n" \
9
+ "Subject: #{obj.subject}"
10
+ }
@@ -12,12 +12,14 @@ module Isolator
12
12
  # - `send_notifications` - whether to send notifications (through uniform_notifier);
13
13
  # defauls to false
14
14
  class Configuration
15
- attr_accessor :raise_exceptions, :logger, :send_notifications
15
+ attr_accessor :raise_exceptions, :logger, :send_notifications,
16
+ :backtrace_filter
16
17
 
17
18
  def initialize
18
19
  @logger = nil
19
20
  @raise_exceptions = test_env?
20
21
  @send_notifications = false
22
+ @backtrace_filter = ->(backtrace) { backtrace.take(5) }
21
23
  end
22
24
 
23
25
  alias raise_exceptions? raise_exceptions
@@ -4,9 +4,9 @@ module Isolator # :nodoc: all
4
4
  class UnsafeOperationError < StandardError
5
5
  MESSAGE = "You are trying to do unsafe operation inside db transaction"
6
6
 
7
- def initialize(msg = nil)
7
+ def initialize(msg = nil, details: nil)
8
8
  msg ||= self.class::MESSAGE
9
- super
9
+ super(details ? "#{msg}\nDetails: #{details}" : msg)
10
10
  end
11
11
  end
12
12
 
@@ -48,7 +48,7 @@ module Isolator
48
48
  end
49
49
 
50
50
  def filtered_backtrace
51
- backtrace.reject { |line| line =~ /\/(gems|ruby)/ }.take_while { |line| line !~ /ruby/ }
51
+ Isolator.config.backtrace_filter.call(backtrace)
52
52
  end
53
53
 
54
54
  def uniform_notifier_loaded?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Isolator
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  end
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.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-02 00:00:00.000000000 Z
11
+ date: 2019-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sniffer
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.14'
33
+ version: '1.16'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.14'
40
+ version: '1.16'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -253,6 +253,7 @@ files:
253
253
  - bin/setup
254
254
  - gemfiles/activerecord42.gemfile
255
255
  - gemfiles/jruby.gemfile
256
+ - gemfiles/rails6.gemfile
256
257
  - gemfiles/railsmaster.gemfile
257
258
  - gemfiles/ruby_2.2.2.gemfile
258
259
  - isolator.gemspec
@@ -306,8 +307,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
306
307
  - !ruby/object:Gem::Version
307
308
  version: '0'
308
309
  requirements: []
309
- rubyforge_project:
310
- rubygems_version: 2.7.6
310
+ rubygems_version: 3.0.2
311
311
  signing_key:
312
312
  specification_version: 4
313
313
  summary: Detect non-atomic interactions within DB transactions