我已经建立了一个基于Measurement
运行MeasurementSetting
的系统。每个设置使用ice_cube
(以及一些其他测量属性)定义计划。我能够为每个设置编辑此计划,然后使用以下内容轮询下一次出现:
def next_occurrences
schedule.occurrences(Time.now + 1.day)
end
这给了我一组时间戳,应该有一个Measurement
。
现在,我也安装了Sidekiq,并且我可以使用MeasurementWorker
在特定时间成功运行测量。为此,我只创建一个空的Measurement
记录,将其与其设置相关联,然后perform_async
(或perform_at(...)
)此工作人员:
class MeasurementWorker
include Sidekiq::Worker
sidekiq_options retry: 1, backtrace: true
def perform(measurement_id)
Measurement.find(measurement_id).run
end
end
缺少的是我不知何故需要根据设置的时间表创建空测量。但是我该怎么做呢?
说我有以下数据:
MeasurementSetting
,ID为1,每日时间安排在中午12:00 MeasurementSetting
,每小时(上午12:00,上午01:00等)按小时计划。现在我需要:
Measurement
,使用设置1,每天12点Measurement
,每隔一小时使用设置2 但是怎么样?
我应该每分钟检查是否有MeasurementSetting
被定义为 now ,然后创建空的Measurement
记录,然后运行它们使用Sidekiq的具体设置?
或者我应该提前使用他们的设置生成空Measurement
条记录,并以这种方式安排它们?
实现这一目标的最简单方法是什么?
答案 0 :(得分:0)
我会每分钟使用cron来寻找应该立即运行的MeasurementSettings。如果是,请创建一个Sidekiq作业立即运行,填充测量值。
答案 1 :(得分:0)
以下是我成功完成的方式:
使用字段planned_start_time
更新应按计划运行的模型。这将保留计划开始的时间。
使用whenever
Gem每分钟运行一次类方法,例如Measurement.run_all_scheduled
在该方法中,浏览每个设置(即时间表的位置),并检查它是否正在发生:
setting = MeasurementSetting.find(1) # get some setting, choose whatever
schedule = setting.schedule
if not schedule.occurring_at? Time.now
# skip this measurement, since it's not planned to run now
如果是这种情况,那么检查我们是否可以通过查看数据库来运行测量,如果没有任何先前的测量具有相同的计划开始时间。首先,我们必须获得当前时间表的计划开始时间,例如现在是3点04分。计划的开始时间可能是下午3点。
this_planned_start_time = schedule.previous_occurrence(Time.now).start_time
然后我们检查最后一次测量的开始时间(limit(1)
是否只是最后一次)是否相同。
if Measurement.limit(1).last.planned_start_time != this_planned_start_time
# skip this one, since it was already run
如果没有,我们可以继续设置测量值。
measurement = Measurement.create measurement_setting: setting,
planed_start_time: this_planned_start_time
然后运行它:
measurement.delay.run