Amit Pal
Amit Pal

Reputation: 11062

How to perform Asynchrnous task in rails using delayed_jobs?

Task: Delete an item in Async manner [HomeWork]

I have already configured Active jobs with delayed_jobs in my rails application but I am still confused about performing Async task in rails project.

Let's take an example: I have some item to delete from the database but I want to do it in Async manner. I also read about perform_later or perform_now method in delayed_job blogs. Here is my code which is working fine:

Controller class

 def destroy
   PostJob.perform_now(params[:id])
   respond_to do |format|
    format.xml  { head :ok }
    format.js { render 'posts.js.erb' }
  end
 end

Job class

class PostJob < ActiveJob::Base
 queue_as :default

 def perform(id)
  @post = Post.find(id)
  @post.destroy
 end
end

According to official doc of delayed_jobs I can add handle_asynchronously in the end of method to run in async manner. How can I implement in this case?

My Question:

  1. When I am looking at destroy method it is not deleting the element in Async way. However every steps written in destroy method is in Synchronous. Am I wrong?
  2. If it's not then How can I implement destroy method to delete post in async manner?
  3. Backgrounding task and cron job are same thing?

Edit -1

After giving suggestion by A Fader Darkly, I changed perform_now to perform_later which is working perfectly for Async process but it is not deleting the entry from table (code is fine because it works when i user perform_now).

Also when I am running job manually by following command, Everything works fine:

rake jobs:work

Is there any way to execute delay_job task as soon as the queue get some new data?

Upvotes: 2

Views: 2960

Answers (1)

A Fader Darkly
A Fader Darkly

Reputation: 3636

If you change your destroy method to call:

PostJob.perform_later(params[:id])

it should happen asynchronously. If not, you have some more set-up to do.

For your questions:

  1. Yes you are right, but what you say is a tautology. Everything in that method is synchronous - the job queue isn't used because of the perform_now. Thus destroy isn't deleting in an async way.
  2. See above.
  3. Cron jobs work on the operating system level and are scheduled regularly for particular times. You could have a cron job working every minute, for example, or every day, or week (on a particular day at a particular time). They run from a schedule file called a crontab.

'Backgrounding' a task simply stops it from taking over the IO of your terminal session. So you can carry on using the terminal while the process runs in the background. Generally this is done on an ad-hoc basis, so you don't have to wait for a heavy operation to complete before going on to do different tasks.

EDIT

Based on edits to the question, it sounds like Delayed Job daemon needs to be started. From the instructions:

Note: For Rails 4 replace script/delayed_job with bin/delayed_job When running a queue locally, omit the 'RAILS_ENV=production' part of commands.

Running Jobs script/delayed_job can be used to manage a background process which will start working off jobs.

To do so, add gem "daemons" to your Gemfile and make sure you've run rails generate delayed_job.

You can then do the following:

RAILS_ENV=production script/delayed_job start RAILS_ENV=production script/delayed_job stop

Runs two workers in separate processes.

RAILS_ENV=production script/delayed_job -n 2 start RAILS_ENV=production script/delayed_job stop

Set the --queue or --queues option to work from a particular queue.

RAILS_ENV=production script/delayed_job --queue=tracking start RAILS_ENV=production script/delayed_job --queues=mailers,tasks start

Use the --pool option to specify a worker pool. You can use this option multiple times to start different numbers of workers for different queues.

The following command will start 1 worker for the tracking queue,

2 workers for the mailers and tasks queues, and 2 workers for any jobs:

RAILS_ENV=production script/delayed_job --pool=tracking --pool=mailers,tasks:2 --pool=*:2 start

Runs all available jobs and then exits

RAILS_ENV=production script/delayed_job start --exit-on-complete

or to run in the foreground

RAILS_ENV=production script/delayed_job run --exit-on-complete

Upvotes: 1

Related Questions