Alexander
Alexander

Reputation: 4257

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!

Upvotes: 5

Views: 3769

Answers (2)

Alexander
Alexander

Reputation: 4257

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!

Upvotes: 8

Dmitry Polyakovsky
Dmitry Polyakovsky

Reputation: 1585

I created app/models/delayed_backend_mongoid_job.rb.

class DelayedBackendMongoidJob
  include Mongoid::Document    
  field :priority,      type: Integer
  field :attempts,      type: Integer
  field :queue,         type: String
  field :handler,       type: String
  field :run_at,        type: DateTime
  field :created_at,    type: DateTime
  field :updated_at,    type: DateTime
end

If you are using ActiveRecord you need to adjust the model file. Then I installed rails_admin and I can view/edit any of the records in that table.

If you have a job scheduled to run in 2 days all you have to do is delete the record and DJ will never pick it up.

Upvotes: 1

Related Questions