периодическая задача рельсов

У меня есть приложение ruby on rails, в котором я пытаюсь найти способ запускать код каждые несколько секунд.

Я нашел много информации и идей с использованием cron или cron-подобных реализаций, но они точны вплоть до минуты и/или требуют внешних инструментов. Я хочу отбросить задачу каждые 15 секунд или около того, и я хочу, чтобы она была полностью автономной внутри приложения (если приложение останавливается, задачи останавливаются и внешняя настройка).

Это используется для генерации данных кэша. Каждые несколько секунд задача будет собирать некоторые данные, а затем хранить их в кеше, который будет использоваться всеми клиентскими запросами. Задача довольно медленная, поэтому ее нужно запускать в фоновом режиме, а не блокировать запросы клиентов.

Я новичок в рубине, но имею сильный фон perl, и так, как я бы решил это, было бы создание таймера и обработчика интервалов, который вилки, запускает код, а затем выходит, когда это будет сделано.
Возможно, было бы даже лучше всего имитировать запрос клиента и иметь собственную вилку контроллера rails. Таким образом, я мог бы запустить задачу, нажав на URI для нее (хотя, поскольку задача будет выполняться каждые несколько секунд, я сомневаюсь, что мне когда-нибудь понадобится, но может иметь будущее использование). Хотя было бы тривиально просто заставить контроллер вызывать любой метод, который вызывается планировщиком периодических задач (один раз он есть).

Ответ 1

Вообще говоря, нет встроенного способа, которым я знаю, чтобы создать периодическую задачу в приложении. Rails построен на стойке, и он ожидает получить HTTP-запросы, что-то сделать, а затем вернуться. Поэтому вам просто нужно самостоятельно управлять периодической задачей.

Я думаю, учитывая частоту, что вам нужно для выполнения задачи, достойным решением может быть просто написать себе простую задачу рейка, которая навсегда зацикливается и выпустить ее одновременно с запуском приложения, используя что-то вроде Формана. Foreman часто используется так, чтобы управлять запуском/выключением фоновых рабочих вместе со своими приложениями. При производстве вы можете использовать что-то еще для управления процессами, например Monit.

Ответ 2

Я предлагаю всякий раз, когда gem https://github.com/javan/whenever

Он позволяет указать расписание, например:

every 15.minutes do
  MyClass.do_stuff
end

Там нет планирования работы cron или обезьяны с внешними службами.

Ответ 3

Вы можете либо написать свой собственный метод, что-то вроде

class MyWorker
  def self.work
    #do you work
    sleep 15
  end
end

запустите его с помощью rails runner MyWorker.work Будет создан отдельный процесс, работающий в фоновом режиме

Или вы можете использовать что-то вроде Resque, но это другой подход. Он работает так: что-то добавляет задачу в очередь, между тем рабочий получает всю работу, находящуюся в очереди, и пытается ее завершить.

Это зависит от вашей собственной потребности.

Ответ 4

Использовать что-то вроде отложенной работы и требовать ее так часто?

Ответ 5

Используйте тонкий или другой сервер, который использует eventmachine, а затем используйте таймеры, которые являются частью eventmachine. Пример: в config/application.rb

EM.add_periodic_timer(2) do
  do_this_every_2_sec
end  

Ответ 6

Я знаю, что это старый вопрос. Но, возможно, для кого-то этот ответ может быть полезным. Существует драгоценный камень, называемый crono.

Crono - это временный фоновой планировщик планировщика заданий (как и Cron) для Ruby on Rails.

Кроно - чистый рубин. Он не использует Unix Cron и другие зависящие от платформы вещи. Таким образом, вы можете использовать его на всех платформах, поддерживаемых Ruby. Он сохраняет состояния работы вашей базы данных с помощью Active Record. У вас есть полный контроль над работой, выполняющей процесс. Это Ruby, чтобы вы могли понять и изменить его в соответствии с вашими потребностями.

Замечательная вещь с crono заключается в том, что ее код сам объясняется. Чтобы периодически выполнять задание, вы можете просто сделать:

Crono.perform(YourJob).every 2.days

Возможно, вы также можете сделать:

Crono.perform(YourJob).every 30.seconds

В любом случае, вы действительно можете многое сделать. Другим примером может быть:

Crono.perform(TestJob).every 1.week, on: :monday, at: "15:30"

Я предлагаю эту драгоценность вместо того, чтобы когда-либо использовать таблицу Unix Cron, которая не всегда доступна.