我有一个佣金任务send_emails
,可以向很多人发送电子邮件。我在控制器中调用这个rake任务,如Rake in Background railscast中所述。但是我想安排这个rake任务在特定的日期和时间运行,这对于每天都不一样(这不是一个cron工作)。 日期和时间是从表单动态设置的。
对于上面实现的用于发送电子邮件的rake任务,我想向最终用户显示邮件发送过程的状态。例如,假设rake任务中有一个response
对象,我可以将其用作response.status
,response.delivered?
,response.address
等。如何访问此对象(或在我的控制器的rake文件中的任何变量?
我不想使用delayed_job
,但希望实现 run_at
和in_the_future
的功能。此外whenever
宝石获胜我能够解决我的第一个问题因为我无法将日期和时间传递给它的调度程序。
答案 0 :(得分:1)
我会为邮件作业创建新模型,如下所示:
应用/模型/ mail_job.rb 强>
class MailJob
attr_accessible :email, :send_at, :delivered
scope :should_deliver, -> { where(delivered: false).where('send_at <= ?', Time.now) }
def should_deliver?
!delivered? && send_at <= Time.now
end
...
end
并使用Sidekiq + Sidetiq,每分钟(或任何其他间隔)运行并检查应该传递的邮件作业。
希望这有帮助!
答案 1 :(得分:1)
首先,从控制器调用rake任务是一种不好的做法。 Ryan在2008年发布了该视频,因为已经出现了许多更好的解决方案。你不应该忽视它。
我建议您使用delayed_job
,它可以很好地满足您的需求。因为,如果你想动态调用任务,应该有一些检查器,它将每秒连续检查欲望字段。延迟作业每次都会检查其数据库,您可以使用它。
无论如何,你可以使用这样的东西
def self.run_when
Scheduler.all.each do |s|
if d.dynamically_assigned_field < 1.second.ago
d.run_my_job!
d.status = "finished"
d.save
end
end
end
而且,在模型中你可以做这样的事情
def run_my_job!
self.status = "processing"
self.save
long_running_task
end
还有一件事你应该记住,如果太多的工人/批处理/ cron作业在同一时间运行,它将争夺资源并可能进入死锁状态。根据您的服务器容量,您应该限制正在运行的作业。
Sidekiq也是您可以考虑的好选择。就个人而言,我喜欢sidekiq,因为它不会每次都打到我的数据库,非常有效地扩展。它使用redis但价格昂贵。