Module: LyberCore::Robot

Defined in:
lib/lyber_core/robot.rb,
lib/lyber_core/return_state.rb

Defined Under Namespace

Modules: ClassMethods Classes: ReturnState

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#check_queued_statusObject

Returns the value of attribute check_queued_status.



50
51
52
# File 'lib/lyber_core/robot.rb', line 50

def check_queued_status
  @check_queued_status
end

#workflow_serviceObject (readonly)

Returns the value of attribute workflow_service.



51
52
53
# File 'lib/lyber_core/robot.rb', line 51

def workflow_service
  @workflow_service
end

Class Method Details

.included(base) ⇒ Object

Add the ClassMethods to the class this is being mixed into



10
11
12
# File 'lib/lyber_core/robot.rb', line 10

def self.included base
  base.extend ClassMethods
end

.step_to_classname(step, opts = {}) ⇒ String

Converts a given step to the Robot class name Examples:

  • ‘dor:assemblyWF:jp2-create` into `Robots::DorRepo::Assembly::Jp2Create`

  • ‘dor:gisAssemblyWF:start-assembly-workflow` into `Robots::DorRepo::GisAssembly::StartAssemblyWorkflow`

  • ‘dor:etdSubmitWF:binder-transfer` into `Robots:DorRepo::EtdSubmit::BinderTransfer`

Parameters:

  • step. (String)

    fully qualified step name, e.g., ‘dor:accessionWF:descriptive-metadata`

  • opts (Hash) (defaults to: {})
  • :repo_suffix (Hash)

    a customizable set of options

Returns:

  • (String)

    The class name for the robot, e.g., ‘Robots::DorRepo::Accession:DescriptiveMetadata`



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/lyber_core/robot.rb', line 38

def self.step_to_classname step, opts = {}
  # generate the robot job class name
  opts[:repo_suffix] ||= 'Repo'
  r, w, s = step.split(/:/, 3)
  return [
    'Robots',
    r.camelcase + opts[:repo_suffix], # 'Dor' conflicts with dor-services
    w.sub('WF', '').camelcase,
    s.gsub('-', '_').camelcase
  ].join('::')
end

Instance Method Details

#initialize(repo, workflow_name, step_name, opts = {}) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/lyber_core/robot.rb', line 53

def initialize(repo, workflow_name, step_name, opts = {})
  Signal.trap("QUIT") { puts "#{Process.pid} ignoring SIGQUIT" } # SIGQUIT ignored to let the robot finish
  @repo = repo
  @workflow_name = workflow_name
  @step_name = step_name
  @check_queued_status = opts.fetch(:check_queued_status, true)
  @workflow_service = opts.fetch(:workflow_service, Dor::WorkflowService)
end

#work(druid) ⇒ Object

Sets up logging, timing and error handling of the job Calls the #perform method, then sets workflow to ‘completed’ or ‘error’ depending on success



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/lyber_core/robot.rb', line 64

def work(druid)
  LyberCore::Log.set_logfile($stdout)                     # let process manager(bluepill) handle logging
  LyberCore::Log.info "#{druid} processing"
  return if @check_queued_status && !item_queued?(druid)

  result = nil
  elapsed = Benchmark.realtime do
    result = self.perform druid                                    # implemented in the mixed-in robot class
  end

  # this is the default note to pass back to workflow service, but it can be overriden by a robot that uses the Lybercore::Robot::ReturnState object to return a status
  note = Socket.gethostname
  
  # the final workflow state is determined by the return value of the perform step, if it is a ReturnState object, 
  # we will use the defined status, otherwise default to completed
  # if a note is passed back, we will also use that instead of the default
  if result.class == LyberCore::Robot::ReturnState
    workflow_state = result.status
    note = result.note unless result.note.blank?
  else
    workflow_state = 'completed'  
  end
  
  # update the workflow status from its current state to the state returned by perform (or 'completed' as the default) 
  workflow_service.update_workflow_status @repo, druid, @workflow_name, @step_name, workflow_state, :elapsed => elapsed, :note => note
  LyberCore::Log.info "Finished #{druid} in #{sprintf("%0.4f",elapsed)}s"

rescue => e
  Honeybadger.notify(e) if defined? Honeybadger
  begin
    LyberCore::Log.error e.message + "\n" + e.backtrace.join("\n")
    workflow_service.update_workflow_error_status @repo, druid , @workflow_name, @step_name, e.message, :error_text => Socket.gethostname
  rescue => e2
    LyberCore::Log.error "Cannot set #{druid} to status='error'\n" + e2.message + "\n" + e2.backtrace.join("\n")
    raise e2 # send exception to Resque failed queue
  end
end