So I'm just needing a bit of advice here.
I have an app that I deployed to heroku, and I have mailers set up so when things like 'record is added' mailers run and send email to users.
One type of mailer I'd like to create is one that goes out on a specific day.
For example, I might say, send mailer on November 3rd at 6:00 am.
How would I go about scheduling that? I mean I can't really use .deliver_later because I realize when the dyno goes to sleep the job will no longer be queued (at least that's how I understand it)
SO I supposed I need to use something like Redis, or Sidekiq, or perhaps Heroku Scheduler? Any advice on this subject would be extremely helpful. I've read a few SO posts about this, but I'm still lost.
Thank you in advanced.
You can achieve it using Sidekiq.
Sidekiq allows you to schedule the time when a job will be executed. You use perform_in(interval_in_seconds, *args) or perform_at(timestamp, *args) rather than the standard perform_async(*args):
MyWorker.perform_in(3.hours, 'mike', 1)
MyWorker.perform_at(3.hours.from_now, 'mike', 1)
This is useful for example if you want to send the user an email 3 hours after they sign up. Jobs which are scheduled in the past are enqueued for immediate execution.
In your case, you can achieve it using perform_at(timestamp, *args) have a look at code -
time_stemp = DateTime.parse("09/11/2020 06:00 AM")
SendMailToUserWorker.perform_at(time_stemp, args)
More information here -
https://github.com/mperham/sidekiq/wiki/Scheduled-Jobs
I haven't used Heroku. In my case, I use sidekiq and sidekiq-cron to do some cron job
I want to trigger an event, specifically send out an email and update attributes on some models, on a specific DateTime (which is a column in one of my models).
I have searched around but have not really found any solutions to this.
Is there any way of achieving this?
You can use a queueing solution along with a scheduler.
Queueing solution: Resque with Redis backend
https://github.com/resque/resque
Scheduling solution : https://github.com/resque/resque-scheduler
Resque.enqueue_at(5.days.from_now, SomeJob)
You can schedule a job to run at a particular date. Combine this with the ability to setup a schedule.
Say you trigger the first job on Jan 1st and want it to run every 30 days.
You can use a queuing solution to send out email asynchronously : something like Resque with a Redis backend.
I'm creating a Todo list app in Rails 4 to learn more about running background jobs and cron. Currently I use Sidekiq to send task confirmation mails asynchronously EmailWorker.perform_in(5.minutes, #todo.id).
Now, I have a Schedule field in the task creation form and it's a DateTime field. I would like to know how to send the task reminder mail at that exact date and time. Do I have to calculate the days and hours from Time.now and covert them to minutes using a model method and pass in the value or is there an easier way to get this done?
I tried a couple of different ideas. Finally, I got it to work by converting the difference between Time.now and the scheduled time in minutes.
What gems/technology would be best suited for creating an auction style system where a certain action is run when a given duration of time has expired? (ie. sending an email message to users telling them the auction is over).
If you want real time notification I think resque_sceduler suites you. So you can schedule the task to send the email for the exact time the auction ends.
If there is no problem to wait some minutes or hours you can use cron jobs or something like that. There are many options actually.
How would I go about sending an email to a user, say, 48 hours after they sign up, in Ruby on Rails? Thanks!
As Joseph Daigle mentioned, you need to obviously record the exact date and time the user registered. After that, you need a cron running every certain number of minutes (every hour, for example) checking to see if there's any new users whose registration time is greater than 48 hours, send a mail to said user and mark that user as already emailed, so you don't email them again.
As per the actual mail sending, check out the following documentation page:
http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
It has all you need to know to send mails with RoR.
I recommend that you use the latest version of BackgrounDRb to handle this. You can read about BackgrounDRb here: http://backgroundrb.rubyforge.org/
In order to queue a message for later delivery, the BackgrounDRb client code (in your application model's after_create callback, maybe) could look something like this:
MiddleMan(:email_worker).enq_send_email_task(:message => #message,
:job_key => "notify1",
:scheduled_at => Time.now + 48.hours)
You'd have to build a BackgrounDRb worker to handle sending the email:
# RAILS_ROOT/lib/workers/email_worker.rb
class EmailWorker < BackgrounDRb::MetaWorker
set_worker_name :email_worker
def send_email_task(message)
# ... Code to send the email message
end
end
Note that in order to use BackgrounDRb in this way, you have to use persistent job queues, so make sure you run the migration included with BackgrounDRb to set up the persistence table in your application.
BackgrounDRb is started separately from Rails (mongrel, apache, etc) using 'script/backgroundrb start', so make sure that you add the daemon to whatever process monitoring you're using (god, monit, etc) or that you create an /etc/init.d script for it.
First you're going to need a running daemon or background service which can poll your queue (probably from in a database) every few minutes.
The algorithm is pretty simple. Record the time of the user event in the queue. When the daemon checks that item in the queue, and the time difference is greater than 48 hours, prepare the e-mail to send.
You can queue jobs with a delay using async observer. Ideally, anything you have that isn't known to be instant (or very close to it) all the time should pass through something like that.
I wrote a plugin called acts_as_scheduled that may help you out.
acts_as_scheduled allows you to manage
scheduled events for your models.
A good example of this is scheduling
the update of RSS Feeds in a
background process using Cron or
BackgroundRB.
With acts_as_scheduled your schedule
manager can simply call
"Model.find_next_scheduled()" to grab
the next item from the database.
How I would approach this is by creating a scheduling controller, that will query the database for the next_scheduled and then use a mailer to send the message. The you set up a Cron Job to call the controller periodically using WGET or CURL. The advantage of the Cron/Controller approach is that no further infrastructure or configuration is required on the server and you avoid complicated threading code.
I think I'd be inclined to store the need for the email and the earliest time after which it should be sent, somewhere separate, then have my things-to-do task look at that. That way I only have to process as many records as there are emails to be sent, rather than examine every user every time, which would either get tedious or require an otherwise probably unnecessary index. As a bonus, if I had other tasks to be performed on some sort of a diarised basis, the same construct would be useful with little modification.