class Dynflow::ExecutionPlan::Steps::Abstract

Attributes

action_class[R]
action_id[R]
delayed_events[R]
ended_at[R]
error[RW]
execution_plan_id[R]
execution_time[R]
id[R]
progress_weight[W]
queue[R]
real_time[R]
started_at[R]
state[R]
world[R]

Public Class Methods

new(execution_plan_id, id, state, action_class, action_id, error, world, started_at = nil, ended_at = nil, execution_time = 0.0, real_time = 0.0, progress_done = nil, progress_weight = nil, queue = nil) click to toggle source

rubocop:disable Metrics/ParameterLists

# File lib/dynflow/execution_plan/steps/abstract.rb, line 14
def initialize(execution_plan_id,
               id,
               state,
               action_class,
               action_id,
               error,
               world,
               started_at      = nil,
               ended_at        = nil,
               execution_time  = 0.0,
               real_time       = 0.0,
               progress_done   = nil,
               progress_weight = nil,
               queue           = nil)

  @id                = id || raise(ArgumentError, 'missing id')
  @execution_plan_id = Type! execution_plan_id, String
  @world             = Type! world, World
  @error             = Type! error, ExecutionPlan::Steps::Error, NilClass
  @started_at        = Type! started_at, Time, NilClass
  @ended_at          = Type! ended_at, Time, NilClass
  @execution_time    = Type! execution_time, Numeric
  @real_time         = Type! real_time, Numeric

  @progress_done     = Type! progress_done, Numeric, NilClass
  @progress_weight   = Type! progress_weight, Numeric, NilClass

  @queue = Type! queue, Symbol, NilClass

  self.state = state.to_sym

  Child! action_class, Action
  @action_class = action_class

  @action_id = action_id || raise(ArgumentError, 'missing action_id')
end
new_from_hash(hash, execution_plan_id, world) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 145
def self.new_from_hash(hash, execution_plan_id, world)
  check_class_matching hash
  new(execution_plan_id,
    hash[:id],
    hash[:state],
    Action.constantize(hash[:action_class]),
    hash[:action_id],
    hash_to_error(hash[:error]),
    world,
    string_to_time(hash[:started_at]),
    string_to_time(hash[:ended_at]),
    hash[:execution_time].to_f,
    hash[:real_time].to_f,
    hash[:progress_done].to_f,
    hash[:progress_weight].to_f,
    (hash[:queue] && hash[:queue].to_sym))
end
states() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 76
def self.states
  @states ||= [:scheduling, :pending, :running, :success, :suspended, :skipping, :skipped, :error, :cancelled]
end

Public Instance Methods

==(other) click to toggle source

rubocop:enable Metrics/ParameterLists

# File lib/dynflow/execution_plan/steps/abstract.rb, line 52
def ==(other)
  other.class == self.class && other.execution_plan_id == self.execution_plan_id && other.id == self.id
end
action(execution_plan) click to toggle source

@return [Action] in presentation mode, intended for retrieving: progress information, details, human outputs, etc.

# File lib/dynflow/execution_plan/steps/abstract.rb, line 127
def action(execution_plan)
  world.persistence.load_action_for_presentation(execution_plan, action_id, self)
end
action_logger() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 56
def action_logger
  @world.action_logger
end
cancellable?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 135
def cancellable?
  false
end
default_progress_done() click to toggle source

in specific states it’s clear what progress the step is in

# File lib/dynflow/execution_plan/steps/abstract.rb, line 110
def default_progress_done
  case self.state
  when :success, :skipped
    1
  when :pending
    0
  end
end
execute(*args) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 80
def execute(*args)
  raise NotImplementedError
end
mark_to_skip() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 64
def mark_to_skip
  raise NotImplementedError
end
persistence() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 68
def persistence
  world.persistence
end
phase() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 60
def phase
  raise NotImplementedError
end
progress_done() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 105
def progress_done
  default_progress_done || @progress_done || 0
end
progress_weight() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 119
def progress_weight
  @progress_weight || 0 # 0 means not calculated yet
end
save(conditions = {}) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 72
def save(conditions = {})
  persistence.save_step(self, conditions)
end
skippable?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 131
def skippable?
  self.state == :error
end
to_hash() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 88
def to_hash
  recursive_to_hash execution_plan_uuid: execution_plan_id,
                    id:                  id,
                    state:               state,
                    class:               self.class.to_s,
                    action_class:        action_class.to_s,
                    action_id:           action_id,
                    error:               error,
                    started_at:          started_at,
                    ended_at:            ended_at,
                    execution_time:      execution_time,
                    real_time:           real_time,
                    progress_done:       progress_done,
                    progress_weight:     progress_weight,
                    queue:               queue
end
to_s() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 84
def to_s
  "#<#{self.class.name}:#{execution_plan_id}:#{id}>"
end
with_sub_plans?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 139
def with_sub_plans?
  false
end

Private Instance Methods

calculate_progress(action) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 178
def calculate_progress(action)
  @progress_done, @progress_weight = action.calculated_progress
  if @progress_done.is_a?(Float) && !@progress_done.finite?
    action_logger.error("Unexpected progress value #{@progress_done} for step #{execution_plan_id}##{id}")
    @progress_done = 0
  end
end
update_step_telemetry(current_execution_time) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 186
def update_step_telemetry(current_execution_time)
  Dynflow::Telemetry.with_instance do |t|
    if [:success, :skipped].include?(state)
      t.observe_histogram(:dynflow_step_real_time,
        real_time * 1000,
        :action => action_class.to_s, :phase => phase.to_s_humanized)
    end
    t.observe_histogram(:dynflow_step_execution_time,
      current_execution_time * 1000,
      :action => action_class.to_s, :phase => phase.to_s_humanized)
  end
end
with_meta_calculation(action, &block) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 165
def with_meta_calculation(action, &block)
  start = Time.now.utc
  @started_at ||= start
  block.call
ensure
  calculate_progress(action)
  @ended_at = Time.now.utc
  current_execution_time = @ended_at - start
  @execution_time += current_execution_time
  @real_time       = @ended_at - @started_at
  update_step_telemetry(current_execution_time)
end