如何在轨道中每隔几秒钟运行一次动作10分钟?

时间:2021-11-21 19:14:47

I am trying to build quizup like app and want to send broadcast every 10 second with a random question for 2 minutes. How do I do that using rails ? I am using action cable for sending broadcast. I can use rufus-scheduler for running an action every few seconds but I am not sure if it make sense to use it for my use case .

我正在尝试像app一样构建quizup,并希望每隔10秒发送一次随机问题播放2分钟。我如何使用rails做到这一点?我正在使用动作电缆发送广播。我可以使用rufus-scheduler每隔几秒运行一次动作,但我不确定将它用于我的用例是否有意义。

1 个解决方案

#1


1  

Simplest solution would be to fork a new thread:

最简单的解决方案是分叉一个新线程:

Thread.new do
  duration = 2.minutes
  interval = 10.seconds
  number_of_questions_left = duration.seconds / interval.seconds

  while(number_of_questions_left > 0) do
    ActionCable.server.broadcast(
      "some_broadcast_id", { random_question: 'How are you doing?' }
    )
    number_of_questions_left -= 1
    sleep(interval)
  end
end

Notes:

  • This is only a simple solution of which you are actually ending up more than 2.minutes of total run time, because each loop actually ends up sleeping very slightly more than 10 seconds. If this discrepancy is not important, then the solution above would be already sufficient.

    这只是一个简单的解决方案,实际上你的总运行时间超过2分钟,因为每个循环实际上最终睡眠时间超过10秒。如果这种差异并不重要,那么上述解决方案就足够了。

  • Also, this kind-of-scheduler only persists in memory, as opposed to a dedicated background worker like sidekiq. So, if the rails process gets terminated, then all currently running "looping" code will also be terminated as well, which you might intentionally want or not want.

    此外,这种调度程序仅存在于内存中,而不是像sidekiq这样的专用后台工作程序。因此,如果rails进程被终止,那么所有当前正在运行的“循环”代码也将被终止,这可能是您有意想要或不想要的。

If using rufus-scheduler:

number_of_questions_left = 12

scheduler = Rufus::Scheduler.new

# `first_in` is set so that first-time job runs immediately
scheduler.every '10s', first_in: 0.1 do |job|
  ActionCable.server.broadcast(
    "some_broadcast_id", { random_question: 'How are you doing?' }
  )
  number_of_questions_left -= 1
  job.unschedule if number_of_questions_left == 0
end

#1


1  

Simplest solution would be to fork a new thread:

最简单的解决方案是分叉一个新线程:

Thread.new do
  duration = 2.minutes
  interval = 10.seconds
  number_of_questions_left = duration.seconds / interval.seconds

  while(number_of_questions_left > 0) do
    ActionCable.server.broadcast(
      "some_broadcast_id", { random_question: 'How are you doing?' }
    )
    number_of_questions_left -= 1
    sleep(interval)
  end
end

Notes:

  • This is only a simple solution of which you are actually ending up more than 2.minutes of total run time, because each loop actually ends up sleeping very slightly more than 10 seconds. If this discrepancy is not important, then the solution above would be already sufficient.

    这只是一个简单的解决方案,实际上你的总运行时间超过2分钟,因为每个循环实际上最终睡眠时间超过10秒。如果这种差异并不重要,那么上述解决方案就足够了。

  • Also, this kind-of-scheduler only persists in memory, as opposed to a dedicated background worker like sidekiq. So, if the rails process gets terminated, then all currently running "looping" code will also be terminated as well, which you might intentionally want or not want.

    此外,这种调度程序仅存在于内存中,而不是像sidekiq这样的专用后台工作程序。因此,如果rails进程被终止,那么所有当前正在运行的“循环”代码也将被终止,这可能是您有意想要或不想要的。

If using rufus-scheduler:

number_of_questions_left = 12

scheduler = Rufus::Scheduler.new

# `first_in` is set so that first-time job runs immediately
scheduler.every '10s', first_in: 0.1 do |job|
  ActionCable.server.broadcast(
    "some_broadcast_id", { random_question: 'How are you doing?' }
  )
  number_of_questions_left -= 1
  job.unschedule if number_of_questions_left == 0
end