module OscMacheteRails::Statusable
Methods that deal with pbs batch job status management within a Rails ActiveRecord
model
Public Class Methods
# File lib/osc_machete_rails/statusable.rb, line 63 def self.classes @classes ||= [] end
# File lib/osc_machete_rails/statusable.rb, line 27 def self.included(obj) # track the classes that include this module self.classes << Kernel.const_get(obj.name) unless obj.name.nil? # add class methods obj.send(:extend, ClassMethods) begin obj.class_eval do # Store job object info in a JSON column and replace old column methods if respond_to?(:table_exists?) && table_exists? && respond_to?(:column_names) && column_names.include?('job_cache') store :job_cache, accessors: [ :script, :pbsid, :host ], coder: JSON delegate :script_name, to: :job define_method :job_path do job.path end else define_method(:job_cache) do { script: (job_path && script_name) ? Pathname.new(job_path).join(script_name) : nil, pbsid: pbsid, host: nil } end end end rescue StandardError => e msg = "\nIf you are precompiling assets, you can ignore this:\n\tError thrown: #{e.inspect}" msg += "\n\tError thrown in OscMacheteRails::Statusable.included when trying to add job_cache to the class including Statusable: #{obj.name}." msg += "\n\tjob_cache method was not added to class." unless obj.method_defined? :job_cache msg += "\n\n" STDERR.puts msg end end
for each Statusable
, call update_status! on active jobs
# File lib/osc_machete_rails/statusable.rb, line 68 def self.update_status_of_all_active_jobs # to eager load classes, set config.eager_load to true or execute Rails.application.eager_load! if self.classes.empty? Rails.logger.warn "Statusable.classes Array is empty. This should contain a list of all the classes that include Statusable. " \ "This could occur if the Rails app is not configured to eager load classes." else Rails.logger.debug "Updating active job statuses via Statusable.update_status_of_all_active_jobs." end self.classes.each do |klass| klass.active.to_a.each(&:update_status!) if klass.respond_to?(:active) end end
Public Instance Methods
Returns associated OSC::Machete::Job instance
# File lib/osc_machete_rails/statusable.rb, line 123 def job OSC::Machete::Job.new(job_cache.symbolize_keys) end
Setter that accepts an OSC::Machete::Job instance
@param [Job] new_job The Job object to be assigned to the Statusable
instance.
# File lib/osc_machete_rails/statusable.rb, line 99 def job=(new_job) if self.has_attribute?(:job_cache) self.script = new_job.script_path.to_s self.pbsid = new_job.pbsid self.host = new_job.host if new_job.respond_to?(:host) else self.script_name = new_job.script_name self.job_path = new_job.path.to_s self.pbsid = new_job.pbsid end begin self.status = new_job.status rescue PBS::Error => e # a safe default self.status = OSC::Machete::Status.queued # log the error Rails.logger.error("After submitting the job with pbsid: #{pbsid}," \ " checking the status raised a PBS::Error: #{e.message}") end end
A hook that can be overidden with custom code also looks for default validation methods for existing WARNING: THIS USES ActiveSupport::Inflector methods underscore and parameterize
@return [Boolean] true if the results script is present
# File lib/osc_machete_rails/statusable.rb, line 144 def results_valid? valid = true if self.respond_to?(:script_name) && !script_name.nil? if self.respond_to?(results_validation_method_name) valid = self.send(results_validation_method_name) end end valid end
Build the results validation method name from script_name attr using ActiveSupport methods
Call this using the Rails console to see what method you should implement to support results validation for that job.
@return [String] A string representing a validation method name from script_name attr using ActiveSupport methods
# File lib/osc_machete_rails/statusable.rb, line 135 def results_validation_method_name File.basename(script_name, ".*").underscore.parameterize(separator: '_') + "_results_valid?" end
getter returns a Status value from CHAR or a Status value
# File lib/osc_machete_rails/statusable.rb, line 14 def status OSC::Machete::Status.new(super) end
# File lib/osc_machete_rails/statusable.rb, line 9 def status=(s) super(OSC::Machete::Status.new(s).char) end
delete the batch job and update status may raise PBS::Error as it is unhandled here!
# File lib/osc_machete_rails/statusable.rb, line 20 def stop(update: true) return unless status.active? job.delete update(status: OSC::Machete::Status.failed) if update end
FIXME: should have a unit test for this!
job.update_status! will update and save object if submitted? and ! completed? and status changed from previous state force will cause status to update regardless of completion status, redoing the validations. This way, if you are fixing validation methods you can use the Rails console to update the status of a Workflow by doing this: Container.last.jobs.each {|j| j.update_status!(force: true) } Or for a single statusable such as job: job.update_status!(force: true) FIXME: should log whether a validation method was called or throw a warning that no validation method was found (the one that would have been called) @param [Boolean, nil] force Force the update. (Default: false)
# File lib/osc_machete_rails/statusable.rb, line 173 def update_status!(force: false) # this will make it easier to differentiate from current_status cached_status = status # by default only update if its an active job if (cached_status.not_submitted? && pbsid) || cached_status.active? || force # get the current status from the system current_status = job.status # if job is done, lets re-validate if current_status.completed? current_status = results_valid? ? OSC::Machete::Status.passed : OSC::Machete::Status.failed end if (current_status != cached_status) || force self.status = current_status self.save end end rescue PBS::Error => e # we log the error but we just don't update the status Rails.logger.error("During update_status! call on job with pbsid #{pbsid} and id #{id}" \ " a PBS::Error was thrown: #{e.message}") end