bcdd-result 0.11.0 → 0.13.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/.rubocop.yml +16 -1
- data/CHANGELOG.md +97 -15
- data/README.md +508 -95
- data/Steepfile +4 -4
- data/examples/multiple_listeners/Rakefile +55 -0
- data/examples/multiple_listeners/app/models/account/member.rb +10 -0
- data/examples/multiple_listeners/app/models/account/owner_creation.rb +62 -0
- data/examples/multiple_listeners/app/models/account.rb +11 -0
- data/examples/multiple_listeners/app/models/user/creation.rb +67 -0
- data/examples/multiple_listeners/app/models/user/token/creation.rb +51 -0
- data/examples/multiple_listeners/app/models/user/token.rb +7 -0
- data/examples/multiple_listeners/app/models/user.rb +15 -0
- data/examples/multiple_listeners/config/boot.rb +16 -0
- data/examples/multiple_listeners/config/initializers/bcdd.rb +11 -0
- data/examples/multiple_listeners/config.rb +27 -0
- data/examples/multiple_listeners/db/setup.rb +61 -0
- data/examples/multiple_listeners/lib/bcdd/result/rollback_on_failure.rb +15 -0
- data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +28 -0
- data/examples/multiple_listeners/lib/runtime_breaker.rb +11 -0
- data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +54 -0
- data/examples/single_listener/Rakefile +92 -0
- data/examples/single_listener/app/models/account/member.rb +10 -0
- data/examples/single_listener/app/models/account/owner_creation.rb +62 -0
- data/examples/single_listener/app/models/account.rb +11 -0
- data/examples/single_listener/app/models/user/creation.rb +67 -0
- data/examples/single_listener/app/models/user/token/creation.rb +51 -0
- data/examples/single_listener/app/models/user/token.rb +7 -0
- data/examples/single_listener/app/models/user.rb +15 -0
- data/examples/single_listener/config/boot.rb +16 -0
- data/examples/single_listener/config/initializers/bcdd.rb +11 -0
- data/examples/single_listener/config.rb +23 -0
- data/examples/single_listener/db/setup.rb +49 -0
- data/examples/single_listener/lib/bcdd/result/rollback_on_failure.rb +15 -0
- data/examples/single_listener/lib/runtime_breaker.rb +11 -0
- data/examples/single_listener/lib/single_transitions_listener.rb +108 -0
- data/lib/bcdd/result/callable_and_then/caller.rb +49 -0
- data/lib/bcdd/result/callable_and_then/config.rb +15 -0
- data/lib/bcdd/result/callable_and_then/error.rb +11 -0
- data/lib/bcdd/result/callable_and_then.rb +9 -0
- data/lib/bcdd/result/config/switchers/features.rb +5 -1
- data/lib/bcdd/result/config.rb +15 -4
- data/lib/bcdd/result/context/callable_and_then.rb +39 -0
- data/lib/bcdd/result/context/expectations/mixin.rb +2 -2
- data/lib/bcdd/result/context/mixin.rb +3 -3
- data/lib/bcdd/result/context/success.rb +29 -7
- data/lib/bcdd/result/context.rb +34 -16
- data/lib/bcdd/result/contract/for_types.rb +1 -1
- data/lib/bcdd/result/contract/for_types_and_values.rb +2 -0
- data/lib/bcdd/result/error.rb +20 -11
- data/lib/bcdd/result/expectations/mixin.rb +3 -3
- data/lib/bcdd/result/expectations.rb +6 -6
- data/lib/bcdd/result/ignored_types.rb +14 -0
- data/lib/bcdd/result/mixin.rb +3 -3
- data/lib/bcdd/result/transitions/config.rb +26 -0
- data/lib/bcdd/result/transitions/listener.rb +51 -0
- data/lib/bcdd/result/transitions/listeners.rb +87 -0
- data/lib/bcdd/result/transitions/tracking/disabled.rb +4 -6
- data/lib/bcdd/result/transitions/tracking/enabled.rb +103 -24
- data/lib/bcdd/result/transitions/tracking.rb +8 -3
- data/lib/bcdd/result/transitions/tree.rb +36 -6
- data/lib/bcdd/result/transitions.rb +11 -14
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +39 -22
- data/sig/bcdd/result/callable_and_then.rbs +60 -0
- data/sig/bcdd/result/config.rbs +3 -0
- data/sig/bcdd/result/context.rbs +65 -4
- data/sig/bcdd/result/error.rbs +9 -6
- data/sig/bcdd/result/expectations.rbs +4 -4
- data/sig/bcdd/result/ignored_types.rbs +9 -0
- data/sig/bcdd/result/transitions.rbs +107 -7
- data/sig/bcdd/result.rbs +10 -6
- metadata +48 -6
@@ -2,30 +2,36 @@
|
|
2
2
|
|
3
3
|
module BCDD::Result::Transitions
|
4
4
|
class Tracking::Enabled
|
5
|
-
attr_accessor :tree, :records, :root_started_at
|
5
|
+
attr_accessor :tree, :records, :root_started_at, :listener
|
6
6
|
|
7
|
-
private :tree, :tree=, :records, :records=, :root_started_at, :root_started_at=
|
7
|
+
private :tree, :tree=, :records, :records=, :root_started_at, :root_started_at=, :listener, :listener=
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def exec(name, desc)
|
10
|
+
transition_node, scope = start(name, desc)
|
11
11
|
|
12
|
-
|
13
|
-
end
|
12
|
+
result = nil
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
listener.around_transitions(scope: scope) do
|
15
|
+
result = EnsureResult[yield]
|
16
|
+
end
|
17
17
|
|
18
|
-
tree.
|
18
|
+
tree.move_to_root! if transition_node.root?
|
19
19
|
|
20
|
-
|
20
|
+
finish(result)
|
21
21
|
|
22
|
-
|
22
|
+
result
|
23
|
+
rescue ::Exception => e
|
24
|
+
err!(e, transition_node)
|
25
|
+
end
|
23
26
|
|
24
|
-
|
27
|
+
def err!(exception, transition_node)
|
28
|
+
if transition_node.root?
|
29
|
+
listener.before_interruption(exception: exception, transitions: map_transitions)
|
25
30
|
|
26
|
-
|
31
|
+
reset!
|
32
|
+
end
|
27
33
|
|
28
|
-
|
34
|
+
raise exception
|
29
35
|
end
|
30
36
|
|
31
37
|
def reset!
|
@@ -38,43 +44,116 @@ module BCDD::Result::Transitions
|
|
38
44
|
track(result, time: ::Time.now.getutc)
|
39
45
|
end
|
40
46
|
|
41
|
-
def record_and_then(type_arg, arg
|
47
|
+
def record_and_then(type_arg, arg)
|
48
|
+
return yield if tree.frozen?
|
49
|
+
|
42
50
|
type = type_arg.instance_of?(::Method) ? :method : type_arg
|
43
51
|
|
44
|
-
|
45
|
-
|
46
|
-
current_and_then[:method_name] = type_arg.name if type == :method
|
52
|
+
current_and_then = { type: type, arg: arg }
|
53
|
+
current_and_then[:method_name] = type_arg.name if type == :method
|
47
54
|
|
48
|
-
|
49
|
-
|
55
|
+
tree.current.value[1] = current_and_then
|
56
|
+
|
57
|
+
scope, and_then = tree.current_value
|
50
58
|
|
51
|
-
|
59
|
+
result = nil
|
60
|
+
|
61
|
+
listener.around_and_then(scope: scope, and_then: and_then) { result = yield }
|
62
|
+
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def reset_and_then!
|
67
|
+
return if tree.frozen?
|
68
|
+
|
69
|
+
tree.current.value[1] = Tracking::EMPTY_HASH
|
52
70
|
end
|
53
71
|
|
54
72
|
private
|
55
73
|
|
74
|
+
def start(name, desc)
|
75
|
+
name_and_desc = [name, desc]
|
76
|
+
|
77
|
+
tree.frozen? ? root_start(name_and_desc) : tree.insert!(name_and_desc)
|
78
|
+
|
79
|
+
scope = tree.current.value[0]
|
80
|
+
|
81
|
+
listener.on_start(scope: scope)
|
82
|
+
|
83
|
+
[tree.current, scope]
|
84
|
+
end
|
85
|
+
|
86
|
+
def finish(result)
|
87
|
+
node = tree.current
|
88
|
+
|
89
|
+
tree.move_up!
|
90
|
+
|
91
|
+
return unless node.root?
|
92
|
+
|
93
|
+
transitions = map_transitions
|
94
|
+
|
95
|
+
result.send(:transitions=, transitions)
|
96
|
+
|
97
|
+
listener.on_finish(transitions: transitions)
|
98
|
+
|
99
|
+
reset!
|
100
|
+
end
|
101
|
+
|
56
102
|
TreeNodeValueNormalizer = ->(id, (nam, des)) { [{ id: id, name: nam, desc: des }, Tracking::EMPTY_HASH] }
|
57
103
|
|
58
104
|
def root_start(name_and_desc)
|
59
105
|
self.root_started_at = now_in_milliseconds
|
60
106
|
|
107
|
+
self.listener = build_listener
|
108
|
+
|
61
109
|
self.records = []
|
62
110
|
|
63
111
|
self.tree = Tree.new(name_and_desc, normalizer: TreeNodeValueNormalizer)
|
64
112
|
end
|
65
113
|
|
66
114
|
def track(result, time:)
|
67
|
-
|
115
|
+
record = track_record(result, time)
|
116
|
+
|
117
|
+
records << record
|
118
|
+
|
119
|
+
listener.on_record(record: record)
|
120
|
+
|
121
|
+
record
|
122
|
+
end
|
123
|
+
|
124
|
+
def track_record(result, time)
|
125
|
+
result_data = result.data.to_h
|
126
|
+
result_data[:source] = result.send(:source)
|
68
127
|
|
69
128
|
root, = tree.root_value
|
70
129
|
parent, = tree.parent_value
|
71
130
|
current, and_then = tree.current_value
|
72
131
|
|
73
|
-
|
132
|
+
{ root: root, parent: parent, current: current, result: result_data, and_then: and_then, time: time }
|
74
133
|
end
|
75
134
|
|
76
135
|
def now_in_milliseconds
|
77
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
136
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :millisecond)
|
137
|
+
end
|
138
|
+
|
139
|
+
def map_transitions
|
140
|
+
duration = (now_in_milliseconds - root_started_at)
|
141
|
+
|
142
|
+
trace_id = Config.instance.trace_id.call
|
143
|
+
|
144
|
+
metadata = { duration: duration, ids_tree: tree.nested_ids, ids_matrix: tree.ids_matrix, trace_id: trace_id }
|
145
|
+
|
146
|
+
{ version: Tracking::VERSION, records: records, metadata: metadata }
|
147
|
+
end
|
148
|
+
|
149
|
+
def build_listener
|
150
|
+
Config.instance.listener.new
|
151
|
+
rescue ::StandardError => e
|
152
|
+
err = "#{e.message} (#{e.class}); Backtrace: #{e.backtrace&.join(', ')}"
|
153
|
+
|
154
|
+
warn("Fallback to #{Listener::Null} because registered listener raised an exception: #{err}")
|
155
|
+
|
156
|
+
Listener::Null.new
|
78
157
|
end
|
79
158
|
end
|
80
159
|
end
|
@@ -6,14 +6,19 @@ class BCDD::Result
|
|
6
6
|
require_relative 'tracking/enabled'
|
7
7
|
require_relative 'tracking/disabled'
|
8
8
|
|
9
|
+
VERSION = 1
|
10
|
+
|
9
11
|
EMPTY_ARRAY = [].freeze
|
10
12
|
EMPTY_HASH = {}.freeze
|
11
13
|
EMPTY_TREE = Tree.new(nil).freeze
|
12
|
-
|
13
|
-
|
14
|
+
EMPTY = {
|
15
|
+
version: VERSION,
|
16
|
+
records: EMPTY_ARRAY,
|
17
|
+
metadata: { duration: 0, ids_tree: EMPTY_ARRAY, ids_matrix: EMPTY_HASH, trace_id: nil }.freeze
|
18
|
+
}.freeze
|
14
19
|
|
15
20
|
def self.instance
|
16
|
-
Config.instance.feature.enabled?(:transitions) ? Tracking::Enabled.new : Tracking::Disabled
|
21
|
+
::BCDD::Result::Config.instance.feature.enabled?(:transitions) ? Tracking::Enabled.new : Tracking::Disabled
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
@@ -46,9 +46,9 @@ class BCDD::Result
|
|
46
46
|
def initialize(value, normalizer: ->(_id, val) { val })
|
47
47
|
@size = 0
|
48
48
|
|
49
|
-
@root = Node.new(value, parent: nil, id:
|
49
|
+
@root = Node.new(value, parent: nil, id: size, normalizer: normalizer)
|
50
50
|
|
51
|
-
@current =
|
51
|
+
@current = root
|
52
52
|
end
|
53
53
|
|
54
54
|
def root_value
|
@@ -70,19 +70,23 @@ class BCDD::Result
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def insert!(value)
|
73
|
-
|
73
|
+
move_to! insert(value)
|
74
|
+
end
|
75
|
+
|
76
|
+
def move_to!(node)
|
77
|
+
tap { @current = node }
|
74
78
|
end
|
75
79
|
|
76
80
|
def move_up!(level = 1)
|
77
|
-
tap { level.times {
|
81
|
+
tap { level.times { move_to!(current.parent || root) } }
|
78
82
|
end
|
79
83
|
|
80
84
|
def move_down!(level = 1, index: -1)
|
81
|
-
tap { level.times { current.children[index].then { |child|
|
85
|
+
tap { level.times { current.children[index].then { |child| move_to!(child) if child } } }
|
82
86
|
end
|
83
87
|
|
84
88
|
def move_to_root!
|
85
|
-
|
89
|
+
move_to!(root)
|
86
90
|
end
|
87
91
|
|
88
92
|
NestedIds = ->(node) { [node.id, node.children.map(&NestedIds)] }
|
@@ -90,6 +94,32 @@ class BCDD::Result
|
|
90
94
|
def nested_ids
|
91
95
|
NestedIds[root]
|
92
96
|
end
|
97
|
+
|
98
|
+
IdsMatrix = ->(tree, row, col, ids, previous) do
|
99
|
+
last_row = previous[0]
|
100
|
+
|
101
|
+
tree.each_with_index do |node, index|
|
102
|
+
row = [(index + 1), last_row].max
|
103
|
+
|
104
|
+
id, leaf = node
|
105
|
+
|
106
|
+
ids[id] = previous == [row, col] ? [row, col + 1] : [row, col]
|
107
|
+
|
108
|
+
previous = ids[id]
|
109
|
+
|
110
|
+
IdsMatrix[leaf, row, col + 1, ids, previous]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def ids_matrix
|
115
|
+
current = [0, 0]
|
116
|
+
|
117
|
+
ids = { 0 => current }
|
118
|
+
|
119
|
+
IdsMatrix[nested_ids[1], 1, 1, ids, current]
|
120
|
+
|
121
|
+
ids
|
122
|
+
end
|
93
123
|
end
|
94
124
|
end
|
95
125
|
end
|
@@ -2,29 +2,26 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
module Transitions
|
5
|
+
require_relative 'transitions/listener'
|
6
|
+
require_relative 'transitions/listeners'
|
7
|
+
require_relative 'transitions/config'
|
5
8
|
require_relative 'transitions/tree'
|
6
9
|
require_relative 'transitions/tracking'
|
7
10
|
|
8
11
|
THREAD_VAR_NAME = :bcdd_result_transitions_tracking
|
9
12
|
|
13
|
+
EnsureResult = ->(result) do
|
14
|
+
return result if result.is_a?(::BCDD::Result)
|
15
|
+
|
16
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: :transitions)
|
17
|
+
end
|
18
|
+
|
10
19
|
def self.tracking
|
11
20
|
Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
|
12
21
|
end
|
13
22
|
end
|
14
23
|
|
15
|
-
def self.transitions(name: nil, desc: nil)
|
16
|
-
Transitions.tracking.
|
17
|
-
|
18
|
-
result = yield
|
19
|
-
|
20
|
-
result.is_a?(::BCDD::Result) or raise Error::UnexpectedOutcome.build(outcome: result, origin: :transitions)
|
21
|
-
|
22
|
-
Transitions.tracking.finish(result: result)
|
23
|
-
|
24
|
-
result
|
25
|
-
rescue ::Exception => e
|
26
|
-
Transitions.tracking.reset!
|
27
|
-
|
28
|
-
raise e
|
24
|
+
def self.transitions(name: nil, desc: nil, &block)
|
25
|
+
Transitions.tracking.exec(name, desc, &block)
|
29
26
|
end
|
30
27
|
end
|
data/lib/bcdd/result/version.rb
CHANGED
data/lib/bcdd/result.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
4
|
+
require 'singleton'
|
5
|
+
|
3
6
|
require_relative 'result/version'
|
4
|
-
require_relative 'result/transitions'
|
5
7
|
require_relative 'result/error'
|
8
|
+
require_relative 'result/ignored_types'
|
9
|
+
require_relative 'result/transitions'
|
10
|
+
require_relative 'result/callable_and_then'
|
6
11
|
require_relative 'result/data'
|
7
12
|
require_relative 'result/handler'
|
8
13
|
require_relative 'result/failure'
|
@@ -16,9 +21,9 @@ require_relative 'result/config'
|
|
16
21
|
class BCDD::Result
|
17
22
|
attr_accessor :unknown, :transitions
|
18
23
|
|
19
|
-
attr_reader :
|
24
|
+
attr_reader :source, :data, :type_checker, :terminal
|
20
25
|
|
21
|
-
protected :
|
26
|
+
protected :source
|
22
27
|
|
23
28
|
private :unknown, :unknown=, :type_checker, :transitions=
|
24
29
|
|
@@ -26,18 +31,18 @@ class BCDD::Result
|
|
26
31
|
Config.instance
|
27
32
|
end
|
28
33
|
|
29
|
-
def self.configuration
|
34
|
+
def self.configuration(freeze: true)
|
30
35
|
yield(config)
|
31
36
|
|
32
|
-
config.freeze
|
37
|
+
freeze and config.freeze
|
33
38
|
end
|
34
39
|
|
35
|
-
def initialize(type:, value:,
|
40
|
+
def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
|
36
41
|
data = Data.new(kind, type, value)
|
37
42
|
|
38
43
|
@type_checker = Contract.evaluate(data, expectations)
|
39
|
-
@
|
40
|
-
@terminal =
|
44
|
+
@source = source
|
45
|
+
@terminal = kind == :failure || (terminal && !IgnoredTypes.include?(type))
|
41
46
|
@data = data
|
42
47
|
|
43
48
|
self.unknown = true
|
@@ -88,12 +93,20 @@ class BCDD::Result
|
|
88
93
|
tap { yield(value, type) if unknown }
|
89
94
|
end
|
90
95
|
|
91
|
-
def and_then(method_name = nil,
|
96
|
+
def and_then(method_name = nil, injected_value = nil, &block)
|
92
97
|
return self if terminal?
|
93
98
|
|
94
99
|
method_name && block and raise ::ArgumentError, 'method_name and block are mutually exclusive'
|
95
100
|
|
96
|
-
method_name ?
|
101
|
+
method_name ? call_and_then_source_method(method_name, injected_value) : call_and_then_block(block)
|
102
|
+
end
|
103
|
+
|
104
|
+
def and_then!(source, injected_value = nil, _call: nil)
|
105
|
+
raise Error::CallableAndThenDisabled unless Config.instance.feature.enabled?(:and_then!)
|
106
|
+
|
107
|
+
return self if terminal?
|
108
|
+
|
109
|
+
call_and_then_callable!(source, value: value, injected_value: injected_value, method_name: _call)
|
97
110
|
end
|
98
111
|
|
99
112
|
def handle
|
@@ -139,27 +152,27 @@ class BCDD::Result
|
|
139
152
|
block.call(value, type)
|
140
153
|
end
|
141
154
|
|
142
|
-
def
|
143
|
-
method =
|
155
|
+
def call_and_then_source_method(method_name, injected_value)
|
156
|
+
method = source.method(method_name)
|
144
157
|
|
145
|
-
Transitions.tracking.record_and_then(method,
|
146
|
-
result =
|
158
|
+
Transitions.tracking.record_and_then(method, injected_value) do
|
159
|
+
result = call_and_then_source_method!(method, injected_value)
|
147
160
|
|
148
161
|
ensure_result_object(result, origin: :method)
|
149
162
|
end
|
150
163
|
end
|
151
164
|
|
152
|
-
def
|
165
|
+
def call_and_then_source_method!(method, injected_value)
|
153
166
|
case method.arity
|
154
|
-
when 0 then
|
155
|
-
when 1 then
|
156
|
-
when 2 then
|
157
|
-
else raise Error::
|
167
|
+
when 0 then source.send(method.name)
|
168
|
+
when 1 then source.send(method.name, value)
|
169
|
+
when 2 then source.send(method.name, value, injected_value)
|
170
|
+
else raise Error::InvalidSourceMethodArity.build(source: source, method: method, max_arity: 2)
|
158
171
|
end
|
159
172
|
end
|
160
173
|
|
161
174
|
def call_and_then_block(block)
|
162
|
-
Transitions.tracking.record_and_then(:block, nil
|
175
|
+
Transitions.tracking.record_and_then(:block, nil) do
|
163
176
|
result = call_and_then_block!(block)
|
164
177
|
|
165
178
|
ensure_result_object(result, origin: :block)
|
@@ -170,11 +183,15 @@ class BCDD::Result
|
|
170
183
|
block.call(value)
|
171
184
|
end
|
172
185
|
|
186
|
+
def call_and_then_callable!(source, value:, injected_value:, method_name:)
|
187
|
+
CallableAndThen::Caller.call(source, value: value, injected_value: injected_value, method_name: method_name)
|
188
|
+
end
|
189
|
+
|
173
190
|
def ensure_result_object(result, origin:)
|
174
191
|
raise Error::UnexpectedOutcome.build(outcome: result, origin: origin) unless result.is_a?(::BCDD::Result)
|
175
192
|
|
176
|
-
return result if result.
|
193
|
+
return result if result.source.equal?(source)
|
177
194
|
|
178
|
-
raise Error::
|
195
|
+
raise Error::InvalidResultSource.build(given_result: result, expected_source: source)
|
179
196
|
end
|
180
197
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module BCDD::Result::CallableAndThen
|
2
|
+
class Config
|
3
|
+
attr_accessor default_method_name_to_call: Symbol
|
4
|
+
|
5
|
+
def initialize: -> void
|
6
|
+
|
7
|
+
def options: () -> Hash[Symbol, untyped]
|
8
|
+
end
|
9
|
+
|
10
|
+
class Error < BCDD::Result::Error
|
11
|
+
end
|
12
|
+
|
13
|
+
class Error::InvalidArity < Error
|
14
|
+
def self.build: (
|
15
|
+
source: untyped,
|
16
|
+
method: Symbol,
|
17
|
+
arity: String
|
18
|
+
) -> Error::InvalidArity
|
19
|
+
end
|
20
|
+
|
21
|
+
class Caller
|
22
|
+
def self.call: (
|
23
|
+
untyped source,
|
24
|
+
value: untyped,
|
25
|
+
injected_value: untyped,
|
26
|
+
method_name: (Symbol | nil)
|
27
|
+
) -> BCDD::Result
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.call_proc!: (
|
32
|
+
untyped source,
|
33
|
+
untyped value,
|
34
|
+
untyped injected_value
|
35
|
+
) -> BCDD::Result
|
36
|
+
|
37
|
+
def self.call_method!: (
|
38
|
+
untyped source,
|
39
|
+
Method method,
|
40
|
+
untyped value,
|
41
|
+
untyped injected_value
|
42
|
+
) -> BCDD::Result
|
43
|
+
|
44
|
+
def self.callable_method: (
|
45
|
+
untyped source,
|
46
|
+
(Symbol | nil) method_name
|
47
|
+
) -> ::Method
|
48
|
+
|
49
|
+
def self.ensure_result_object: (
|
50
|
+
untyped source,
|
51
|
+
untyped value,
|
52
|
+
BCDD::Result result
|
53
|
+
) -> BCDD::Result
|
54
|
+
|
55
|
+
def self.expected_result_object: () -> singleton(BCDD::Result)
|
56
|
+
|
57
|
+
def self.expected_outcome: () -> String
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/sig/bcdd/result/config.rbs
CHANGED
@@ -14,6 +14,9 @@ class BCDD::Result::Config
|
|
14
14
|
|
15
15
|
def initialize: -> void
|
16
16
|
|
17
|
+
def and_then!: () -> BCDD::Result::CallableAndThen::Config
|
18
|
+
def transitions: () -> BCDD::Result::Transitions::Config
|
19
|
+
|
17
20
|
def freeze: -> BCDD::Result::Config
|
18
21
|
def options: -> Hash[Symbol, BCDD::Result::Config::Switcher]
|
19
22
|
def to_h: -> Hash[Symbol, Hash[Symbol | String, bool]]
|
data/sig/bcdd/result/context.rbs
CHANGED
@@ -1,38 +1,99 @@
|
|
1
1
|
class BCDD::Result::Context < BCDD::Result
|
2
2
|
EXPECTED_OUTCOME: String
|
3
3
|
|
4
|
-
|
4
|
+
SourceMethodArity: ^(Method) -> Integer
|
5
5
|
|
6
6
|
attr_reader acc: Hash[Symbol, untyped]
|
7
7
|
|
8
8
|
def initialize: (
|
9
9
|
type: Symbol,
|
10
10
|
value: untyped,
|
11
|
-
?
|
11
|
+
?source: untyped,
|
12
12
|
?expectations: BCDD::Result::Contract::Evaluator,
|
13
13
|
?terminal: bool
|
14
14
|
) -> void
|
15
15
|
|
16
|
-
def and_then: (?Symbol, **untyped) ?{ (Hash[Symbol, untyped]) -> untyped } ->
|
16
|
+
def and_then: (?Symbol, **untyped) ?{ (Hash[Symbol, untyped]) -> untyped } -> untyped
|
17
|
+
|
18
|
+
def and_then!: (untyped, **untyped) -> untyped
|
17
19
|
|
18
20
|
private
|
19
21
|
|
20
|
-
def
|
22
|
+
def call_and_then_source_method: (Symbol, Hash[Symbol, untyped]) -> BCDD::Result::Context
|
23
|
+
|
24
|
+
def call_and_then_callable!: (untyped, value: untyped, injected_value: untyped, method_name: (Symbol | nil)) -> BCDD::Result::Context
|
25
|
+
|
21
26
|
def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result::Context
|
22
27
|
|
23
28
|
def raise_unexpected_outcome_error: (BCDD::Result::Context | untyped, Symbol) -> void
|
24
29
|
end
|
25
30
|
|
31
|
+
class BCDD::Result::Context
|
32
|
+
class Error < BCDD::Result::Error
|
33
|
+
class InvalidExposure < BCDD::Result::Context::Error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
26
38
|
class BCDD::Result::Context
|
27
39
|
class Success < BCDD::Result::Context
|
28
40
|
include BCDD::Result::Success::Methods
|
29
41
|
|
42
|
+
FetchValues: Proc
|
43
|
+
|
30
44
|
def and_expose: (Symbol, Array[Symbol], terminal: bool) -> BCDD::Result::Context::Success
|
31
45
|
end
|
32
46
|
|
33
47
|
def self.Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
|
34
48
|
end
|
35
49
|
|
50
|
+
module BCDD::Result::Context::CallableAndThen
|
51
|
+
class Caller < BCDD::Result::CallableAndThen::Caller
|
52
|
+
module KeyArgs
|
53
|
+
def self.parameters?: (untyped) -> bool
|
54
|
+
|
55
|
+
def self.invalid_arity: (untyped, Symbol) -> BCDD::Result::CallableAndThen::Error::InvalidArity
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.call: (
|
59
|
+
untyped source,
|
60
|
+
value: untyped,
|
61
|
+
injected_value: untyped,
|
62
|
+
method_name: (Symbol | nil),
|
63
|
+
) -> BCDD::Result::Context
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def self.call_proc!: (
|
68
|
+
untyped source,
|
69
|
+
Hash[Symbol, untyped] value,
|
70
|
+
nil injected_value
|
71
|
+
) -> BCDD::Result::Context
|
72
|
+
|
73
|
+
def self.call_method!: (
|
74
|
+
untyped source,
|
75
|
+
Method method,
|
76
|
+
Hash[Symbol, untyped] value,
|
77
|
+
nil injected_value
|
78
|
+
) -> BCDD::Result::Context
|
79
|
+
|
80
|
+
def self.callable_method: (
|
81
|
+
untyped source,
|
82
|
+
(Symbol | nil) method_name
|
83
|
+
) -> ::Method
|
84
|
+
|
85
|
+
def self.ensure_result_object: (
|
86
|
+
untyped source,
|
87
|
+
untyped value,
|
88
|
+
BCDD::Result::Context result
|
89
|
+
) -> BCDD::Result::Context
|
90
|
+
|
91
|
+
def self.expected_result_object: () -> singleton(BCDD::Result::Context)
|
92
|
+
|
93
|
+
def self.expected_outcome: () -> String
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
36
97
|
class BCDD::Result::Context
|
37
98
|
class Failure < BCDD::Result::Context
|
38
99
|
include BCDD::Result::Failure::Methods
|
data/sig/bcdd/result/error.rbs
CHANGED
@@ -13,19 +13,22 @@ class BCDD::Result
|
|
13
13
|
-> BCDD::Result::Error::UnexpectedOutcome
|
14
14
|
end
|
15
15
|
|
16
|
-
class
|
17
|
-
def self.build: (given_result: BCDD::Result,
|
18
|
-
-> BCDD::Result::Error::
|
16
|
+
class InvalidResultSource < BCDD::Result::Error
|
17
|
+
def self.build: (given_result: BCDD::Result, expected_source: untyped)
|
18
|
+
-> BCDD::Result::Error::InvalidResultSource
|
19
19
|
end
|
20
20
|
|
21
|
-
class
|
22
|
-
def self.build: (
|
23
|
-
-> BCDD::Result::Error::
|
21
|
+
class InvalidSourceMethodArity < BCDD::Result::Error
|
22
|
+
def self.build: (source: untyped, method: Method, max_arity: Integer)
|
23
|
+
-> BCDD::Result::Error::InvalidSourceMethodArity
|
24
24
|
end
|
25
25
|
|
26
26
|
class UnhandledTypes < BCDD::Result::Error
|
27
27
|
def self.build: (types: Set[Symbol])
|
28
28
|
-> BCDD::Result::Error::UnhandledTypes
|
29
29
|
end
|
30
|
+
|
31
|
+
class CallableAndThenDisabled < BCDD::Result::Error
|
32
|
+
end
|
30
33
|
end
|
31
34
|
end
|
@@ -16,14 +16,14 @@ class BCDD::Result::Expectations
|
|
16
16
|
def self.result_factory_without_expectations: -> singleton(BCDD::Result)
|
17
17
|
|
18
18
|
def self.new: (
|
19
|
-
?
|
19
|
+
?source: untyped,
|
20
20
|
?contract: BCDD::Result::Contract::Evaluator,
|
21
21
|
?terminal: bool,
|
22
22
|
**untyped
|
23
23
|
) -> (BCDD::Result::Expectations | untyped)
|
24
24
|
|
25
25
|
def initialize: (
|
26
|
-
?
|
26
|
+
?source: untyped,
|
27
27
|
?contract: BCDD::Result::Contract::Evaluator,
|
28
28
|
?terminal: bool,
|
29
29
|
**untyped
|
@@ -32,13 +32,13 @@ class BCDD::Result::Expectations
|
|
32
32
|
def Success: (Symbol, ?untyped) -> BCDD::Result::Success
|
33
33
|
def Failure: (Symbol, ?untyped) -> BCDD::Result::Failure
|
34
34
|
|
35
|
-
def with: (
|
35
|
+
def with: (source: untyped) -> BCDD::Result::Expectations
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def _ResultAs: (singleton(BCDD::Result), Symbol, untyped) -> untyped
|
40
40
|
|
41
|
-
attr_reader
|
41
|
+
attr_reader source: untyped
|
42
42
|
attr_reader contract: BCDD::Result::Contract::Evaluator
|
43
43
|
attr_reader terminal: bool
|
44
44
|
end
|