Ruby on rails Rails 3.1/rake-不带队列的日期特定任务
我想给我的用户一个选项,让他们在特定的(用户指定的)时间向他们发送帐户统计的每日摘要 让我们假设以下模型:Ruby on rails Rails 3.1/rake-不带队列的日期特定任务,ruby-on-rails,ruby,ruby-on-rails-3,rake,scheduled-tasks,Ruby On Rails,Ruby,Ruby On Rails 3,Rake,Scheduled Tasks,我想给我的用户一个选项,让他们在特定的(用户指定的)时间向他们发送帐户统计的每日摘要 让我们假设以下模型: class DailySummery << ActiveRecord::Base # attributes: # send_at # => 10:00 (hour) # last_sent_at # => Time of the last sent summary end 课堂每日总结10:00(小时) #上次发送时间 #=>上次发送摘要的时间
class DailySummery << ActiveRecord::Base
# attributes:
# send_at
# => 10:00 (hour)
# last_sent_at
# => Time of the last sent summary
end
课堂每日总结10:00(小时)
#上次发送时间
#=>上次发送摘要的时间
结束
现在是否有最佳实践,如何通过电子邮件将此帐户摘要发送到特定时间
目前,我有一个无限的rake任务正在运行,它会永久性地检查电子邮件是否可以发送,我想将每日摘要生成和发送放在这个rake任务中。
我想我可以用以下伪代码来解决这个问题:
while true
User.all.each do |u|
u.generate_and_deliver_dailysummery if u.last_sent_at < Time.now - 24.hours
end
sleep 60
end
为true时
User.all.each do|u|
u、 如果上次发送时间
但我不确定这是否有一些隐藏的警告
注意:我不想使用resq或redis之类的队列强>
编辑:添加睡眠(已在我的脚本中添加)
编辑:这是一项时间紧迫的服务(交易价格通知),因此应该尽可能快。这就是为什么我不想使用基于队列或作业的系统的背景。我使用Monit来管理这个rake任务,它工作得非常好。只有两种主要方法可以延迟执行。当站点上的用户点击某个页面时运行脚本,这样做效率低且不完全准确。或者使用某种后台进程,无论是cron作业还是resque/delayed作业等 虽然让rake进程永远运行的方法可以很好地工作,但效率很低,因为一旦完成,您就要24/7地对用户进行迭代,比如:
while true
User.where("last_sent_at <= ? OR last_sent_at = ?", 24.hours.ago, nil).each do |u|
u.generate_and_deliver_dailysummery
end
sleep 3600
end
为true时
User.where(“last_sent_at实际上只有两种主要方法可以执行延迟执行。当站点上的用户点击页面时运行脚本,这是低效且不完全准确的。或者使用某种后台过程,无论是cron作业还是resque/延迟作业/等等
虽然让rake进程永远运行的方法可以很好地工作,但效率很低,因为一旦完成,您就要24/7地对用户进行迭代,比如:
while true
User.where("last_sent_at <= ? OR last_sent_at = ?", 24.hours.ago, nil).each do |u|
u.generate_and_deliver_dailysummery
end
sleep 3600
end
为true时
User.where(“last_sent_at您可以这样做,您还需要检查您要发送的时间。因此,从伪代码开始并添加到伪代码:
while true
User.all.each do |u|
if u.last_sent_at < Time.now - 24.hours && Time.now.hour >= u.send_at
u.generate_and_deliver_dailysummery
# the next 2 lines are only needed if "generate_and_deliver_dailysummery" doesn't sent last_sent_at already
u.last_sent_at = Time.now
u.save
end
end
sleep 900
end
为true时
User.all.each do|u|
如果上次发送时间=u.send\u在
u、 生成和交付每日摘要
#仅当“generate_and_deliver_dailysummery”尚未在最后发送时才需要下两行
u、 上次发送时间=Time.now
u、 拯救
结束
结束
睡900
结束
我还添加了sleep
,这样您就不会不必要地重击数据库。您可能还想研究将循环限制在您需要发送给的一组用户。类似于Zachary建议的查询将比您现有的查询效率更高。您可以这样做,还需要检查您想要使用的时间从伪代码开始并添加到它:
while true
User.all.each do |u|
if u.last_sent_at < Time.now - 24.hours && Time.now.hour >= u.send_at
u.generate_and_deliver_dailysummery
# the next 2 lines are only needed if "generate_and_deliver_dailysummery" doesn't sent last_sent_at already
u.last_sent_at = Time.now
u.save
end
end
sleep 900
end
为true时
User.all.each do|u|
如果上次发送时间=u.send\u在
u、 生成和交付每日摘要
#仅当“generate_and_deliver_dailysummery”尚未在最后发送时才需要下两行
u、 上次发送时间=Time.now
u、 拯救
结束
结束
睡900
结束
我还添加了sleep
,这样您就不会不必要地重击数据库。您可能还想研究将该循环限制为仅限于您需要发送到的用户集。类似于Zachary建议的查询将比您现有的查询效率更高。定期运行任务是cron的作用所在。the gem(https://github.com/javan/whenever)使为应用程序配置cron定义变得简单
随着应用程序的扩展,您可能会发现rake任务的运行时间太长,而且队列在cron调度上非常有用。您可以使用cron控制何时调度交付,但实际由工作池执行交付。cron的作用是定期运行任务(https://github.com/javan/whenever)使为应用程序配置cron定义变得简单
作为应用程序的比例,您可能会发现RAKE任务运行时间过长,队列在CRON调度之上是有用的。您可以使用CRON来控制交付时的调度,但实际上是由一个工作池执行的。
< P>如果您不想使用队列-考虑延迟作业(排序为一个可怜的MAN队列)-它确实作为一个类似于您正在做的rake任务运行
它将所有任务存储在作业表中,通常在您添加任务时,它会将其排队以尽快运行,但是您可以覆盖它以将其延迟到特定时间
您可以将DayLyPrimeCype转换为DayySyryYeWork,一旦完成,它可以在下一天运行中重新排队自己的实例 如果您不想使用队列——考虑延迟作业(排序为一个穷人队列)-它运行的RAKE任务类似于您正在做的
它将所有任务存储在作业表中,通常在您添加任务时,它会将其排队以尽快运行,但是您可以覆盖它以将其延迟到特定时间
您可以将DailySummary类转换为DailySummary作业,一旦完成,它就可以为自己的新实例重新排队,以便在接下来的几天运行您是如何更新last\u sent\u at
属性的
如果你使用
last_sent_at += 24.hours
并初始化为last\u sent\u at=Time.now.at\u开始日期+send\u at
一切都会好起来的
不要在=时间使用上次发送。现在使用。这是bec