我有这样的回调:
after_commit :sponsored_notification, on: [:create, :update]
def sponsored_notification
current_time = Time.now.in_time_zone(self.try(:timezone)).strftime("%Y-%m-%d %H:%M:%S")
if current_time < self.try(:notify_time) && self.try(:is_sent) == false
run_time = self.updated_at + (self.try(:notify_time) - current_time.to_time).seconds
SponsoredNotificationWorker.perform_at(run_time, self.id)
end
end
我的问题是,当我创建一个赞助者然后更新它时,我收到了两个通知,但是我只想收到一个,应该发送最新的赞助者信息。我以为在这种情况下,回调被触发了两次。如果发生更新,如何跳过创建操作?
答案 0 :(得分:1)
我认为您需要重新考虑流程的外观,然后重构代码以添加片段以实现您所描述的内容。
您添加的回调仅在您:create
或:update
模型时才会触发,也就是说,如果您创建并更新该模型,则两次。如果您在每个呼叫中让一个工作人员排队,那么您将在传递给run_time
的{{1}}处执行该工作。
根据这里的最终目标,您可以做很多事情。您是否想一次通知一次,而不考虑后续更新?或者,您只是不想向用户发送通知?
在第一种情况下,我将逻辑移至工作程序:
perform_at
的模型添加notified
布尔标志。 true
,则跳过该对象,不要执行任何操作。 notified
来更改perform_at
。在第二种情况下,您可能希望使用“通知第一件事,然后等待1个小时,不通知其他任何东西”之类的内容。
perform_async
属性,并将其存储到回调中的notified_at
中。 Time.current
中的常量,例如以小时为单位)。 NOTIFICATION_WINDOW = 1
检查your_object#notified_at
,以查看是否需要通知或丢弃。 YourObject#NOTIFICATION_WINDOW.hours.ago
更改为perform_at
,所以请立即通知并保持一个小时的沉默。perform_async
),并且在接下来的一个小时内:create
之后的任何时间都不会做任何事情。 如果您想要更智能的东西,例如“将一堆通知分组”并将它们一起发送,那么您需要一种不同的方法。例如,在您的数据库中写入:update
个布尔标志的Notification
项,然后安排一个notified
任务以从数据库中获取所有rake
unnotified
您可以根据需要将DB分组并分批分发。这将意味着从当前的回调中删除该工作线程,并创建一个将定期调度的工作线程(每个5分钟?每小时?)。
这些是一些可能符合您要求的想法。首先澄清一下,尝试一些尝试,也许我们可以进一步缩小范围。