Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Active Job - How to cancel a scheduled Action Mailer job?

I am using Delayed Job as my queuing backend for Active Job. I have not set up any custom jobs and plan on using Action Mailer to send out scheduled emails asynchronously. How can I prevent a scheduled email from being sent out?

For example, suppose the user can set up email reminders on my application. If the user sets up a reminder for three days in the future, a job will be created. If the user removes that email reminder, the job should be deleted.

Any help would be greatly appreciated!

like image 238
Alexander Avatar asked Jan 26 '16 21:01

Alexander


1 Answers

I decided to approach the problem differently. Instead of scheduling a job and destroying it, I'm just simply scheduling a job.

When the user sets up a reminder for three days in the future, a job is created, just as before. If the user removes the email reminder, the job will still run in three days but won't do anything. Here's an example setup:

# controllers/users_controller.rb

def schedule_reminder
  # Get the user that scheduled the reminder
  user = User.find_by_id(params[:id])

  # Create a reminder for the user
  reminder = user.reminders.create(active: true)

  # Schedule the reminder to be sent out
  SendReminderJob.set(wait_until: 3.days.from_now).perform_later(reminder.id)
end

def unschedule_reminder
  reminder = Reminder.find_by_id(params[:reminder_id])

  reminder.destroy
end

When the user schedules a reminder, def schedule_reminder is executed. This method creates a reminder and schedules a job that will run in 3 days. It passes in the reminder's ID as an argument so the job can retrieve the reminder when it runs.

When the user deletes the reminder, def unschedule_reminder is executed. This method finds the reminder and deletes it.

Here's what my SendReminderJob job looks like:

# jobs/send_reminder_job.rb

class SendReminderJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    # Get the reminder
    # args.first is the reminder ID
    reminder = Reminder.find_by_id(args.first)

    # Check if the reminder exists
    if !reminder.nil?
      # Send the email to the user

    end
  end
end

When this job runs in three days, it checks to see if the reminder is still set. If it is, it sends out an email to the user. Otherwise, it does nothing. Regardless of whether or not it does anything, this job is deleted after three days!

like image 107
Alexander Avatar answered Sep 23 '22 00:09

Alexander