Abhishek
Abhishek

Reputation: 341

How to create short lived Database entries in ruby on rails?

I want to create some notifications that should be short-lived, 1 day or so. So that I can send out those notifications if the user is accessing all notifications today, but not tomorrow.

Suppose someone is creating some post with, I want to send them a notification whenever post upload is successful. But that notification won't matter tomorrow and will create unnecessary confusion.

I considered using Sidekiq for the process, in an after_commit hook, trigger a sidekiq job to run after 18 hrs, something like:

after_commit :trigger_destroyer

private 

def trigger_destroyer
  if notification_type == 'shortlived'
    NotificationDestroyer.perform_in(3.hours.from_now, id)
  end
end

Or I can run a cron job that will read created_at, and type of notifications and delete them there.

Is there any better approach?

Upvotes: 0

Views: 91

Answers (3)

max
max

Reputation: 101811

You could create a ActiveJob or Rake task that purges the entire table instead:

class NotificationCleanupJob < ApplicationJob
  queue_as :default

  def perform
    Notification.where('created_at < ?', 30.days.ago).delete_all
  end
end

There are various gems that can be used to set up recurring jobs such aswhenever,chrono, clockwork and rufus-scheduler. Heroku also has a built in scheduler.

This is far more effective then setting up jobs that do this one row at a time and which will pretty much constantly eat up worker processes.

This should be combined with filtering when you display / use the records in Rails.

Upvotes: 3

lacostenycoder
lacostenycoder

Reputation: 11196

This is an elaboration on the previous answer. You probably just want to set up a scope for displaying the notifications to the users, so something like this should work.

class Notification
  belongs_to :user

  STALE_DAYS ||= (ENV['STALE_NOTIFICATIONS_PERIOD'].to_i || 30).min
  scope :active { where('created_at > ?', (STALE_DAYS).days.ago) }
  scope :stale { where('created_at <= ?', (STALE_DAYS).days.ago) }

  def to_s
    self.text # or whatever name of notification body field is
  end
end

Run this job ever stale days.

class NotificationCleanupJob < ApplicationJob
  queue_as :default

  def perform
    Notification.where('created_at < ?', (stale).days.ago).delete_all
  end
end

Then in your views you can do something like this:

<% @user.notifications.active.each |notification| %>
  <div class="notification">
    <%= notification %>
  </div>
<% end %>

Upvotes: 0

Jon
Jon

Reputation: 10898

If you want these notifications displayed when the user visits the site, you don't need to do anything special with Sidekiq, Redis, Cron, etc. All you need to do is load notifications younger than 24 hours and display them.

As an additional task, you could delete any notifications older than 24 hours at the same time, perhaps also deleting notifications you've displayed ... depending on your needs.

However, if these notifications are to be sent directly to the user without them performing an action (loading a page) to trigger the notification, then you'll need to use some kind of scheduling system like Sidekiq.

Upvotes: 1

Related Questions