convenient_service 0.7.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 +18 -0
- data/ROADMAP.md +2 -0
- data/lib/convenient_service/aliases.rb +9 -0
- data/lib/convenient_service/common/plugins/has_constructor_without_initialize/concern.rb +19 -0
- data/lib/convenient_service/configs/minimal.rb +176 -0
- data/lib/convenient_service/configs/standard.rb +16 -104
- data/lib/convenient_service/configs.rb +1 -0
- data/lib/convenient_service/dependencies.rb +8 -0
- data/lib/convenient_service/examples/dry/gemfile/dry_service/config.rb +5 -5
- data/lib/convenient_service/examples/rails/gemfile/rails_service/config.rb +7 -7
- data/lib/convenient_service/rspec/helpers/custom/ignoring_error.rb +3 -0
- data/lib/convenient_service/rspec/helpers/custom/wrap_method/entities/wrapped_method.rb +29 -3
- data/lib/convenient_service/rspec/matchers/custom/results/base.rb +5 -0
- data/lib/convenient_service/service/plugins/has_result/concern/class_methods.rb +3 -3
- data/lib/convenient_service/service/plugins/has_result/constants.rb +0 -3
- data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data.rb +13 -0
- data/lib/convenient_service/service/plugins/raises_on_double_result/middleware.rb +37 -2
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_backtrace.rb +80 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_cause.rb +78 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_exception.rb +169 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_line.rb +40 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands.rb +7 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/constants.rb +13 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/middleware.rb +58 -0
- data/lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions.rb +5 -0
- data/lib/convenient_service/support/undefined.rb +9 -0
- data/lib/convenient_service/support.rb +2 -0
- data/lib/convenient_service/version.rb +1 -1
- metadata +12 -2
@@ -22,7 +22,7 @@ module ConvenientService
|
|
22
22
|
# NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
|
23
23
|
#
|
24
24
|
def success(
|
25
|
-
service:
|
25
|
+
service: create_without_initialize,
|
26
26
|
data: Constants::DEFAULT_SUCCESS_DATA
|
27
27
|
)
|
28
28
|
result_class.create(
|
@@ -42,7 +42,7 @@ module ConvenientService
|
|
42
42
|
# NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
|
43
43
|
#
|
44
44
|
def failure(
|
45
|
-
service:
|
45
|
+
service: create_without_initialize,
|
46
46
|
data: Constants::DEFAULT_FAILURE_DATA,
|
47
47
|
message: data.any? ? data.first.join(" ") : Constants::DEFAULT_FAILURE_MESSAGE
|
48
48
|
)
|
@@ -63,7 +63,7 @@ module ConvenientService
|
|
63
63
|
# NOTE: This method is internally used by custom RSpec helper `stub_service`. It should NOT be used in the client code.
|
64
64
|
#
|
65
65
|
def error(
|
66
|
-
service:
|
66
|
+
service: create_without_initialize,
|
67
67
|
message: Constants::DEFAULT_ERROR_MESSAGE,
|
68
68
|
code: Constants::DEFAULT_ERROR_CODE
|
69
69
|
)
|
@@ -5,9 +5,6 @@ module ConvenientService
|
|
5
5
|
module Plugins
|
6
6
|
module HasResult
|
7
7
|
module Constants
|
8
|
-
DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Service::Plugins::HasResult::Concern }
|
9
|
-
DEFAULT_SERVICE_INSTANCE = DEFAULT_SERVICE_CLASS.new
|
10
|
-
|
11
8
|
SUCCESS_STATUS = :success
|
12
9
|
FAILURE_STATUS = :failure
|
13
10
|
ERROR_STATUS = :error
|
@@ -18,6 +18,19 @@ module ConvenientService
|
|
18
18
|
|
19
19
|
attr_reader :value
|
20
20
|
|
21
|
+
##
|
22
|
+
# @internal
|
23
|
+
# NOTE: Ruby hashes enumerate their values in the order that the corresponding keys were inserted.
|
24
|
+
# That is why the end-user can be 100% sure that the failure message is always generated from the first key/value pair.
|
25
|
+
# - https://ruby-doc.org/core-2.7.0/Hash.html
|
26
|
+
#
|
27
|
+
# TODO: A test that crashes when such behaviour is broken.
|
28
|
+
#
|
29
|
+
# NOTE: As a result, there is NO need to use any custom `OrderedHash` implementations.
|
30
|
+
# - https://api.rubyonrails.org/v5.1/classes/ActiveSupport/OrderedHash.html
|
31
|
+
# - https://github.com/rails/rails/issues/22681
|
32
|
+
# - https://api.rubyonrails.org/classes/ActiveSupport/OrderedOptions.html
|
33
|
+
#
|
21
34
|
def initialize(value:)
|
22
35
|
@value = value
|
23
36
|
end
|
@@ -5,6 +5,26 @@ module ConvenientService
|
|
5
5
|
module Plugins
|
6
6
|
module RaisesOnDoubleResult
|
7
7
|
class Middleware < Core::MethodChainMiddleware
|
8
|
+
##
|
9
|
+
# @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
|
10
|
+
#
|
11
|
+
# @internal
|
12
|
+
# TODO: Rewrite `RaisesOnDoubleResult` to make it thread-safe.
|
13
|
+
#
|
14
|
+
# NOTE: Minimal reproducible example.
|
15
|
+
#
|
16
|
+
# class Service
|
17
|
+
# include ConvenientService::Standard::Config
|
18
|
+
#
|
19
|
+
# def result
|
20
|
+
# success
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# service = Service.new
|
25
|
+
#
|
26
|
+
# 10.times.reduce([]) { |threads| threads << Thread.new { service.result } }.join
|
27
|
+
#
|
8
28
|
def next(...)
|
9
29
|
refute_has_result! || mark_as_has_result!
|
10
30
|
|
@@ -14,8 +34,14 @@ module ConvenientService
|
|
14
34
|
private
|
15
35
|
|
16
36
|
##
|
17
|
-
#
|
18
|
-
#
|
37
|
+
# @return [Boolean]
|
38
|
+
# @raise [ConvenientService::Service::Plugins::RaisesOnDoubleResult::Errors::DoubleResult]
|
39
|
+
#
|
40
|
+
# @internal
|
41
|
+
# NOTE: `refute` is `!assert`.
|
42
|
+
# - https://docs.seattlerb.org/minitest
|
43
|
+
#
|
44
|
+
# NOTE: This method contains a trailing exclamation mark in its name since it is mutable.
|
19
45
|
#
|
20
46
|
def refute_has_result!
|
21
47
|
return unless entity.internals.cache.exist?(:has_result)
|
@@ -23,6 +49,15 @@ module ConvenientService
|
|
23
49
|
raise Errors::DoubleResult.new(service: entity)
|
24
50
|
end
|
25
51
|
|
52
|
+
##
|
53
|
+
# @return [Boolean]
|
54
|
+
#
|
55
|
+
# @internal
|
56
|
+
# NOTE: Name is inspired by `mark_as_read`.
|
57
|
+
# - https://github.com/ledermann/unread
|
58
|
+
#
|
59
|
+
# NOTE: This method contains a trailing exclamation mark in its name since it is mutable.
|
60
|
+
#
|
26
61
|
def mark_as_has_result!
|
27
62
|
entity.internals.cache.write(:has_result, true)
|
28
63
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Service
|
5
|
+
module Plugins
|
6
|
+
module RescuesResultUnhandledExceptions
|
7
|
+
module Commands
|
8
|
+
class FormatBacktrace < Support::Command
|
9
|
+
##
|
10
|
+
# @!attribute [r] backtrace
|
11
|
+
# @return [Array, nil]
|
12
|
+
#
|
13
|
+
attr_reader :backtrace
|
14
|
+
|
15
|
+
##
|
16
|
+
# @!attribute [r] max_size
|
17
|
+
# @return [Integer]
|
18
|
+
#
|
19
|
+
attr_reader :max_size
|
20
|
+
|
21
|
+
##
|
22
|
+
# @param backtrace [Array, nil]
|
23
|
+
# @param max_size [Integer]
|
24
|
+
# @return [void]
|
25
|
+
#
|
26
|
+
# @internal
|
27
|
+
# IMPORTANT: Sometimes `exception.backtrace` can be `nil`.
|
28
|
+
# - https://blog.kalina.tech/2019/04/exception-without-backtrace-in-ruby.html
|
29
|
+
# - https://github.com/jruby/jruby/issues/4467
|
30
|
+
#
|
31
|
+
def initialize(backtrace:, max_size:)
|
32
|
+
@backtrace = backtrace.to_a
|
33
|
+
@max_size = max_size
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [String]
|
38
|
+
#
|
39
|
+
# @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
|
40
|
+
#
|
41
|
+
# @example Backtrace with upto 10 lines.
|
42
|
+
#
|
43
|
+
# # /gem/lib/convenient_service/factories/services.rb:120:in `result'
|
44
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
|
45
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
|
46
|
+
# # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
|
47
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
48
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
|
49
|
+
# # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
|
50
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
|
51
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
|
52
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
53
|
+
#
|
54
|
+
# @example Backtrace with more than 10 lines.
|
55
|
+
#
|
56
|
+
# # /gem/lib/convenient_service/factories/services.rb:120:in `result'
|
57
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
|
58
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
|
59
|
+
# # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
|
60
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
61
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
|
62
|
+
# # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
|
63
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
|
64
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
|
65
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
66
|
+
# # ...
|
67
|
+
#
|
68
|
+
def call
|
69
|
+
message = backtrace.take(max_size).map { |line| Commands::FormatLine.call(line: line) }.join("\n")
|
70
|
+
|
71
|
+
message << "\n# ..." if backtrace.size > max_size
|
72
|
+
|
73
|
+
message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Service
|
5
|
+
module Plugins
|
6
|
+
module RescuesResultUnhandledExceptions
|
7
|
+
module Commands
|
8
|
+
class FormatCause < Support::Command
|
9
|
+
##
|
10
|
+
# @!attribute [r] exception
|
11
|
+
# @return [StandardError, nil]
|
12
|
+
#
|
13
|
+
attr_reader :cause
|
14
|
+
|
15
|
+
##
|
16
|
+
# @param cause [StandardError]
|
17
|
+
# @return [void]
|
18
|
+
#
|
19
|
+
def initialize(cause:)
|
20
|
+
@cause = cause
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @return [String]
|
25
|
+
#
|
26
|
+
# @note Cause formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
|
27
|
+
#
|
28
|
+
# @example Cause.
|
29
|
+
#
|
30
|
+
# ------------------
|
31
|
+
# --- Caused by: ---
|
32
|
+
# StandardError:
|
33
|
+
# cause message
|
34
|
+
# # /gem/lib/convenient_service/factories/service/class.rb:41:in `result'
|
35
|
+
#
|
36
|
+
def call
|
37
|
+
return "" unless cause
|
38
|
+
|
39
|
+
<<~MESSAGE.chomp
|
40
|
+
------------------
|
41
|
+
--- Caused by: ---
|
42
|
+
#{cause.class}:
|
43
|
+
#{cause.message}
|
44
|
+
#{formatted_cause_first_line}
|
45
|
+
MESSAGE
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
##
|
51
|
+
# @return [String, nil]
|
52
|
+
#
|
53
|
+
# @internal
|
54
|
+
# IMPORTANT: Sometimes `exception.backtrace` can be `nil`.
|
55
|
+
# - https://blog.kalina.tech/2019/04/exception-without-backtrace-in-ruby.html
|
56
|
+
# - https://github.com/jruby/jruby/issues/4467
|
57
|
+
#
|
58
|
+
def cause_first_line
|
59
|
+
return "" unless cause
|
60
|
+
return "" unless cause.backtrace
|
61
|
+
|
62
|
+
cause.backtrace.first
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# @return [String, nil]
|
67
|
+
#
|
68
|
+
def formatted_cause_first_line
|
69
|
+
return "" unless cause_first_line
|
70
|
+
|
71
|
+
Commands::FormatLine.call(line: cause_first_line)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Service
|
5
|
+
module Plugins
|
6
|
+
module RescuesResultUnhandledExceptions
|
7
|
+
module Commands
|
8
|
+
class FormatException < Support::Command
|
9
|
+
##
|
10
|
+
# @!attribute [r] exception
|
11
|
+
# @return [StandardError]
|
12
|
+
#
|
13
|
+
attr_reader :exception
|
14
|
+
|
15
|
+
##
|
16
|
+
# @!attribute [r] args
|
17
|
+
# @return [StandardError]
|
18
|
+
#
|
19
|
+
attr_reader :args
|
20
|
+
|
21
|
+
##
|
22
|
+
# @!attribute [r] kwargs
|
23
|
+
# @return [StandardError]
|
24
|
+
#
|
25
|
+
attr_reader :kwargs
|
26
|
+
|
27
|
+
##
|
28
|
+
# @!attribute [r] block
|
29
|
+
# @return [StandardError]
|
30
|
+
#
|
31
|
+
attr_reader :block
|
32
|
+
|
33
|
+
##
|
34
|
+
# @param exception [StandardError]
|
35
|
+
# @param args [Array]
|
36
|
+
# @param kwargs [Hash]
|
37
|
+
# @param block [Proc, nil]
|
38
|
+
# @return [void]
|
39
|
+
#
|
40
|
+
def initialize(exception:, args:, kwargs:, block:)
|
41
|
+
@exception = exception
|
42
|
+
@args = args
|
43
|
+
@kwargs = kwargs
|
44
|
+
@block = block
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# @return [String]
|
49
|
+
#
|
50
|
+
# @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
|
51
|
+
#
|
52
|
+
# @example Simple exception.
|
53
|
+
#
|
54
|
+
# StandardError:
|
55
|
+
# exception message
|
56
|
+
# # /gem/lib/convenient_service/factories/services.rb:120:in `result'
|
57
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
|
58
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
|
59
|
+
# # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
|
60
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
61
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
|
62
|
+
# # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
|
63
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
|
64
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
|
65
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
66
|
+
#
|
67
|
+
# @example Exception with backtrace with more than 10 lines.
|
68
|
+
#
|
69
|
+
# StandardError:
|
70
|
+
# exception message
|
71
|
+
# # /gem/lib/convenient_service/factories/services.rb:120:in `result'
|
72
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
|
73
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
|
74
|
+
# # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
|
75
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
76
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
|
77
|
+
# # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
|
78
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
|
79
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
|
80
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
81
|
+
# # ...
|
82
|
+
#
|
83
|
+
# @example Exception with cause.
|
84
|
+
#
|
85
|
+
# StandardError:
|
86
|
+
# exception message
|
87
|
+
# # /gem/lib/convenient_service/factories/service/class.rb:43:in `rescue in result'
|
88
|
+
# # /gem/lib/convenient_service/factories/service/class.rb:40:in `result'
|
89
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `call'
|
90
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/caller/commands/define_method_middlewares_caller.rb:116:in `block in result'
|
91
|
+
# # /gem/lib/convenient_service/dependencies/extractions/ruby_middleware/middleware/runner.rb:67:in `block (2 levels) in build_call_chain'
|
92
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/chain.rb:35:in `next'
|
93
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `block in next'
|
94
|
+
# # /gem/lib/convenient_service/support/cache.rb:110:in `fetch'
|
95
|
+
# # /gem/lib/convenient_service/common/plugins/caches_return_value/middleware.rb:17:in `next'
|
96
|
+
# # /gem/lib/convenient_service/core/entities/config/entities/method_middlewares/entities/middleware.rb:73:in `call'
|
97
|
+
# ------------------
|
98
|
+
# --- Caused by: ---
|
99
|
+
# StandardError:
|
100
|
+
# cause message
|
101
|
+
# # /gem/lib/convenient_service/factories/service/class.rb:41:in `result'
|
102
|
+
#
|
103
|
+
# @internal
|
104
|
+
# TODO: Think about the following questions:
|
105
|
+
# - How to format args, kwargs and block?
|
106
|
+
# - Who should format them? The end-user or this plugin?
|
107
|
+
#
|
108
|
+
def call
|
109
|
+
<<~MESSAGE.rstrip
|
110
|
+
#{formatted_exception}
|
111
|
+
#{formatted_exception_backtrace}
|
112
|
+
#{formatted_exception_cause}
|
113
|
+
MESSAGE
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
##
|
119
|
+
# @return [String]
|
120
|
+
#
|
121
|
+
def formatted_exception
|
122
|
+
<<~MESSAGE.chomp
|
123
|
+
#{exception.class}:
|
124
|
+
#{exception.message}
|
125
|
+
MESSAGE
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Formats exception backtrace. When backtrace has more then `max_backtrace_size` lines, the extra lines are trimmed.
|
130
|
+
# That is especially important for the monitoring system with the limited amount of memory, since it may too expensive to store the full backtrace all the time.
|
131
|
+
#
|
132
|
+
# @return [String]
|
133
|
+
#
|
134
|
+
# @internal
|
135
|
+
# TODO: Add an ability to set `max_backtrace_size` while configuring the middleware. For example:
|
136
|
+
#
|
137
|
+
# class Service
|
138
|
+
# include ConvenientService::Standard::Config
|
139
|
+
#
|
140
|
+
# middlewares :result, scope: :class do
|
141
|
+
# use ConvenientService::Service::Plugins::RescuesResultUnhandledExceptions::Middleware, max_backtrace_size: 1_000
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# # ...
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
def formatted_exception_backtrace
|
148
|
+
Commands::FormatBacktrace.call(backtrace: exception.backtrace, max_size: max_backtrace_size)
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# @return [String]
|
153
|
+
#
|
154
|
+
def formatted_exception_cause
|
155
|
+
Commands::FormatCause.call(cause: exception.cause)
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# @return [Integer]
|
160
|
+
#
|
161
|
+
def max_backtrace_size
|
162
|
+
Constants::DEFAULT_MAX_BACKTRACE_SIZE
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Service
|
5
|
+
module Plugins
|
6
|
+
module RescuesResultUnhandledExceptions
|
7
|
+
module Commands
|
8
|
+
class FormatLine < Support::Command
|
9
|
+
##
|
10
|
+
# @!attribute [r] line
|
11
|
+
# @return [String]
|
12
|
+
#
|
13
|
+
attr_reader :line
|
14
|
+
|
15
|
+
##
|
16
|
+
# @param line [String]
|
17
|
+
# @return [void]
|
18
|
+
#
|
19
|
+
def initialize(line:)
|
20
|
+
@line = line
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @return [String]
|
25
|
+
#
|
26
|
+
# @note Exceptions formatting is inspired by RSpec. It has almost the same output (at least for RSpec 3).
|
27
|
+
#
|
28
|
+
# @example Line.
|
29
|
+
#
|
30
|
+
# # /gem/lib/convenient_service/factories/services.rb:120:in `result'
|
31
|
+
#
|
32
|
+
def call
|
33
|
+
"# #{line}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ConvenientService
|
4
|
+
module Service
|
5
|
+
module Plugins
|
6
|
+
module RescuesResultUnhandledExceptions
|
7
|
+
class Middleware < Core::MethodChainMiddleware
|
8
|
+
##
|
9
|
+
# @param args [Array]
|
10
|
+
# @param kwargs [Hash]
|
11
|
+
# @param block [Proc, nil]
|
12
|
+
# @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
|
13
|
+
#
|
14
|
+
# @internal
|
15
|
+
# NOTE: `rescue => exception` is the same as `rescue ::StandardError => exception`.
|
16
|
+
#
|
17
|
+
# IMPORTANT: Never rescue `Exception` since its direct descendants are used internally by Ruby, rescue `StandardError` instead.
|
18
|
+
# - https://thoughtbot.com/blog/rescue-standarderror-not-exception
|
19
|
+
# - https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby
|
20
|
+
# - https://ruby-doc.org/core-2.7.0/Exception.html
|
21
|
+
#
|
22
|
+
def next(*args, **kwargs, &block)
|
23
|
+
chain.next(*args, **kwargs, &block)
|
24
|
+
rescue => exception
|
25
|
+
failure_result_from(exception, *args, **kwargs, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
##
|
31
|
+
# @param exception [StandardError]
|
32
|
+
# @param args [Array]
|
33
|
+
# @param kwargs [Hash]
|
34
|
+
# @param block [Proc, nil]
|
35
|
+
# @return [ConvenientService::Service::Plugins::HasResult::Entities::Result]
|
36
|
+
#
|
37
|
+
def failure_result_from(exception, *args, **kwargs, &block)
|
38
|
+
entity.failure(
|
39
|
+
data: {exception: exception},
|
40
|
+
message: format_exception(exception, *args, **kwargs, &block)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @param exception [StandardError]
|
46
|
+
# @param args [Array]
|
47
|
+
# @param kwargs [Hash]
|
48
|
+
# @param block [Proc, nil]
|
49
|
+
# @return [String]
|
50
|
+
#
|
51
|
+
def format_exception(exception, *args, **kwargs, &block)
|
52
|
+
Commands::FormatException.call(exception: exception, args: args, kwargs: kwargs, block: block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: convenient_service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marian Kostyk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -427,6 +427,7 @@ files:
|
|
427
427
|
- lib/convenient_service/common/plugins/normalizes_env/middleware.rb
|
428
428
|
- lib/convenient_service/configs.rb
|
429
429
|
- lib/convenient_service/configs/aliases.rb
|
430
|
+
- lib/convenient_service/configs/minimal.rb
|
430
431
|
- lib/convenient_service/configs/standard.rb
|
431
432
|
- lib/convenient_service/core.rb
|
432
433
|
- lib/convenient_service/core/aliases.rb
|
@@ -825,6 +826,14 @@ files:
|
|
825
826
|
- lib/convenient_service/service/plugins/raises_on_double_result.rb
|
826
827
|
- lib/convenient_service/service/plugins/raises_on_double_result/errors.rb
|
827
828
|
- lib/convenient_service/service/plugins/raises_on_double_result/middleware.rb
|
829
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions.rb
|
830
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands.rb
|
831
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_backtrace.rb
|
832
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_cause.rb
|
833
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_exception.rb
|
834
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/commands/format_line.rb
|
835
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/constants.rb
|
836
|
+
- lib/convenient_service/service/plugins/rescues_result_unhandled_exceptions/middleware.rb
|
828
837
|
- lib/convenient_service/service/plugins/wraps_result_in_db_transaction.rb
|
829
838
|
- lib/convenient_service/service/plugins/wraps_result_in_db_transaction/middleware.rb
|
830
839
|
- lib/convenient_service/services.rb
|
@@ -867,6 +876,7 @@ files:
|
|
867
876
|
- lib/convenient_service/support/not_passed.rb
|
868
877
|
- lib/convenient_service/support/raw_value.rb
|
869
878
|
- lib/convenient_service/support/ruby.rb
|
879
|
+
- lib/convenient_service/support/undefined.rb
|
870
880
|
- lib/convenient_service/support/version.rb
|
871
881
|
- lib/convenient_service/support/version/null_version.rb
|
872
882
|
- lib/convenient_service/utils.rb
|