bcdd-result 0.13.0 → 1.1.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 +4 -4
- data/CHANGELOG.md +61 -21
- data/README.md +397 -227
- data/Rakefile +1 -1
- data/Steepfile +1 -1
- data/examples/multiple_listeners/Rakefile +8 -8
- data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
- data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
- data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
- data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
- data/examples/multiple_listeners/config.rb +3 -3
- data/examples/multiple_listeners/db/setup.rb +2 -3
- data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
- data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
- data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
- data/examples/service_objects/Rakefile +36 -0
- data/examples/service_objects/app/models/account/member.rb +10 -0
- data/examples/service_objects/app/models/account.rb +11 -0
- data/examples/service_objects/app/models/user/token.rb +7 -0
- data/examples/service_objects/app/models/user.rb +15 -0
- data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
- data/examples/service_objects/app/services/application_service.rb +79 -0
- data/examples/service_objects/app/services/user/creation.rb +56 -0
- data/examples/service_objects/app/services/user/token/creation.rb +37 -0
- data/examples/service_objects/config/boot.rb +17 -0
- data/examples/service_objects/config/initializers/bcdd.rb +9 -0
- data/examples/service_objects/config.rb +20 -0
- data/examples/service_objects/db/setup.rb +49 -0
- data/examples/single_listener/Rakefile +5 -5
- data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
- data/examples/single_listener/app/models/user/creation.rb +1 -1
- data/examples/single_listener/app/models/user/token/creation.rb +1 -1
- data/examples/single_listener/config/initializers/bcdd.rb +0 -2
- data/examples/single_listener/config.rb +1 -1
- data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
- data/lib/bcdd/{result/context → context}/callable_and_then.rb +6 -5
- data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
- data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
- data/lib/bcdd/context/failure.rb +9 -0
- data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
- data/lib/bcdd/{result/context → context}/success.rb +11 -11
- data/lib/bcdd/context.rb +115 -0
- data/lib/bcdd/failure.rb +23 -0
- data/lib/bcdd/result/_self.rb +198 -0
- data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
- data/lib/bcdd/result/config/switchers/addons.rb +2 -2
- data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
- data/lib/bcdd/result/config/switchers/features.rb +5 -5
- data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
- data/lib/bcdd/result/config.rb +7 -5
- data/lib/bcdd/result/contract/type_checker.rb +4 -0
- data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
- data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
- data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
- data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
- data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
- data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
- data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
- data/lib/bcdd/result/event_logs.rb +27 -0
- data/lib/bcdd/result/failure.rb +1 -3
- data/lib/bcdd/result/success.rb +1 -3
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +23 -191
- data/lib/bcdd/success.rb +23 -0
- data/sig/bcdd/context.rbs +175 -0
- data/sig/bcdd/failure.rbs +13 -0
- data/sig/bcdd/result/config.rbs +1 -3
- data/sig/bcdd/result/context.rbs +2 -174
- data/sig/bcdd/result/contract.rbs +1 -0
- data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
- data/sig/bcdd/result.rbs +13 -31
- data/sig/bcdd/success.rbs +13 -0
- metadata +41 -24
- data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
- data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
- data/lib/bcdd/result/context/failure.rb +0 -9
- data/lib/bcdd/result/context.rb +0 -93
- data/lib/bcdd/result/failure/methods.rb +0 -21
- data/lib/bcdd/result/success/methods.rb +0 -21
- data/lib/bcdd/result/transitions.rb +0 -27
@@ -6,20 +6,20 @@ class BCDD::Result
|
|
6
6
|
OPTIONS = {
|
7
7
|
expectations: {
|
8
8
|
default: true,
|
9
|
-
affects: %w[BCDD::Result::Expectations BCDD::
|
9
|
+
affects: %w[BCDD::Result::Expectations BCDD::Context::Expectations]
|
10
10
|
},
|
11
|
-
|
11
|
+
event_logs: {
|
12
12
|
default: true,
|
13
|
-
affects: %w[BCDD::Result BCDD::
|
13
|
+
affects: %w[BCDD::Result BCDD::Context BCDD::Result::Expectations BCDD::Context::Expectations]
|
14
14
|
},
|
15
15
|
and_then!: {
|
16
16
|
default: false,
|
17
|
-
affects: %w[BCDD::Result BCDD::
|
17
|
+
affects: %w[BCDD::Result BCDD::Context BCDD::Result::Expectations BCDD::Context::Expectations]
|
18
18
|
}
|
19
19
|
}.transform_values!(&:freeze).freeze
|
20
20
|
|
21
21
|
Listener = ->(option_name, _bool) do
|
22
|
-
Thread.current[
|
22
|
+
Thread.current[EventLogs::THREAD_VAR_NAME] = nil if option_name == :event_logs
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.switcher
|
@@ -6,7 +6,7 @@ class BCDD::Result
|
|
6
6
|
OPTIONS = {
|
7
7
|
nil_as_valid_value_checking: {
|
8
8
|
default: false,
|
9
|
-
affects: %w[BCDD::Result::Expectations BCDD::
|
9
|
+
affects: %w[BCDD::Result::Expectations BCDD::Context::Expectations]
|
10
10
|
}
|
11
11
|
}.transform_values!(&:freeze).freeze
|
12
12
|
|
data/lib/bcdd/result/config.rb
CHANGED
@@ -9,8 +9,6 @@ require_relative 'config/switchers/pattern_matching'
|
|
9
9
|
|
10
10
|
class BCDD::Result
|
11
11
|
class Config
|
12
|
-
include ::Singleton
|
13
|
-
|
14
12
|
attr_reader :addon, :feature, :constant_alias, :pattern_matching
|
15
13
|
|
16
14
|
def initialize
|
@@ -21,8 +19,8 @@ class BCDD::Result
|
|
21
19
|
@and_then_ = CallableAndThen::Config.new
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
|
22
|
+
def event_logs
|
23
|
+
EventLogs::Config.instance
|
26
24
|
end
|
27
25
|
|
28
26
|
def and_then!
|
@@ -35,7 +33,7 @@ class BCDD::Result
|
|
35
33
|
constant_alias.freeze
|
36
34
|
pattern_matching.freeze
|
37
35
|
and_then!.freeze
|
38
|
-
|
36
|
+
event_logs.freeze
|
39
37
|
|
40
38
|
super
|
41
39
|
end
|
@@ -58,5 +56,9 @@ class BCDD::Result
|
|
58
56
|
"options=#{options.keys.sort.inspect} " \
|
59
57
|
"and_then!=#{and_then!.options.inspect}>"
|
60
58
|
end
|
59
|
+
|
60
|
+
@instance = new
|
61
|
+
|
62
|
+
singleton_class.send(:attr_reader, :instance)
|
61
63
|
end
|
62
64
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Config
|
5
|
-
include ::Singleton
|
6
|
-
|
7
5
|
attr_reader :listener, :trace_id
|
8
6
|
|
9
7
|
def initialize
|
@@ -22,5 +20,9 @@ module BCDD::Result::Transitions
|
|
22
20
|
|
23
21
|
@trace_id = arg
|
24
22
|
end
|
23
|
+
|
24
|
+
@instance = new
|
25
|
+
|
26
|
+
singleton_class.send(:attr_reader, :instance)
|
25
27
|
end
|
26
28
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
module Listener
|
5
5
|
module ClassMethods
|
6
|
-
def
|
6
|
+
def around_event_logs?
|
7
7
|
false
|
8
8
|
end
|
9
9
|
|
@@ -26,7 +26,7 @@ module BCDD::Result::Transitions
|
|
26
26
|
|
27
27
|
def on_start(scope:); end
|
28
28
|
|
29
|
-
def
|
29
|
+
def around_event_logs(scope:)
|
30
30
|
yield
|
31
31
|
end
|
32
32
|
|
@@ -36,9 +36,9 @@ module BCDD::Result::Transitions
|
|
36
36
|
|
37
37
|
def on_record(record:); end
|
38
38
|
|
39
|
-
def on_finish(
|
39
|
+
def on_finish(event_logs:); end
|
40
40
|
|
41
|
-
def before_interruption(exception:,
|
41
|
+
def before_interruption(exception:, event_logs:); end
|
42
42
|
end
|
43
43
|
|
44
44
|
module Listener::Null
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Listeners
|
5
5
|
class Chain
|
6
6
|
include Listener
|
@@ -13,26 +13,26 @@ module BCDD::Result::Transitions
|
|
13
13
|
end
|
14
14
|
|
15
15
|
around_and_then = list.select(&:around_and_then?)
|
16
|
-
|
16
|
+
around_event_logs = list.select(&:around_event_logs?)
|
17
17
|
|
18
18
|
raise ArgumentError, 'only one listener can have around_and_then? == true' if around_and_then.size > 1
|
19
|
-
raise ArgumentError, 'only one listener can have
|
19
|
+
raise ArgumentError, 'only one listener can have around_event_logs? == true' if around_event_logs.size > 1
|
20
20
|
|
21
|
-
@listeners = { list: list, around_and_then: around_and_then[0],
|
21
|
+
@listeners = { list: list, around_and_then: around_and_then[0], around_event_logs: around_event_logs[0] }
|
22
22
|
end
|
23
23
|
|
24
24
|
def new
|
25
|
-
list, around_and_then,
|
25
|
+
list, around_and_then, around_event_logs = listeners[:list], nil, nil
|
26
26
|
|
27
27
|
instances = list.map do |item|
|
28
28
|
instance = item.new
|
29
29
|
around_and_then = instance if listener?(:around_and_then, instance)
|
30
|
-
|
30
|
+
around_event_logs = instance if listener?(:around_event_logs, instance)
|
31
31
|
|
32
32
|
instance
|
33
33
|
end
|
34
34
|
|
35
|
-
list.one? ? list[0].new : Listeners.send(:new, instances, around_and_then,
|
35
|
+
list.one? ? list[0].new : Listeners.send(:new, instances, around_and_then, around_event_logs)
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
@@ -50,22 +50,22 @@ module BCDD::Result::Transitions
|
|
50
50
|
Chain.new(listeners)
|
51
51
|
end
|
52
52
|
|
53
|
-
attr_reader :listeners, :around_and_then_listener, :
|
53
|
+
attr_reader :listeners, :around_and_then_listener, :around_event_logs_listener
|
54
54
|
|
55
|
-
private :listeners, :around_and_then_listener, :
|
55
|
+
private :listeners, :around_and_then_listener, :around_event_logs_listener
|
56
56
|
|
57
|
-
def initialize(listeners, around_and_then_listener,
|
57
|
+
def initialize(listeners, around_and_then_listener, around_event_logs_listener)
|
58
58
|
@listeners = listeners
|
59
59
|
@around_and_then_listener = around_and_then_listener || Listener::Null
|
60
|
-
@
|
60
|
+
@around_event_logs_listener = around_event_logs_listener || Listener::Null
|
61
61
|
end
|
62
62
|
|
63
63
|
def on_start(scope:)
|
64
64
|
listeners.each { _1.on_start(scope: scope) }
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
68
|
-
|
67
|
+
def around_event_logs(scope:, &block)
|
68
|
+
around_event_logs_listener.around_event_logs(scope: scope, &block)
|
69
69
|
end
|
70
70
|
|
71
71
|
def around_and_then(scope:, and_then:, &block)
|
@@ -76,12 +76,12 @@ module BCDD::Result::Transitions
|
|
76
76
|
listeners.each { _1.on_record(record: record) }
|
77
77
|
end
|
78
78
|
|
79
|
-
def on_finish(
|
80
|
-
listeners.each { _1.on_finish(
|
79
|
+
def on_finish(event_logs:)
|
80
|
+
listeners.each { _1.on_finish(event_logs: event_logs) }
|
81
81
|
end
|
82
82
|
|
83
|
-
def before_interruption(exception:,
|
84
|
-
listeners.each { _1.before_interruption(exception: exception,
|
83
|
+
def before_interruption(exception:, event_logs:)
|
84
|
+
listeners.each { _1.before_interruption(exception: exception, event_logs: event_logs) }
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -1,32 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Tracking::Enabled
|
5
5
|
attr_accessor :tree, :records, :root_started_at, :listener
|
6
6
|
|
7
7
|
private :tree, :tree=, :records, :records=, :root_started_at, :root_started_at=, :listener, :listener=
|
8
8
|
|
9
9
|
def exec(name, desc)
|
10
|
-
|
10
|
+
event_log_node, scope = start(name, desc)
|
11
11
|
|
12
12
|
result = nil
|
13
13
|
|
14
|
-
listener.
|
14
|
+
listener.around_event_logs(scope: scope) do
|
15
15
|
result = EnsureResult[yield]
|
16
16
|
end
|
17
17
|
|
18
|
-
tree.move_to_root! if
|
18
|
+
tree.move_to_root! if event_log_node.root?
|
19
19
|
|
20
20
|
finish(result)
|
21
21
|
|
22
22
|
result
|
23
23
|
rescue ::Exception => e
|
24
|
-
err!(e,
|
24
|
+
err!(e, event_log_node)
|
25
25
|
end
|
26
26
|
|
27
|
-
def err!(exception,
|
28
|
-
if
|
29
|
-
listener.before_interruption(exception: exception,
|
27
|
+
def err!(exception, event_log_node)
|
28
|
+
if event_log_node.root?
|
29
|
+
listener.before_interruption(exception: exception, event_logs: map_event_logs)
|
30
30
|
|
31
31
|
reset!
|
32
32
|
end
|
@@ -90,11 +90,11 @@ module BCDD::Result::Transitions
|
|
90
90
|
|
91
91
|
return unless node.root?
|
92
92
|
|
93
|
-
|
93
|
+
event_logs = map_event_logs
|
94
94
|
|
95
|
-
result.send(:
|
95
|
+
result.send(:event_logs=, event_logs)
|
96
96
|
|
97
|
-
listener.on_finish(
|
97
|
+
listener.on_finish(event_logs: event_logs)
|
98
98
|
|
99
99
|
reset!
|
100
100
|
end
|
@@ -136,12 +136,14 @@ module BCDD::Result::Transitions
|
|
136
136
|
::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :millisecond)
|
137
137
|
end
|
138
138
|
|
139
|
-
def
|
139
|
+
def map_event_logs
|
140
140
|
duration = (now_in_milliseconds - root_started_at)
|
141
141
|
|
142
142
|
trace_id = Config.instance.trace_id.call
|
143
143
|
|
144
|
-
|
144
|
+
ids = { tree: tree.ids, matrix: tree.ids_matrix, level_parent: tree.ids_level_parent }
|
145
|
+
|
146
|
+
metadata = { duration: duration, trace_id: trace_id, ids: ids }
|
145
147
|
|
146
148
|
{ version: Tracking::VERSION, records: records, metadata: metadata }
|
147
149
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
|
-
module
|
4
|
+
module EventLogs
|
5
5
|
module Tracking
|
6
6
|
require_relative 'tracking/enabled'
|
7
7
|
require_relative 'tracking/disabled'
|
@@ -11,14 +11,15 @@ class BCDD::Result
|
|
11
11
|
EMPTY_ARRAY = [].freeze
|
12
12
|
EMPTY_HASH = {}.freeze
|
13
13
|
EMPTY_TREE = Tree.new(nil).freeze
|
14
|
+
EMPTY_IDS = { tree: EMPTY_ARRAY, matrix: EMPTY_HASH, level_parent: EMPTY_HASH }.freeze
|
14
15
|
EMPTY = {
|
15
16
|
version: VERSION,
|
16
17
|
records: EMPTY_ARRAY,
|
17
|
-
metadata: { duration: 0,
|
18
|
+
metadata: { duration: 0, ids: EMPTY_IDS, trace_id: nil }.freeze
|
18
19
|
}.freeze
|
19
20
|
|
20
21
|
def self.instance
|
21
|
-
::BCDD::Result::Config.instance.feature.enabled?(:
|
22
|
+
::BCDD::Result::Config.instance.feature.enabled?(:event_logs) ? Tracking::Enabled.new : Tracking::Disabled
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
|
-
module
|
4
|
+
module EventLogs
|
5
5
|
class Tree
|
6
6
|
class Node
|
7
7
|
attr_reader :id, :value, :parent, :normalizer, :children
|
@@ -89,13 +89,17 @@ class BCDD::Result
|
|
89
89
|
move_to!(root)
|
90
90
|
end
|
91
91
|
|
92
|
-
|
92
|
+
Ids = ->(node) { [node.id, node.children.map(&Ids)] }
|
93
93
|
|
94
|
-
def
|
95
|
-
|
94
|
+
def ids
|
95
|
+
Ids[root]
|
96
96
|
end
|
97
97
|
|
98
|
-
|
98
|
+
def ids_list
|
99
|
+
ids.flatten
|
100
|
+
end
|
101
|
+
|
102
|
+
IdsMatrix = ->(tree, row, col, memo, previous) do
|
99
103
|
last_row = previous[0]
|
100
104
|
|
101
105
|
tree.each_with_index do |node, index|
|
@@ -103,22 +107,34 @@ class BCDD::Result
|
|
103
107
|
|
104
108
|
id, leaf = node
|
105
109
|
|
106
|
-
|
110
|
+
memo[id] = previous == [row, col] ? [row, col + 1] : [row, col]
|
107
111
|
|
108
|
-
previous =
|
112
|
+
previous = memo[id]
|
109
113
|
|
110
|
-
IdsMatrix[leaf, row, col + 1,
|
114
|
+
IdsMatrix[leaf, row, col + 1, memo, previous]
|
111
115
|
end
|
112
116
|
end
|
113
117
|
|
114
118
|
def ids_matrix
|
115
119
|
current = [0, 0]
|
116
120
|
|
117
|
-
|
121
|
+
memo = { 0 => current }
|
122
|
+
|
123
|
+
IdsMatrix[ids[1], 1, 1, memo, current]
|
124
|
+
|
125
|
+
memo
|
126
|
+
end
|
127
|
+
|
128
|
+
IdsLevelParent = ->((id, node), parent = 0, level = 0, memo = {}) do
|
129
|
+
memo[id] = [level, parent]
|
118
130
|
|
119
|
-
|
131
|
+
node.each { |leaf| IdsLevelParent[leaf, id, level + 1, memo] }
|
132
|
+
|
133
|
+
memo
|
134
|
+
end
|
120
135
|
|
121
|
-
|
136
|
+
def ids_level_parent
|
137
|
+
IdsLevelParent[ids]
|
122
138
|
end
|
123
139
|
end
|
124
140
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
module EventLogs
|
5
|
+
require_relative 'event_logs/listener'
|
6
|
+
require_relative 'event_logs/listeners'
|
7
|
+
require_relative 'event_logs/config'
|
8
|
+
require_relative 'event_logs/tree'
|
9
|
+
require_relative 'event_logs/tracking'
|
10
|
+
|
11
|
+
THREAD_VAR_NAME = :bcdd_result_event_logs_tracking
|
12
|
+
|
13
|
+
EnsureResult = ->(result) do
|
14
|
+
return result if result.is_a?(::BCDD::Result)
|
15
|
+
|
16
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: :event_logs)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.tracking
|
20
|
+
Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.event_logs(name: nil, desc: nil, &block)
|
25
|
+
EventLogs.tracking.exec(name, desc, &block)
|
26
|
+
end
|
27
|
+
end
|
data/lib/bcdd/result/failure.rb
CHANGED
data/lib/bcdd/result/success.rb
CHANGED