Rails防抖延迟作业后台任务?去除重复项

4

防抖动(Debouncing)是一种常见的方法,可以推迟一个函数或作业的执行,直到一定的时间过去。

应用场景:在多个用户活跃聊天的对话中,他们不应该为每条消息收到一封电子邮件通知。但很可能在几分钟的沉默之后,如果这些消息没有被读取,用户应该看到一个通知。

Delayed_Job

目前没有解决方案,但有相关问题:https://github.com/collectiveidea/delayed_job/issues/72

Sidekiq

https://github.com/hummingbird-me/sidekiq-debounce


在RabbitMQ中,我使用死信交换机。 - jvillian
3个回答

3
做自己并不是那么糟糕。
class AdminJob
  def self.debounce(job, args={})
    handler = YAML.dump(job)
    count = Delayed::Job.where(handler: handler).where('locked_at IS NULL').delete_all
    Rails.logger.info("deleted: #{count} jobs")
    Delayed::Job.enqueue(job, args)
  end
end

代替写作如下内容:
Delayed::Job.enqueue(YourJobName.new(account_id), {run_at: 10.minutes.from_now})

您现在正在编写如下内容:
AdminJob.debounce(YourJobName.new(account_id), {run_at: 10.minutes.from_now})

Delayed job将您的作业参数序列化为YAML,然后将其保存到数据库中作为handler。因此,如果您连续10次调用AdminJob.debounce(...),它将在每个调用之前删除。

确保给自己足够的时间(5分钟等)让用户继续采取行动。如果您在1秒后运行作业,他们很可能会继续采取行动并再次触发。

是的,我在3年后回答自己的问题...


我不确定,但我的猜测是执行删除所有查询将导致数据库引擎仍然需要进行数据库查找(类似于select...where)。在对包含数千条记录(或数万条记录)的大型数据库上对串行化列(长字符串)执行此操作可能会非常缓慢。如果这是使用可以很好索引的作业唯一键或签名完成的,则这将是一个不错的方法。 - Peter P.

0
我会安排一个定期任务,比如每5分钟检查是否有需要通知的人。是的,这似乎是一个昂贵的操作,但对于您的用例,我目前没有看到其他解决方案。所以假设您有10个用户使用聊天功能。每5分钟,您可以检查是否有用户没有看到某些消息,如果是,则只在他们N分钟不活动时通知他们。
要安排这样的任务,您可以使用crono gem。请参阅answer
Crono让您可以做到这样的事情:
Crono.perform(CheckUsersToBeNotifiedJob).every 5.minutes

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接