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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +61 -21
  4. data/README.md +397 -227
  5. data/Rakefile +1 -1
  6. data/Steepfile +1 -1
  7. data/examples/multiple_listeners/Rakefile +8 -8
  8. data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
  9. data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
  10. data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
  11. data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
  12. data/examples/multiple_listeners/config.rb +3 -3
  13. data/examples/multiple_listeners/db/setup.rb +2 -3
  14. data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
  15. data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
  16. data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
  17. data/examples/service_objects/Rakefile +36 -0
  18. data/examples/service_objects/app/models/account/member.rb +10 -0
  19. data/examples/service_objects/app/models/account.rb +11 -0
  20. data/examples/service_objects/app/models/user/token.rb +7 -0
  21. data/examples/service_objects/app/models/user.rb +15 -0
  22. data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
  23. data/examples/service_objects/app/services/application_service.rb +79 -0
  24. data/examples/service_objects/app/services/user/creation.rb +56 -0
  25. data/examples/service_objects/app/services/user/token/creation.rb +37 -0
  26. data/examples/service_objects/config/boot.rb +17 -0
  27. data/examples/service_objects/config/initializers/bcdd.rb +9 -0
  28. data/examples/service_objects/config.rb +20 -0
  29. data/examples/service_objects/db/setup.rb +49 -0
  30. data/examples/single_listener/Rakefile +5 -5
  31. data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
  32. data/examples/single_listener/app/models/user/creation.rb +1 -1
  33. data/examples/single_listener/app/models/user/token/creation.rb +1 -1
  34. data/examples/single_listener/config/initializers/bcdd.rb +0 -2
  35. data/examples/single_listener/config.rb +1 -1
  36. data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
  37. data/lib/bcdd/{result/context → context}/callable_and_then.rb +6 -5
  38. data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
  39. data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
  40. data/lib/bcdd/context/failure.rb +9 -0
  41. data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
  42. data/lib/bcdd/{result/context → context}/success.rb +11 -11
  43. data/lib/bcdd/context.rb +115 -0
  44. data/lib/bcdd/failure.rb +23 -0
  45. data/lib/bcdd/result/_self.rb +198 -0
  46. data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
  47. data/lib/bcdd/result/config/switchers/addons.rb +2 -2
  48. data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
  49. data/lib/bcdd/result/config/switchers/features.rb +5 -5
  50. data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
  51. data/lib/bcdd/result/config.rb +7 -5
  52. data/lib/bcdd/result/contract/type_checker.rb +4 -0
  53. data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
  54. data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
  55. data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
  56. data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
  57. data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
  58. data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
  59. data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
  60. data/lib/bcdd/result/event_logs.rb +27 -0
  61. data/lib/bcdd/result/failure.rb +1 -3
  62. data/lib/bcdd/result/success.rb +1 -3
  63. data/lib/bcdd/result/version.rb +1 -1
  64. data/lib/bcdd/result.rb +23 -191
  65. data/lib/bcdd/success.rb +23 -0
  66. data/sig/bcdd/context.rbs +175 -0
  67. data/sig/bcdd/failure.rbs +13 -0
  68. data/sig/bcdd/result/config.rbs +1 -3
  69. data/sig/bcdd/result/context.rbs +2 -174
  70. data/sig/bcdd/result/contract.rbs +1 -0
  71. data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
  72. data/sig/bcdd/result.rbs +13 -31
  73. data/sig/bcdd/success.rbs +13 -0
  74. metadata +41 -24
  75. data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
  76. data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
  77. data/lib/bcdd/result/context/failure.rb +0 -9
  78. data/lib/bcdd/result/context.rb +0 -93
  79. data/lib/bcdd/result/failure/methods.rb +0 -21
  80. data/lib/bcdd/result/success/methods.rb +0 -21
  81. 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::Result::Context::Expectations]
9
+ affects: %w[BCDD::Result::Expectations BCDD::Context::Expectations]
10
10
  },
11
- transitions: {
11
+ event_logs: {
12
12
  default: true,
13
- affects: %w[BCDD::Result BCDD::Result::Context BCDD::Result::Expectations BCDD::Result::Context::Expectations]
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::Result::Context BCDD::Result::Expectations BCDD::Result::Context::Expectations]
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[Transitions::THREAD_VAR_NAME] = nil if option_name == :transitions
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::Result::Context::Expectations]
9
+ affects: %w[BCDD::Result::Expectations BCDD::Context::Expectations]
10
10
  }
11
11
  }.transform_values!(&:freeze).freeze
12
12
 
@@ -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 transitions
25
- Transitions::Config.instance
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
- transitions.freeze
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
@@ -10,6 +10,10 @@ module BCDD::Result::Contract
10
10
  @expectations = expectations
11
11
  end
12
12
 
13
+ def allow!(type)
14
+ expectations.type!(type)
15
+ end
16
+
13
17
  def allow?(types)
14
18
  validate(types, expected: expectations, allow_empty: false)
15
19
  end
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module BCDD::Result::Transitions
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::Transitions
3
+ module BCDD::Result::EventLogs
4
4
  module Listener
5
5
  module ClassMethods
6
- def around_transitions?
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 around_transitions(scope:)
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(transitions:); end
39
+ def on_finish(event_logs:); end
40
40
 
41
- def before_interruption(exception:, transitions:); end
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::Transitions
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
- around_transitions = list.select(&:around_transitions?)
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 around_transitions? == true' if around_transitions.size > 1
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], around_transitions: around_transitions[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, around_transitions = listeners[:list], nil, nil
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
- around_transitions = instance if listener?(:around_transitions, instance)
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, around_transitions)
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, :around_transitions_listener
53
+ attr_reader :listeners, :around_and_then_listener, :around_event_logs_listener
54
54
 
55
- private :listeners, :around_and_then_listener, :around_transitions_listener
55
+ private :listeners, :around_and_then_listener, :around_event_logs_listener
56
56
 
57
- def initialize(listeners, around_and_then_listener, around_transitions_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
- @around_transitions_listener = around_transitions_listener || Listener::Null
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 around_transitions(scope:, &block)
68
- around_transitions_listener.around_transitions(scope: scope, &block)
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(transitions:)
80
- listeners.each { _1.on_finish(transitions: transitions) }
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:, transitions:)
84
- listeners.each { _1.before_interruption(exception: exception, transitions: transitions) }
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,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module BCDD::Result::Transitions
3
+ module BCDD::Result::EventLogs
4
4
  module Tracking::Disabled
5
5
  def self.exec(_name, _desc)
6
6
  EnsureResult[yield]
@@ -1,32 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module BCDD::Result::Transitions
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
- transition_node, scope = start(name, desc)
10
+ event_log_node, scope = start(name, desc)
11
11
 
12
12
  result = nil
13
13
 
14
- listener.around_transitions(scope: scope) do
14
+ listener.around_event_logs(scope: scope) do
15
15
  result = EnsureResult[yield]
16
16
  end
17
17
 
18
- tree.move_to_root! if transition_node.root?
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, transition_node)
24
+ err!(e, event_log_node)
25
25
  end
26
26
 
27
- def err!(exception, transition_node)
28
- if transition_node.root?
29
- listener.before_interruption(exception: exception, transitions: map_transitions)
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
- transitions = map_transitions
93
+ event_logs = map_event_logs
94
94
 
95
- result.send(:transitions=, transitions)
95
+ result.send(:event_logs=, event_logs)
96
96
 
97
- listener.on_finish(transitions: transitions)
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 map_transitions
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
- metadata = { duration: duration, ids_tree: tree.nested_ids, ids_matrix: tree.ids_matrix, trace_id: trace_id }
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 Transitions
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, ids_tree: EMPTY_ARRAY, ids_matrix: EMPTY_HASH, trace_id: nil }.freeze
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?(:transitions) ? Tracking::Enabled.new : Tracking::Disabled
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 Transitions
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
- NestedIds = ->(node) { [node.id, node.children.map(&NestedIds)] }
92
+ Ids = ->(node) { [node.id, node.children.map(&Ids)] }
93
93
 
94
- def nested_ids
95
- NestedIds[root]
94
+ def ids
95
+ Ids[root]
96
96
  end
97
97
 
98
- IdsMatrix = ->(tree, row, col, ids, previous) do
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
- ids[id] = previous == [row, col] ? [row, col + 1] : [row, col]
110
+ memo[id] = previous == [row, col] ? [row, col + 1] : [row, col]
107
111
 
108
- previous = ids[id]
112
+ previous = memo[id]
109
113
 
110
- IdsMatrix[leaf, row, col + 1, ids, previous]
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
- ids = { 0 => current }
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
- IdsMatrix[nested_ids[1], 1, 1, ids, current]
131
+ node.each { |leaf| IdsLevelParent[leaf, id, level + 1, memo] }
132
+
133
+ memo
134
+ end
120
135
 
121
- ids
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
@@ -2,9 +2,7 @@
2
2
 
3
3
  class BCDD::Result
4
4
  class Failure < self
5
- require_relative 'failure/methods'
6
-
7
- include Methods
5
+ include ::BCDD::Failure
8
6
  end
9
7
 
10
8
  def self.Failure(type, value = nil)
@@ -2,9 +2,7 @@
2
2
 
3
3
  class BCDD::Result
4
4
  class Success < self
5
- require_relative 'success/methods'
6
-
7
- include Methods
5
+ include ::BCDD::Success
8
6
  end
9
7
 
10
8
  def self.Success(type, value = nil)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BCDD
4
4
  class Result
5
- VERSION = '0.13.0'
5
+ VERSION = '1.1.0'
6
6
  end
7
7
  end