class Automate::Chain

Captures the entire command chain to be executed. Thus, the main objective of this class is to capture and execute the ‘ChainLinks`. All the capturing happens in the `go` method, and the executing in the `run` method.

Public Class Methods

new(task) click to toggle source

Private constructor. Instance creation is only allowed through ‘#which`.

# File lib/automate/chain.rb, line 103
def initialize(task)
  @task = task
  @cmd_list = []
  @defer_list = []
end
which(task, &block) click to toggle source

Factory method that creates a new command chain.

# File lib/automate/chain.rb, line 12
def self.which(task, &block)
  c = new(task)
  c.instance_exec(&block)
  c
end

Public Instance Methods

go(desc, &block) click to toggle source

Add a new link to the command chain

# File lib/automate/chain.rb, line 19
def go(desc, &block)
  add_command(desc, block)
end
run(args = {}) click to toggle source

Run all the command chain links. Will abort the command chain if any chain link should fail.

# File lib/automate/chain.rb, line 26
def run(args = {})
  notice "About to run command chain which '#{@task}'"

  success = true
  begin
    args = run_command_list(@cmd_list, args)
  rescue ChainFailedError => e
    fail("Chain link ##{e.chain} (#{e.description}) failed.")
    success = false
  end

  notice "Running deferred commands"

  # Note that deferred commands are executed in reverse order, so that
  # the cleanup actions for the last command is executed first.
  # E.g. if the definition order is as follows:
  #
  #   C1, C1_defer, C2, C3, C4, C4_defer
  #
  # The execution order will be
  #
  #   C1, C2, C3, C4, C4_defer, C1_defer
  #
  args = run_command_list(@defer_list.reverse, args)
  if !success
    false
  else
    args
  end

rescue ChainFailedError => e
  fail("Defer command ##{e.chain} (#{e.description}) failed.")
  false
end
run_command_list(list, args) click to toggle source
# File lib/automate/chain.rb, line 62
def run_command_list(list, args)
  list.each_with_index do |cmd, index|
    desc, proc = cmd
    success "#{timestamp} // Running link ##{index+1} - #{desc}"

    error = false
    begin
      ret, out, chain_link_defer = ChainLink.invoke(proc, args)
      @defer_list += chain_link_defer
    rescue ChainLinkFailedError => e
      # TODO: Storing the defer_list in the ChainLinkFailedError is awful,
      # and shall be fixed when there's time to remove this entire exception-based
      # "communication" between chain and chain link.
      @defer_list += e.defer_list
      error = true
    end
    raise ChainFailedError.new(index + 1, desc) if ret == false || error == true

    # Pass the arguments from the last iteration, overwriting everything that
    # was passed from the current one.
    args.merge! out

    # Make it possible to run commands step by step
    if !ENV["AUTOMATE_STEP"].nil?
      puts "Press a key to continue..."
      $stdin.gets
      puts "\n"
    end
  end

  args
end

Private Instance Methods

add_command(desc, cmd) click to toggle source
# File lib/automate/chain.rb, line 113
def add_command(desc, cmd)
  raise "Parameter must be a Proc/Lambda" if !cmd.is_a?(Proc)
  @cmd_list.push [desc, cmd]
end
prefix() click to toggle source

Messenger module related

# File lib/automate/chain.rb, line 124
def prefix
  "=> "
end
timestamp() click to toggle source
# File lib/automate/chain.rb, line 109
def timestamp
  Time.now.strftime('%H:%M:%S.%L')
end