Class: Sbmt::Strangler::Action::Composition::Step

Inherits:
Object
  • Object
show all
Includes:
Metrics
Defined in:
lib/sbmt/strangler/action/composition/step.rb

Constant Summary collapse

TYPES =
%i[sync async].freeze
MAX_LEVEL =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, type: :sync, level: 0, parent: nil) ⇒ Step

Returns a new instance of Step.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/sbmt/strangler/action/composition/step.rb', line 19

def initialize(name:, type: :sync, level: 0, parent: nil)
  if name.nil? || name.to_s == ""
    raise Errors::ConfigurationError, "Composition step name must be a non-empty string or symbol"
  end

  if TYPES.exclude?(type)
    raise Errors::ConfigurationError, "Composition step type must be a symbol from #{TYPES}"
  end

  if !parent.nil? && !parent.is_a?(self.class)
    raise Errors::ConfigurationError, "Composition step parent must be either #{self.class} or nil"
  end

  if !level.is_a?(Integer) && level >= 0
    raise Errors::ConfigurationError, "Composition step level must be a non-negative integer"
  end

  if level > MAX_LEVEL
    raise Errors::MaxLevelError, "Composition step is too deeply nested"
  end

  @name = name
  @type = type
  @level = level
  @parent = parent
  @sync_steps = {}
  @async_steps = {}
end

Instance Attribute Details

#levelObject (readonly)

Returns the value of attribute level.



17
18
19
# File 'lib/sbmt/strangler/action/composition/step.rb', line 17

def level
  @level
end

#nameObject (readonly)

Returns the value of attribute name.



17
18
19
# File 'lib/sbmt/strangler/action/composition/step.rb', line 17

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



17
18
19
# File 'lib/sbmt/strangler/action/composition/step.rb', line 17

def parent
  @parent
end

#typeObject (readonly)

Returns the value of attribute type.



17
18
19
# File 'lib/sbmt/strangler/action/composition/step.rb', line 17

def type
  @type
end

Instance Method Details

#async(name) {|| ... } ⇒ Object

Yields:

  • ()


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/sbmt/strangler/action/composition/step.rb', line 89

def async(name, &)
  if @sync_steps.key?(name)
    raise Errors::ConfigurationError, "Composition step #{name.inspect} has been already defined as sync"
  end

  @async_steps[name] ||=
    Sbmt::Strangler::Action::Composition::Step.new(
      name: name,
      type: :async,
      parent: self,
      level: level + 1
    )
  yield(@async_steps[name]) if block_given?
  self
end

#call(rails_controller, previous_responses: {}) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/sbmt/strangler/action/composition/step.rb', line 48

def call(rails_controller, previous_responses: {})
  with_metrics(rails_controller: rails_controller) do
    result = begin
      with_metrics(part: :process, rails_controller: rails_controller) do
        process_lambda.call(rails_controller, previous_responses)
      end
    rescue => error
      handle_error(error)

      {} # TODO: Better error handling in composition.
    end

    # process composition if there are nested steps
    if composite?
      result = call_composition(rails_controller, previous_responses: previous_responses.merge(name => result))
    end

    result
  end
end

#compose(&block) ⇒ Object



110
111
112
113
# File 'lib/sbmt/strangler/action/composition/step.rb', line 110

def compose(&block)
  @compose_lambda = block
  self
end

#composite?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/sbmt/strangler/action/composition/step.rb', line 69

def composite?
  @sync_steps.any? || @async_steps.any?
end

#process(&block) ⇒ Object



105
106
107
108
# File 'lib/sbmt/strangler/action/composition/step.rb', line 105

def process(&block)
  @process_lambda = block
  self
end

#sync(name) {|| ... } ⇒ Object

Yields:

  • ()


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/sbmt/strangler/action/composition/step.rb', line 73

def sync(name, &)
  if @async_steps.key?(name)
    raise Errors::ConfigurationError, "Composition step #{name.inspect} has been already defined as async"
  end

  @sync_steps[name] ||=
    Sbmt::Strangler::Action::Composition::Step.new(
      name: name,
      type: :sync,
      parent: self,
      level: level + 1
    )
  yield(@sync_steps[name]) if block_given?
  self
end