开发者

How do I save an object only after a delayed_job is successfully completed?

I have a delayed_job designed to send an email using a mailer.

Upon completion, I need to record that the email was sent -- I do this by saving the newly created ContactEmail.

Right now, the new ContactEmail records gets saved even if the delayed_job fails.

How do I correct that so that the new ContactEmail is only saved when the mailer is successfully sent?

Here is the snippet from the cron task which calls the delayed_job:

    puts contact_email.subject

    contact_email.date_sent = Date.today
    contact_email.date_created = Date.today

    contact_email.body = email.substituted_message(contact, contact.colleagues)

    contact_email.status = "sent" 

    #Delayed::Job.enqueue OutboundMailer.deliver_campaign_email(contact,contact_email)
    Delayed::Job.enqueue SomeMailJob.new(contact,contact_email)

    contact_email.save #now save the record

Here is the some_mail_job.rb

class 开发者_开发问答SomeMailJob < Struct.new(:contact, :contact_email) 
   def perform
     OutboundMailer.deliver_campaign_email(contact,contact_email)
   end
 end

And here is the outbound_mailer:

class OutboundMailer < Postage::Mailer 

  def campaign_email(contact,email)
    subject    email.subject
    recipients contact.email
    from       '<me@me.com>'
    sent_on    Date.today

    body       :email => email
  end


You could update the status in the perform of the job itself.

For example, something like:

contact_email.status = 'queued'
contact_email.save
contact_email.delay.deliver_campaign_email

And then in your ContactEmail class, something to the effect of

def deliver_campaign_email
  OutboundMailer.deliver_campaign_email(self.contact, self)
  self.status = 'sent'    # or handle failure and set it appropriately
  self.save
end

delayed_job has some magic bits that it adds to your models that will deal with the persistence.

In order to deal with your OutboundMailer throwing an exception, you can do something like so:

def deliver_campaign_email
  begin
    OutboundMailer.deliver_campaign_email(self.contact, self)
    self.status = 'sent'
  rescue
    self.status = 'failed' # or better yet grab the the message from the exception
  end
  self.save
end


  1. You need synchronic delivery so stop using delayed job in this case and do standard mailer delivery.
  2. or add success column to you ContactEmail - initialy save it with false then update in job to true
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜