views:

81

answers:

1

Hi,

I read the documentation on workers and delayed_job and couldn't follow exactly, so wanted to get head-start with some strategy and sample code.

I have a controller which I use to send emails one by one. Now each day I want to check which emails need to be sent for the day, and then send them through heroku as a delayed_job.

How do I begin to approach this? thanks.

This is what I'm coming up with based on the answers:

Using the 'whenever' gem, I created the following schedule.rb

  every 1.day, :at => '4:30 am' do

    heroku = Heroku::Client.new(ENV['HEROKU_USER'], ENV['HEROKU_PASS'])
    heroku.set_workers(ENV['HEROKU_APP'], 1)

    Contact.all.each do |contact|
      contact_email = contact.email_today

      unless contact.email_today == "none"
        puts contact.first_name
        puts contact_email.days
        puts contact.date_entered

        Delayed::Job.enqueue OutboundMailer.deliver_campaign_email(contact,contact_email)
      end

    end

    heroku.set_workers(ENV['HEROKU_APP'], 0)
  end

To determine whether I should send an email today or not, I created the method for contact.rb:

  def email_today

    next_event_info = self.next_event_info # invokes method for contact

    next_event = next_event_info[:event]
    delay = next_event_info[:delay]

    if next_event.class.name == "Email" && from_today(self, next_event.days) + delay < 0 #helper from_today
      return next_event      
    else
      return "none"
    end

  end

Does this look right? I am developing on windows and deploying to heroku so don't know how to test it...thanks!

+3  A: 

If you're sending emails out once a day, you probably want to start by add the cron addon to your application, which will fire a rake task once-per day.

Obviously, you'll also need to add the delayed_job plugin (http://docs.heroku.com/delayed-job). In addition, your app will need to be running at least one worker.

Then it's just a matter of doing your mail work from within your cron rake task. For example, if you had a mailer called 'UserMailer', your cron could look something like this:

#lib/cron.rb
task :cron => :environment do
  User.all.each do |user|
    Delayed::Job.enqueue UserMailer.deliver_notification(user)
  end
end

If you're only using background tasks to send these emails, you could probably add also some logic in your cron task, and your mailer methods to add and remove workers as required, which will save you having to pay for the workers while they're not in use.

theTRON
can I test teh cron functionality my local windwos environment? Is there a way to add workers from within the controller (versus using the console)?
Angela
I put my attempt to turn on and off the workers for this job (so I don't keep paying)...not sure if it is right....what do you think?
Angela
Check out Pedro's delayed job fork which includes auto scaling heroku workers. http://github.com/pedro/delayed_job/tree/autoscaling
mark
would you recommend that versus collectiveidea? could I just do it manually as I did above, I couldn't figure out the syntax for the pedro autoscaler....
Angela
I am getting an error: Cannot enqueue items which do not respond to perform .... did I need to do anything special with UserMailer? It's just a regular mailer which I use synchronously....
Angela