периодическая задача рельсов
У меня есть приложение 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, которая не всегда доступна.