我过去曾delayed_job
用于类似的任务。可能您可以使用与resque
. 本质上,您必须在当前作业结束时安排下一个作业。
class Subscription < ActiveRecord::Base
after_create :send_email
def send_email
# do stuff and then schedule the next run
ensure
send_email
end
handle_asynchronously :send_email, :run_at => Proc.new{|s| s.deliver_at }
def daily? (frequency == "daily");end
def max_attempts 1;end
def time_sec
hour,min=time.split(":").map(&:to_i)
hour.hours + min.minutes
end
def days_sec
day.nil? ? 0 : Time::DAYS_INTO_WEEK[day.to_sym].days
end
def interval_start_time
time = Time.now.in_time_zone(time_zone)
daily? ? time.beginning_of_day : time.beginning_of_week
end
def deliver_at
run_at = interval_start_time + days_sec + time_sec
if time.past?
run_at = daily? ? run_at.tomorrow : 1.week.from_now(run_at)
end
run_at
end
end
重新安排注意事项
更新代码以处理循环终止。您可以通过添加一个boolean
名为active
(true
默认设置为)的列来处理此问题。要禁用订阅,请将列设置为 false。
def send_email
return unless active?
# do stuff and then schedule the next run
ensure
send_email if active?
end
将max_attempts
作业的 设置为 1。否则您将淹没队列。在上述解决方案中,send_email
将尝试一次的作业。