Introduction

BackgrounDRb offers seemless integration with rails. You can invoke random tasks defined in your workers from rails. You can pass arguments, collect results, monitor status of workers and other statistics.

BackgrounDRb offers two sets of APIs for interacting with workers from rails. One is newer, slicker set and other is older legacy compatibility API. 1.0.3 version made a departure and implemented newer cleaner APIs, we will discuss them first, before getting acquinted with older API. Also, no matter which API you are using MiddleMan is the proxy object that lets you handle all this.

Newer API

Invoke an asynchronous task on a worker :

Following snippet will invoke method some_task with argument data in foo_worker. Also, method will be invoked asychrounously and Rails won’t wait for result from BackgrounDRb server.

worker = MiddleMan.worker(:foo_worker)
worker.some_task(data) 

Here, I would like to illustrate a point that contrary to general percenption, since some_task method is being executed asyhcrounously, don’t expect any meaningful return values from second line.

When you invoke MiddleMan.worker(:foo_worker) it returns a worker proxy, hence you can combine above two lines in one as follows:

MiddleMan.worker(:foo_worker,<optional_job_key>).some_task(data) 

Above snippet also demonstrates that, if your worker was started with a job_key you can use it to get correct proper worker proxy.

Invoke a method on worker and get results :

Following snippet will invoke method some_task with argument data in foo_worker. Also, method block until BackgrounDRb server returns a result.

worker = MiddleMan.worker(:foo_worker)
result = worker.some_task(data,true) 

As illustrated above, you can use job_key or make them in single line too. When you are invoking a method on your worker first optional argument will be passed to your worker method and second optional argument true|false indicates whether we should wait for result from BackgrounDRb server or not.

Fetch Status/Result Objects of a worker :

If you are using register_status in your worker code to store status/result objects, you can retrieve them from rails using:

status_obj = MiddleMan.worker(:foo_worker).ask_status 

You can as usual use job_key if worker was started with a job_key.

You can query status/result objects of all workers in one shot. For example, in your controller:

 def ask_status
  t_response = MiddleMan.query_all_workers
  running_workers = t_response.map { |key,value| "#{key} = #{value}"}.join(',')
  render :text => running_workers
end

Start a Worker :

To start a worker from rails:

used_job_key = MiddleMan.new_worker(:worker => :foo_worker,\
     :job_key => "my_secret_job_key") 

new_worker will always return job_key generated for the worker. It will be same as job_key passed while creating the worker and can be reused to invoke further tasks on the same worker or for deleting the worker.

Important thing to be kept in mind is, when you are creating a worker using above approach, you must use a unique job_key while starting the worker. Also, while invoking any of the other methods like ask_status, worker_info or one of the worker methods, you must use job_key.

Also another complicated example of starting a worker will be:

MiddleMan.new_worker(:worker => :error_worker, :job_key => :hello_world,\
     :data => "wow_man",:schedule => \
     { :hello_world => { :trigger_args => "*/5 * * * * * *",\
     :data => "hello_world" }}) 

Above code will start error_worker with job_key and will pass argument :data to create method of the worker. Worker will be scheduled to run hello_world method every 5 seconds with argument specified in :data.

Worker Statistics:

You can get worker specific information using:

MiddleMan.worker(:foo_worker).worker_info 

The return value will look something like:

{:worker=>:foo_worker, :status=>:running, :job_key=>"hello"} 

Information about all currently running workers can be obtained using:

MiddleMan.all_worker_info 
Return value will look like:
[{:worker=>:foo_worker, :status=>:running, :job_key=>"hello"}, \
     {:worker=>:foo_worker, :status=>:running, :job_key=>""}]