JBoss.orgCommunity Documentation
Scheduled jobs are simply components that execute on a possibly-recurring schedule instead of in response to user interaction. Scheduled jobs fire asynchronously, outside of the normal web-browser thread-of-control. Scheduled jobs have full access to the entire Ruby environment. This allows them to interact with database models and other application functionality.
Each scheduled job maps to exactly one Ruby class. The path and filename should match the class name of the job contained in the file.
| File name | Class name |
|---|---|
mail_notifier.rb | MailNotifier |
mail/notifier.rb | Mail::Notifier |
Example 10.1. Skeleton scheduled job class
(mail/notifier.rb)
module Mail
class Notifier
# implementation goes here
end
end
Each job class should implement a no-argument
run() method to perform the work when
fired. The class may optionally implement a one-argument
on_error(exception) method to handle
any errors raised during the job's execution.
Example 10.2. Scheduled job implementation
(mail/notifier.rb)
module Mail
class Notifier
# optional, only needed if you pass config options to the job
def initialize(options = {})
@options = options
end
def run()
# perform work here
end
def on_error(exception)
# Optionally implement this method to interrogate any exceptions
# raised inside the job's run method.
end
end
endFrom within the class's run() method, the
full application environment is available.
The job schedule defines the time(s) that a job should execute. This may be defined to be single point in time, or more often, as recurring event. The job schedule is defined in your deployment descriptor.
Within the internal torquebox.yml
descriptor (or through an external
descriptor), scheduled jobs are configured using the
*-knob.ymljobs: section, in which a block of
information is provided for each job. The block starts with an
arbitrary name for the job. Each block must also define the job
class and the schedule specification. Optionally a
timeout, a description, and a
config may be provided. Providing a
timeout will cause the job to be interrupted
if it runs beyond the timeout period (see Section 10.3.2, “Timing Out Jobs”).
If you provide
a config, its value will be passed to the
initialize method of the job class.
If you are using the DSL (via torquebox.rb) in
your internal descriptor, each job is defined using the job
directive, with very similar options to the YAML syntax described above.
The DSL does not require a name for each job, unless you intend to share
a job class across multiple jobs.
Example 10.3. Example deployment descriptor
Using the YAML syntax:
application:
..
jobs:
mail.notifier:
job: Mail::Notifier
cron: '0 */5 * * * ?'
timeout: 50000 ms
description: Deliver queued mail notifications
config:
foo: barAnd via the DSL:
TorqueBox.configure do
...
job Mail::Notifier do
name 'mail.notifier' # optional, unless the job class is used by multiple jobs
cron '0 */5 * * * ?'
timeout '5s'
description 'Deliver queued mail notifications' # optional
config do
foo 'bar'
end
end
endThe cron attribute should contain a typical crontab-like entry. It is composed of 7 fields (6 are required).
| Seconds | Minutes | Hours | Day of Month | Month | Day of Week | Year |
|---|---|---|---|---|---|---|
| 0-59 | 0-59 | 0-23 | 1-31 | 1-12 or JAN-DEC | 1-7 or SUN-SAT | 1970-2099 (optional) |
For several fields, you may denote subdivision by using the
forward-slash (/) character. To execute a job every 5
minutes, */5 in the minutes field would specify this
condition.
Spans may be indicated using the dash (-) character.
To execute a job Monday through Friday, MON-FRI should be
used in the day-of-week field.
Multiple values may be separated using the comma (,)
character. The specification of 1,15 in the day-of-month
field would result in the job firing on the 1st and 15th of each
month.
Either day-of-month or day-of-week must be specified using the
? character, since specifying both is contradictory.
To keep jobs from running too long, you can set a
timeout setting for the job. The format of
the timeout is a integer followed by an optional time unit.
The available time units are:
ms - milliseconds
s - seconds
m - minutes
h - hours
If no unit is provided, seconds are assumed.
In addition to specifying a timeout parameter, you will also have
to implement a on_timeout method on your job class
that will be called when the timeout occurs. This method is responsible
for actually shutting down the job - TorqueBox will not kill the job
when the timeout occurs. One approach would be for your job to periodically
check a flag while processing, with on_timeout setting
that flag when called.
Example 10.4. Job with timeout
(mail/notifier.rb)
module Mail
class Notifier
# optional, only needed if you pass config options to the job
def initialize(options = {})
@options = options
@timeout = false
end
def run()
notification_list.each do |n|
raise 'Timeout!' if @timeout
n.notify
end
end
def on_timeout
@timeout = true
end
end
endQuartz manages its own thread pool for running jobs. By default,
this pool contains three threads. If you have more than three jobs executing
at the same time, you may want to increase this pool size. You can do so via
the concurrency setting.
Example 10.5. Setting job concurrency
Using the YAML syntax:
application:
..
jobs:
concurrency: 10
mail.notifier:
job: Mail::Notifier
cron: '0 */5 * * * ?'And via the DSL:
TorqueBox.configure do
...
options_for :jobs, :concurrency => 10
job Mail::Notifier do
name 'mail.notifier' # optional, unless the job class is used by multiple jobs
cron '0 */5 * * * ?'
end
endNote that if you are using a bounded runtime pool for the jobs subsystem that is smaller than the concurrency setting, your available concurrency will be limited to the pool size. See Chapter 16, TorqueBox Runtime Pooling for more details.
TorqueBox supports highly-available singleton jobs. By default, a job only runs on one node in the cluster and if that node goes down or the job fails to run to completion, it is automatically scheduled on a new node.
To use high availability singleton jobs, you must start TorqueBox with a clustered configuration. For example:
$$JBOSS_HOME/bin/standalone.sh --server-config=standalone-ha.xml
Alternatively, use the torquebox command:
$torquebox run --clustered
HA jobs are configured using the singleton
key in the job specification in your deployment descriptor. Its
default value is true so you must manually
configure it with a value of false for the job to
run on every node in the cluster.
Example 10.6. Example deployment descriptor
Using the YAML syntax:
application:
..
jobs:
mail.notifier:
job: Mail::Notifier
cron: '0 */5 * * * ?'
description: Deliver queued mail notifications
singleton: true
config:
foo: barAnd via the DSL:
TorqueBox.configure do
...
job Mail::Notifier do
name 'mail.notifier' # optional, unless the job class is used by multiple jobs
cron '0 */5 * * * ?'
description 'Deliver queued mail notifications' # optional
singleton true
config do
foo 'bar'
end
end
endThis is the same
deployment descriptor from the example above.
Including the singleton attribute with a value
of true is redundant of course, since jobs will
only run on a single node when clustered, by default.
If a job requires access to other resources, such as messaging topics and queues, or Java CDI components these should be injected using the resource injection facilities provided by TorqueBox (see Chapter 12, TorqueBox Resource Injection).
In order for resource injection to function with scheduled jobs,
they must reside either at the root of your application directory (typical
for simple Rack applications), or underneath an
app/jobs/ directory. If you place the job anywhere
else, it may still function, but resources injection will not be
available.