Run single job manually

1,485 views
Skip to first unread message

Abel Tamayo

unread,
Aug 25, 2010, 3:26:04 PM8/25/10
to delayed_job
I'm trying to be inventive and use Delayed_Job to execute a command
after I receive confirmation from a 3rd party service (PayPal) but I'm
having trouble finding the method that will actually execute the
order. After much research of the source code this is what I got (I'm
using a regular Ruby object here instead for simplicity):

a = [3, 2, 6, 1]
job = a.delay.sort!
worker = Delayed::Worker.new

worker.run job #=> true
a #=> [3, 2, 6, 1] NOT SORTED

Again, I'm using an array here because that's easy to test on a
console, but where I'm going is that I create a worker, tell it to run
a job, get true but the job isn't ever run. What would be the way to
do it?

David Genord II

unread,
Aug 30, 2010, 11:46:48 AM8/30/10
to delay...@googlegroups.com
Why are you trying to manually run a single job?

David Genord II

Abel Tamayo

unread,
Aug 30, 2010, 12:03:04 PM8/30/10
to delay...@googlegroups.com
Well, it's something I was trying for a site where you can buy ads for your product once it's listed, but the ads wouldn't be created until I received a notification from Paypal telling the application that the payment was done. It's just a regular delayed job, only not automatically consumed but on demand.
It would go like this (just an example, not code from my actual project).

# ad_controller.rb

def new
  @product = Product.find params[:product_id]
  @job = @product.delay.create params[:ad]
  # Code redirecting user to Paypal passing @job id
end

Then we would receive the notification.

# payment_notifications_controller.rb

def create
  if params[:status] == 'Completed' then  
    job = Delayed::Job.find params[:custom][:job_id]
    worker = Delayed::Worker.new
    worker.run job
  end
end

Again, this is just concept, not my actual code and you probably won't understand it if you've never worked with Paypal. The thing is I looked into the code trying to find a way to make it work, the closest I came to what I was searching for that that "worker.run job" approach but wasn't able to make it work, but any ideas are welcome since I still think it would be an elegant way to work with e-commerce.

David Genord II

unread,
Aug 30, 2010, 12:10:45 PM8/30/10
to delay...@googlegroups.com
Might I suggest that you add a paid field, or similar, to your model instead of trying to delay creation until payment is received. Also use attr_protected so that the user can not set the parameter themselves.
David Genord II

Abel Tamayo

unread,
Aug 30, 2010, 12:39:36 PM8/30/10
to delay...@googlegroups.com
Yeah, I thought of doing that but I still think that delaying creating would be more elegant, clean and flexible and depending on the service you are providing it can be even necessary.

David Genord II

unread,
Aug 30, 2010, 2:19:11 PM8/30/10
to delay...@googlegroups.com
To do what you want to do, which I don't recommend, run
@job = Ad.delay(:run_at => 50.years.from_now).create((params[:ad] || {}).merge(:product_id => @product.id))
Do the create against the class and not the association proxy for more efficient and stable serialization.

Then to run the job on payment notification
job = Delayed::Job.find params[:custom][:job_id]
job.invoke_job # This will NOT destroy the job
job.destroy

worker.run will run and remove the job but it will hide any errors behind the rescheduler and you don't want the job rescheduled.

David Genord II

Abel Tamayo

unread,
Aug 30, 2010, 4:01:11 PM8/30/10
to delay...@googlegroups.com
Thanks!
Reply all
Reply to author
Forward
0 new messages