user5639287
user5639287

Reputation:

Rails listener for expired date

Is there such a thing as a listener in Ruby, or something similar?

For example, how can I check if user date is expired and needed to send an email few days before?


Thanks on your time

Upvotes: 0

Views: 673

Answers (1)

Tom Lord
Tom Lord

Reputation: 28305

There are, broadly speaking, two ways to do this:

  1. Regularly poll for things that are expiring soon, and send emails accordingly. For example, you could use a cron job that runs code along the lines of:

    Model.where(
      'expiration_date < ? AND expiration_date >= ?',
      Time.now + 3.days,
      Time.now
    ).each do |m|
      m.send_reminder_email
    end
    

    You may wish to write this code in a rake task, so your cron job simply triggers it. (You could also refactor the above query logic into a scope; e.g. Model.exires_soon.each {...}

    whenever is a popular library to configure cron jobs via a ruby DSL.

  2. Schedule future jobs, to be run at a specified time. This could be implemented via a redis-backed library (e.g. resque or sidekiq), or databased-backed (e.g. delayed_job). The precise implementation could vary depending on your needs (e.g. can an expiration_date ever change? How and when should the reminder email be cancelled?), but for example perhaps you could do the following:

    class Model < ApplicationRecord
      after_create :schedule_reminder_email
    
      def schedule_reminder_email
        ModelReminderWorker.perform_at(expiration_date - 3.days, self)
      end
    end
    
    class ModelReminderWorker
      include Sidekiq::Worker
    
      def perform
        # ...
      end
    end
    

Your chosen solution should be determined by the specific needs of your application; there is no silver bullet answer to the problem.

For instance:

  • How much consideration do you need to make for performance? With sidekiq you should be fine, but polling with frequent cron jobs could cause issues; to mitigate this, you could think about adding database indexes, or reading from a slave replica DB.
  • Are you concerned about sending emails at totally "random" times, e.g. 2am? Individually scheduled jobs could take this into consideration, but it would be easier to implement this within a single polling cron job. (Or perhaps this behaviour is precisely what's desired!)
  • Think about how best to log errors, handle deployments, control restarts, recover from crashes, and so on... There are a plethora of tools available for all of this, but it's an important thing to get right in a production application.

In general, my advice would be:

If you're new to this, and/or just want to get something functional up and running quickly, go with option 1 above. But if you're building something that needs to scale within a large system, seriously consider how best to implement option 2.

Upvotes: 4

Related Questions