Sidekiq 如何在每个时区的指定时间执行任务?

3

使用Sidekiq,有哪些策略可以让它在每个时区的特定时间执行?

例如,我需要Sidekiq在世界各地以下时间和时区每天执行任务:

... 美国东部时间晚上8:00 美国中部时间晚上8:00 美国山区时间晚上8:00 美国太平洋时间晚上8:00 ...


将那些时间转换为协调世界时有什么问题吗? - spickermann
我们在数据库中记录所有时间都是以协调世界时(UTC)为准。也许我的问题没有表达清楚...我们的用户遍布全球,我们想在每个用户所在的时区的晚上8点发送“每日摘要”。这样说您明白了吗?@spickermann - Chad Taylor
Sidekiq Enterprise 可以实现这一点,但免费版和专业版不包括此功能。 - coreyward
你知道用户所在的时区吗?这些信息是如何存储的(通过时区缩写(可能会有歧义),偏移量,tz)? - spickermann
是的,我们有偏移量、时区,甚至是纬度/经度坐标。我看到你刚刚提供了一个看起来非常有前途的解决方案。非常感谢,@spickermann!我会点赞的。 - Chad Taylor
3个回答

10

我会在每个小时的开头运行同样的工作。您可能希望使用cron每小时运行该作业,或查看此列表以了解如何在Sidekiq中创建定期作业

作业中的第一步是找出当前时间为上午8点的所有时区:

8am_time_zones = ActiveSupport::TimeZone.all
                                        .select { |tz| tz.now.hour == 8 }
                                        .map { |tz| tz.tzinfo.name }
#=> ["America/Los_Angeles", "America/Tijuana", "America/Phoenix"]

使用此列表,您可以轻松地从数据库中加载生活在某个时区(假设您以此格式存储用户的时区)的用户,并向他们发送电子邮件:

User.where(time_zone: 8am_time_zones).find_each do |user|
  # email_newsletter(recipient: user)
end

0

创建这个任务并且每1小时1分钟执行一次

class ScheduleBasedOnTimeZoneJob < ApplicationJob
  queue_as :default

  def perform
    # only execute in the beggening if the day
    return unless now.to_i - now.beginning_of_day.to_i < 300

    time_zones = ["America/Los_Angeles", "America/Tijuana", "America/Phoenix"]
    time_zones.each do |time_zone|
      now = Time.now.in_time_zone(time_zone)

      # Schedule job at 08:00 AM based on the provided timezone
      schedule_at = now.change(hour: 8, min: 0)
      MyTzBasedJob.set(wait_until: schedule_at).perform_later(time_zone: time_zone)
    end
  end
end

0

Sidekiq没有针对“每天”这种用例的调度机制。您需要像whenever这样的cron调度程序。

假设您的服务器已配置为UTC,您只需创建您的计划:

# EST 8pm
every 1.day, :at => '1:00 am' do
  runner "MyModel.task_to_run_at_1_am_UTC"
end
# CST 8pm
every 1.day, :at => '2:00 am' do
  runner "MyOtherModel.task_to_run_at_2_am_UTC"
end

要在一行代码中完成:

every '* 6,7,8,9,10 1 * *' do
  runner "MyOtherModel.task_to_run_at_2_am_UTC"
end

看一下cron语法的构成方式。


我们的服务器设置为UTC时区,但是我们想在每个时区的特定时间(例如晚上8点)运行相同的重复任务(例如MyModel.task_1)。使用whenever gem是否可以实现这一点? - Chad Taylor
是的,您只需使用cron语法。 - Anthony
更新了我的答案@ChadTaylor - Anthony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接