【问题标题】:How to create short lived Database entries in ruby on rails?如何在 ruby​​ on rails 中创建短暂的数据库条目?
【发布时间】:2019-12-15 08:16:11
【问题描述】:

我想创建一些应该是短暂的通知,大约 1 天。这样,如果用户今天访问所有通知,我就可以发送这些通知,但明天不行。

假设有人正在创建一些帖子,我想在帖子上传成功时向他们发送通知。但该通知明天就无关紧要了,而且会造成不必要的混乱。

我考虑过在进程中使用Sidekiq,在after_commit 挂钩中,触发sidekiq 作业在18 hrs 之后运行,类似于:

after_commit :trigger_destroyer

private 

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

或者我可以运行一个读取 created_at 和通知类型的 cron 作业并在那里删除它们。

有没有更好的方法?

【问题讨论】:

  • 我不确定您是否清楚地解释了您要解决的问题。您是否尝试过白板您的用户故事?是否有不止一种类型的动作会触发通知?有很多方法可以解决一个问题。但在明确定义用户故事之前,不能推荐任何一种。
  • 首先想到的是使用 Redis,它可以让您设置数据的到期时间。但是,如果您想将其保留在 SQL 中,则必须询问是否真的有必要在数据库中的所有记录到期时删除它们,或者您的“通知发送者作业”(假设您有一个)是否可以忽略旧的通过比较时间戳记录
  • @lacostenycoder 是的,应该有n 类型的通知。比如commentlikefollow等等。
  • @maxpleaner 我确实尝试过使用Redis,但是,数据应该有多个关联,这一切都让它太乱而无法处理。您建议的第二种方法似乎可行,但是,它只会不断增加表行。但是,该选项也是最不混乱的选项。

标签: ruby-on-rails ruby postgresql activerecord


【解决方案1】:

您可以创建一个 ActiveJob 或 Rake 任务来清除整个表:

class NotificationCleanupJob < ApplicationJob
  queue_as :default

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

有多种 gem 可用于设置重复作业,例如wheneverchronoclockworkrufus-scheduler。 Heroku 也有一个built in scheduler

这比设置一次执行这一行的作业要有效得多,这几乎会不断消耗工作进程。

当您在 Rails 中显示/使用记录时,这应该与过滤相结合。

【讨论】:

    【解决方案2】:

    如果您希望在用户访问网站时显示这些通知,则无需对 Sidekiq、Redis、Cron 等进行任何特殊操作。您只需加载小于 24 小时的通知并显示它们即可。

    作为一项附加任务,您可以同时删除任何超过 24 小时的通知,也许还可以删除您已显示的通知...取决于您的需要。

    但是,如果这些通知要直接发送给用户,而不需要他们执行操作(加载页面)来触发通知,那么您需要使用某种调度系统,例如 Sidekiq。

    【讨论】:

      【解决方案3】:

      这是对上一个答案的详细说明。您可能只是想设置一个向用户显示通知的范围,所以这样的事情应该可以工作。

      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
      

      stale 天运行此作业。

      class NotificationCleanupJob < ApplicationJob
        queue_as :default
      
        def perform
          Notification.where('created_at < ?', (stale).days.ago).delete_all
        end
      end
      

      那么在你的观点中你可以这样做:

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

      【讨论】:

        猜你喜欢
        • 2017-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-01
        • 2016-02-16
        • 1970-01-01
        相关资源
        最近更新 更多