class MovieMasher::Job

Represents a single transcoding operation. Once process is called all of the job's inputs are downloaded and combined together into one mashup, which is then rendered into each of the formats specified by the job's outputs.

These rendered files are then uploaded to the job's destination, or to the output's if it has one defined. At junctures during processing the job's callbacks are requested, so as to alert remote systems of job status.

# construct a job and process it
job = Job.new('./job.json', render_directory: './temp')
job.process
# => true
job[:duration]
# => 360
job.progress
# => {
  rendering: 1,
  uploading: 1,
  downloading: 1,
  downloaded: 1,
  rendered: 1,
  uploaded: 1
}

Public Class Methods

create(hash = nil) click to toggle source
# File lib/job.rb, line 30
def create(hash = nil)
  (hash.is_a?(Job) ? hash : Job.new(hash))
end
init_hash(job) click to toggle source
# File lib/job.rb, line 34
def init_hash(job)
  job[:progress] = Hash.new { 0 }
  Hashable._init_key(job, :id, SecureRandom.uuid)
  Hashable._init_key(job, :inputs, [])
  Hashable._init_key(job, :outputs, [])
  Hashable._init_key(job, :callbacks, [])
  Hashable._init_key(job, :commands, []) # stores commands as executed
  Hashable._init_key(job, :results, []) # stores results of commands
  job
end
new(hash_or_path) click to toggle source

Create a new Job object from a nested structure or a file path.

hash_or_path

Hash or String expected to be a path to a JSON or YML file, which will be parse to the Hash.

Calls superclass method
# File lib/job.rb, line 107
def initialize(hash_or_path)
  @logger = nil
  @audio_graphs = nil
  @video_graphs = nil
  super Hashable.resolved_hash(hash_or_path)
  self.class.init_hash(@hash)
  path_job = __path_job
  FileHelper.safe_path path_job
  path_log = "#{path_job}/log.txt"
  # write massaged job json to job directory
  path_job = Path.concat(path_job, 'job.json')
  File.open(path_job, 'w') { |f| f << @hash.to_json }
  # if we encountered a parsing error, log it
  @hash[:log] = proc { File.read(path_log) }
  log_entry(:error) { @hash[:error] } if @hash[:error]
end

Public Instance Methods

audio_graphs() click to toggle source
# File lib/job.rb, line 46
def audio_graphs
  @audio_graphs ||= Input.audio_graphs(inputs)
end
base_source() click to toggle source
# File lib/job.rb, line 50
def base_source
  _get(__method__)
end
base_source=(value) click to toggle source
Transfer

Resolves relative paths within Input#source and Media#source String values.

# File lib/job.rb, line 56
def base_source=(value)
  _set(__method__, value)
end
callbacks() click to toggle source
Array

Zero or more Callback objects.

# File lib/job.rb, line 61
def callbacks
  _get(__method__)
end
destination() click to toggle source
# File lib/job.rb, line 65
def destination
  _get(__method__)
end
destination=(value) click to toggle source
Destination

Shared by all Output objects that haven't one of their own.

# File lib/job.rb, line 70
def destination=(value)
  _set(__method__, value)
end
error() click to toggle source
# File lib/job.rb, line 74
def error
  _get(__method__)
end
error=(value) click to toggle source

Problem encountered during new or process. If the source of the problem is a command line application then lines from its output that include common phrases will be included. Problems encountered during rendering of optional outputs are not included - check log for a warning instead.

Returns

Returns String that could be multiline and/or quite long.

# File lib/job.rb, line 84
def error=(value)
  _set(__method__, value)
end
error?() click to toggle source
# File lib/job.rb, line 88
def error?
  preflight
  err = error
  err ||= __error_blank_io?
  err ||= __error_io_or_callbacks?
  err ||= __error_destination_or_sources?
  self.error = err
end
id() click to toggle source
String

user supplied identifier.

Default

Nil, or messageId if the Job originated from an SQS message.

# File lib/job.rb, line 99
def id
  _get(__method__)
end
inputs() click to toggle source
Array

One or more Input objects.

# File lib/job.rb, line 125
def inputs
  _get(__method__)
end
log() click to toggle source
String

Current content of the job's log file.

# File lib/job.rb, line 130
def log
  proc = _get(__method__)
  proc.call
end
log_entry(type) { || ... } click to toggle source

Output to the job's log file. If type is :error then job will be halted and its error will be set to the result of proc.

type

Symbol :debug, :info, :warn or :error.

proc

Proc returning a string representing log entry.

# File lib/job.rb, line 140
def log_entry(type, &proc)
  @hash[:error] = yield if type == :error
  logger_job = __logger
  logger_job.send(type, &proc) if logger_job&.send("#{type}?".to_sym)
  puts yield if MovieMasher.configuration[:verbose] == 'debug'
end
module_source() click to toggle source
# File lib/job.rb, line 152
def module_source
  _get(__method__)
end
module_source=(value) click to toggle source
Transfer

Resolves relative font paths within Media#source String values.

Default

base_source

# File lib/job.rb, line 158
def module_source=(value)
  _set(__method__, value)
end
output_path(output, no_trailing_slash: false) click to toggle source
# File lib/job.rb, line 162
def output_path(output, no_trailing_slash: false)
  path = Path.concat(__path_job, output.identifier)
  path = Path.add_slash_end(path) unless no_trailing_slash
  path
end
outputs() click to toggle source
Array

One or more Output objects.

# File lib/job.rb, line 148
def outputs
  _get(__method__)
end
outputs_desire() click to toggle source
# File lib/job.rb, line 168
def outputs_desire
  desired = nil
  outputs.each do |output|
    desired = AV.merge(output[:av], desired)
  end
  desired
end
preflight() click to toggle source
# File lib/job.rb, line 176
def preflight
  self.destination = Destination.create_if destination
  self.base_source = Transfer.create_if base_source
  self.module_source = Transfer.create_if module_source
  inputs.map! do |input|
    input = Input.create input
    input.preflight self
    input
  end
  outputs.map! do |output|
    output = Output.create output
    output.preflight self
    output
  end
  callbacks.map! do |callback|
    Callback.create callback
  end
end
process() click to toggle source

Downloads assets for each Input, renders each Output and uploads to destination or Output#destination so long as error is false.

Returns

Returns true if processing succeeded, otherwise false - check error for details.

# File lib/job.rb, line 200
def process
  rescued_exception = nil
  begin
    error?
    __init_progress unless error
    __process_download unless error
    __process_render unless error
    __process_upload unless error
  rescue StandardError => e
    rescued_exception = e
  end
  begin
    if error || rescued_exception
      # encountered a showstopper (not one raised from optional output)
      rescued_exception = __log_exception(rescued_exception)
      __callback(:error)
    end
  rescue StandardError => e
    rescued_exception = e
  end
  begin
    __log_exception(rescued_exception)
    __callback(:complete)
  rescue StandardError => e
    puts "CAUGHT #{e.is_a?(Error::Job)} #{e.message} #{e.backtrace}"
    # no point in logging after complete
  end
  !error
end
progress() click to toggle source

Current status of processing. The following keys are available:

:downloading

number of files referenced by inputs

:downloaded

number of input files transferred

:rendering

number of outputs to render

:rendered

number of outputs rendered

:uploading

number of files referenced by outputs

:uploaded

number of output files transferred

:calling

number of non-progress callbacks to trigger

:called

number of non-progress callbacks triggered

Initial values for keys ending on 'ing' are based on information supplied in the job description and might change after process is called. For instance, if a mash input uses a remote source then downloading might increase once it's downloaded and parsed for nested media files.

Returns

Returns Hash object with Symbol keys and Integer values.

# File lib/job.rb, line 247
def progress
  _get(__method__)
end
render_path(output) click to toggle source
# File lib/job.rb, line 251
def render_path(output)
  path = ''
  if Type::SEQUENCE == output[:type]
    path = "/#{output[:name]}#{output[:sequence]}"
  end
  path = "#{path}.#{output[:extension]}"
  path = Evaluate.value(path, job: self, output: output)
  "#{output_path(output, no_trailing_slash: true)}#{path}"
end
video_graphs() click to toggle source
# File lib/job.rb, line 261
def video_graphs
  @video_graphs ||= Input.video_graphs(inputs, self)
end