1 Creating job types
For every different kind of work that you want to be done you need to create a new job type. This essentially means that you have to:
- Create a subclass of UbiquoJobs::Jobs::Base
- Override and implement the do_job_work and place there the work that will be performed when the worker starts the job.
The following is a very simple job example, that implements this basic schema that every Job must have
# An example job class
# It simply calculates a Array.size, overriding do_job_work
# Passes the required arguments using the options hash
# Ex:
# ExampleJob.run_async(:options => {:set => [1,2]})
# will execute
# [1,2].size
# and store the result. To display the results use job.output_log
class ExampleJob < UbiquoJobs::Jobs::Base
def do_job_work
set_property :result_output, self.options[:set].size
return 0
end
end
1.1 Parameters
If your job needs to be parameterized, use the options hash when creating to set all the needed parameters:
MassMailer.run_async(:options => {
:recipients => ['one@one.one', 'two@two.two']
:subject => 'This is an example'
:type => :one_time_mail
})
You can use virtual attributes to get parameters, but keep in mind that every thing that is not stored inside options will likely be lost at runtime (when a worker executes your job), since for custom parameters only the options hash has the persistence guaranteed.
1.2 Return code
In ExampleJob the last line is a return 0 statement. The Job Manager needs to know if the job has been executed correctly, and that, unless exceptions are raised, is something that every job must tell to the manager by returning an error code.
This might change in the future to assume that everything went fine unless an exception is raised.
2 ActiveJob
If you know for sure that you will be using the ActiveJob implementation, you can freely use ActiveModel/ActiveRecord goodies in your job classes, including validations or callbacks.
2.1 Validations
Validations will usually be done only on creation
attr_accessor :parts, :file
validates_presence_of :parts, :file, :on => :create
2.2 Callbacks
You can use the usual lifecycle callbacks too
attr_accessor :parts, :file
after_validation_on_create :store_options
def store_options
self.options = {:parts => parts * 20, :file => 'file://' + file}
end
Take in mind that you will usually just touch jobs on creation time, and then the handling is done automatically. For this reason, if your job needs some kind of parameter parsing, like in the above example, do it on creation to leave the job ready for execution.
3 Shell Jobs
If the job type you want to create will primarily execute a shell command, you will probably want to use the ShellJob helpers to do this a no-brainer. The main difference if you are using ShellJob is that, instead of implementing the do_task_work function, you need to override set_command. This is because what happens in execution time (command execution, and output/error handling) is automatically managed, so you just have to state the concrete command that will be run.
# An example shell job class
# Overrides set_command method using the 'path' virtual attribute
# Ex:
# ExampleShellJob.run_async(:path => '.')
# will execute
# ls .
class ExampleShellJob < UbiquoJobs::Jobs::Base
include UbiquoJobs::Helpers::ShellJob
attr_accessor :path
def set_command
self.command = 'ls ' + path
end
end
As you can see, we can use a virtual attribute here, since set_command is called in creation time.
4 Workers
Now that we know how to create new job types, it’s time to know how to execute them, The process that executes planified jobs is called a worker. Hence, all what is needed here is to start a worker.
script/ubiquo_worker worker_id
Every worker must have a unique and known id. This is because when a job is started, the Job Manager needs to identify which worker is doing it. In the case that a worker is killed while executing a job, starting a new worker with the same id will alert the Manager that the previous one did not finish the job, and will make this one again available to be executed.
That’s all – The worker will find available jobs (with the planification threshold overcame) and execute them immediately.
To stop all the running workers use:
script/ubiquo_worker --stop