Class: Dynflow::Action

Inherits:
Serializable show all
Extended by:
Format
Includes:
Algebrick::Matching, Algebrick::TypeCheck, Progress, Rescue
Defined in:
lib/dynflow/action.rb

Direct Known Subclasses

Missing

Defined Under Namespace

Modules: Cancellable, Executable, Format, Phase, Polling, Progress, Rescue Classes: Missing, Suspended

Constant Summary collapse

OutputReference =
ExecutionPlan::OutputReference
ERROR =
Object.new
SUSPEND =
Object.new
Skip =
Algebrick.atom

Constants included from Rescue

Rescue::Strategy, Rescue::SuggestedStrategy

Instance Attribute Summary collapse

Attributes included from Progress

#calculated_progress

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Format

input_format, output_format

Methods included from Rescue

#combine_suggested_strategies, #rescue_strategy, #rescue_strategy_for_planned_action, #rescue_strategy_for_self

Methods included from Progress

#finalize_progress, #finalize_progress_weight, #run_progress, #run_progress_weight

Methods inherited from Serializable

from_hash

Constructor Details

#initialize(attributes, world) ⇒ Action

Returns a new instance of Action.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/dynflow/action.rb', line 90

def initialize(attributes, world)
  Type! attributes, Hash

  @phase             = Type! attributes.fetch(:phase), Phase
  @world             = Type! world, World
  @step              = Type!(attributes.fetch(:step),
                             ExecutionPlan::Steps::Abstract) if phase? Executable
  @execution_plan_id = Type! attributes.fetch(:execution_plan_id), String
  @id                = Type! attributes.fetch(:id), Integer
  @plan_step_id      = Type! attributes.fetch(:plan_step_id), Integer
  @run_step_id       = Type! attributes.fetch(:run_step_id), Integer, NilClass
  @finalize_step_id  = Type! attributes.fetch(:finalize_step_id), Integer, NilClass

  @execution_plan    = Type!(attributes.fetch(:execution_plan), ExecutionPlan) if phase? Present

  getter =-> key, required do
    required ? attributes.fetch(key) : attributes.fetch(key, {})
  end

  @input  = OutputReference.deserialize getter.(:input, phase?(Run, Finalize, Present))
  @output = OutputReference.deserialize getter.(:output, false) if phase? Run, Finalize, Present
end

Instance Attribute Details

#execution_plan_idObject (readonly)

Returns the value of attribute execution_plan_id.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def execution_plan_id
  @execution_plan_id
end

#finalize_step_idObject (readonly)

Returns the value of attribute finalize_step_id.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def finalize_step_id
  @finalize_step_id
end

#idObject (readonly)

Returns the value of attribute id.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def id
  @id
end

#inputObject

Returns the value of attribute input.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def input
  @input
end

#phaseObject (readonly)

Returns the value of attribute phase.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def phase
  @phase
end

#plan_step_idObject (readonly)

Returns the value of attribute plan_step_id.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def plan_step_id
  @plan_step_id
end

#run_step_idObject (readonly)

Returns the value of attribute run_step_id.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def run_step_id
  @run_step_id
end

#worldObject (readonly)

Returns the value of attribute world.



85
86
87
# File 'lib/dynflow/action.rb', line 85

def world
  @world
end

Class Method Details

.all_childrenObject



26
27
28
29
30
# File 'lib/dynflow/action.rb', line 26

def self.all_children
  children.values.inject(children.values) do |children, child|
    children + child.all_children
  end
end

.childrenObject



37
38
39
# File 'lib/dynflow/action.rb', line 37

def self.children
  @children ||= {}
end

.constantize(action_name) ⇒ Object



79
80
81
82
83
# File 'lib/dynflow/action.rb', line 79

def self.constantize(action_name)
  super action_name
rescue NameError
  Action::Missing.generate(action_name)
end

.inherited(child) ⇒ Object



32
33
34
35
# File 'lib/dynflow/action.rb', line 32

def self.inherited(child)
  children[child.name] = child
  super child
end

.middlewareObject



41
42
43
# File 'lib/dynflow/action.rb', line 41

def self.middleware
  @middleware ||= Middleware::Register.new
end

.subscribenil, Class

FIND define subscriptions in world independent on action’s classes,

limited only by in/output formats

Returns:

  • (nil, Class)

    a child of Action



48
49
50
# File 'lib/dynflow/action.rb', line 48

def self.subscribe
  nil
end

Instance Method Details

#action_loggerObject



165
166
167
168
# File 'lib/dynflow/action.rb', line 165

def action_logger
  phase! Executable
  world.action_logger
end

#all_planned_actions(filter_class = Action) ⇒ Array<Action>

returned actions are in Present phase

Parameters:

  • filter_class (Class) (defaults to: Action)

    return only actions which are kind of ‘filter_class`

Returns:

  • (Array<Action>)

    of all (including indirectly) planned actions by this action,



189
190
191
192
193
194
# File 'lib/dynflow/action.rb', line 189

def all_planned_actions(filter_class = Action)
  phase! Present
  mine = planned_actions
  (mine + mine.reduce([]) { |arr, action| arr + action.all_planned_actions }).
      select { |a| a.is_a?(filter_class) }
end

#errorObject



229
230
231
232
# File 'lib/dynflow/action.rb', line 229

def error
  phase! Executable
  @step.error
end

#execute(*args) ⇒ Object



234
235
236
237
# File 'lib/dynflow/action.rb', line 234

def execute(*args)
  phase! Executable
  self.send phase.execute_method_name, *args
end

#execution_planObject



160
161
162
163
# File 'lib/dynflow/action.rb', line 160

def execution_plan
  phase! Plan, Present
  @execution_plan
end

#finalize_stepObject



201
202
203
204
# File 'lib/dynflow/action.rb', line 201

def finalize_step
  phase! Present
  execution_plan.steps.fetch(finalize_step_id) if finalize_step_id
end

#from_subscription?Boolean

Returns:

  • (Boolean)


155
156
157
158
# File 'lib/dynflow/action.rb', line 155

def from_subscription?
  phase! Plan
  @from_subscription
end

#outputObject



134
135
136
137
138
139
140
141
# File 'lib/dynflow/action.rb', line 134

def output
  if phase? Plan
    @output_reference or
        raise 'plan_self has to be invoked before being able to reference the output'
  else
    @output
  end
end

#output=(hash) ⇒ Object



128
129
130
131
132
# File 'lib/dynflow/action.rb', line 128

def output=(hash)
  Type! hash, Hash
  phase! Run
  @output = hash.with_indifferent_access
end

#phase!(*phases) ⇒ Object



117
118
119
120
# File 'lib/dynflow/action.rb', line 117

def phase!(*phases)
  phase?(*phases) or
      raise TypeError, "Wrong phase #{phase}, required #{phases}"
end

#phase?(*phases) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/dynflow/action.rb', line 113

def phase?(*phases)
  Match? phase, *phases
end

#plan_stepObject



170
171
172
173
# File 'lib/dynflow/action.rb', line 170

def plan_step
  phase! Present
  execution_plan.steps.fetch(plan_step_id)
end

#planned_actions(filter = Action) ⇒ Array<Action>

returned actions are in Present phase

Parameters:

  • filter_class (Class)

    return only actions which are kind of ‘filter_class`

Returns:

  • (Array<Action>)

    of directly planned actions by this action,



178
179
180
181
182
183
184
# File 'lib/dynflow/action.rb', line 178

def planned_actions(filter = Action)
  phase! Present
  plan_step.
      planned_steps(execution_plan).
      map { |s| s.action(execution_plan) }.
      select { |a| a.is_a?(filter) }
end

#required_step_ids(input = self.input) ⇒ Array<Fixnum>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns - ids of steps referenced from action.

Returns:

  • (Array<Fixnum>)
    • ids of steps referenced from action



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/dynflow/action.rb', line 241

def required_step_ids(input = self.input)
  results   = []
  recursion =-> value do
    case value
    when Hash
      value.values.each { |v| recursion.(v) }
    when Array
      value.each { |v| recursion.(v) }
    when ExecutionPlan::OutputReference
      results << value.step_id
    else
      # no reference hidden in this arg
    end
    results
  end
  recursion.(input)
end

#run_stepObject



196
197
198
199
# File 'lib/dynflow/action.rb', line 196

def run_step
  phase! Present
  execution_plan.steps.fetch(run_step_id) if run_step_id
end

#set_plan_context(execution_plan, trigger, from_subscription) ⇒ Object



143
144
145
146
147
148
# File 'lib/dynflow/action.rb', line 143

def set_plan_context(execution_plan, trigger, from_subscription)
  phase! Plan
  @execution_plan    = Type! execution_plan, ExecutionPlan
  @trigger           = Type! trigger, Action, NilClass
  @from_subscription = Type! from_subscription, TrueClass, FalseClass
end

#stateObject



224
225
226
227
# File 'lib/dynflow/action.rb', line 224

def state
  phase! Executable
  @step.state
end

#stepsObject



206
207
208
# File 'lib/dynflow/action.rb', line 206

def steps
  [plan_step, run_step, finalize_step]
end

#to_hashObject



210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/dynflow/action.rb', line 210

def to_hash
  recursive_to_hash(
      { class:             self.class.name,
        execution_plan_id: execution_plan_id,
        id:                id,
        plan_step_id:      plan_step_id,
        run_step_id:       run_step_id,
        finalize_step_id:  finalize_step_id,
        input:             input },
      if phase? Run, Finalize, Present
        { output: output }
      end)
end

#triggerObject



150
151
152
153
# File 'lib/dynflow/action.rb', line 150

def trigger
  phase! Plan
  @trigger
end