Время ожидания Ruby on Rails. Как мне развить процесс? - PullRequest
1 голос
/ 02 февраля 2011

У меня есть страница с длинным списком товаров. У каждого есть флажок рядом с ним. Есть функция проверки всех jQuery, но когда я отправляю их все сразу, запрос прерывается, потому что он выполняет несколько запросов и вставляет несколько записей в базу данных MySQL для каждого элемента. Если бы не время ожидания, это заняло бы около 20 минут. Вместо этого я просто отправляю как 30 за раз.

Я хочу иметь возможность просто проверить все и отправить, а затем просто продолжать выполнять другую работу. Мой коллега (1) сказал, что я должен написать грабли. Я сделал это, но в итоге я продублировал код, и я предпочитаю пользовательский интерфейс, потому что, если я хочу отменить проверку? Задание с граблями просто отправляет их всех.

Другой сотрудник (2) рекомендовал использовать вилку. Он сказал, что это породит новый процесс, который будет запущен на сервере, но позволит серверу ответить до того, как это будет сделано. Затем, поскольку элемент исчез после отправки, я мог бы просто обновить страницу, чтобы проверить, все ли выполнено.

Я попробовал это на своем локальном компьютере, однако, все еще кажется, что Rails ожидает завершения процесса, прежде чем он ответит на запрос POST, отправленный HTML-формой. Код, который я использовал, выглядит следующим образом:

def bulk_apply
  pid = fork do
    params[:ids].each do |id|
      Item.find(id).apply # takes a LONG time, esp. x 100
    end
  end
  Process.detach(pid) # reap child process automatically; don't leave running
  flash[:notice] = "Applying... Please wait... Then, refresh page. Only submit once. PID: #{pid}"
  redirect_to :back
end

Coworker 1 сказал, что обычно вы не хотите форкать Rails, потому что форк создает дочерний процесс, который по сути является копией процесса Rails. Он сказал, что если вы хотите сделать это через веб-интерфейс, используйте BackgroundJob (Bj) (потому что мы уже используем это в нашем приложении Rails). Итак, я сейчас изучаю BackgroundJob, но что вы порекомендуете?

Ответы [ 3 ]

2 голосов
/ 07 февраля 2011

Вы должны проверить IronWorker .Было бы очень легко делать то, что вы хотите, и неважно, сколько времени это займет.

В своем действии вы просто создадите экземпляр работника, у которого есть код, выполняющий все ваши запросы к базе данных.Пример работника:

Item.find(id).apply # takes a LONG time, esp. x 100

А вот как вы ставите в очередь эти задания для параллельного выполнения:

client = IronWorkerNG::Client.new
ids.each do |id|
  client.tasks.create("MyWorker", "id"=>id)
end

Это все, что вам нужно сделать, и IronWorker позаботится оотдых.

2 голосов
/ 02 февраля 2011

У меня был хороший успех при использовании фоновой работы. Если вам нужны рельсы, вы будете использовать скрипт / бегун, который все еще запускает новый процесс с рельсами. Хорошо, что Backround Job гарантирует, что за один раз не будет запущено больше одного.

Вы также можете напрямую использовать программу запуска сценариев или даже запускать грабли в фоновом режиме, например:

system " RAILS_ENV=#{RAILS_ENV}   ruby  #{RAILS_ROOT}/script/runner   'CompositeGrid.calculate_values(#{self.id})'  & " unless RAILS_ENV == "test"

Амперсанд говорит ему начать новый процесс. Будьте осторожны, потому что вы, вероятно, не хотите, чтобы они работали одновременно. Я бы определенно воспользовался фоновой работой, если она уже доступна.

0 голосов
/ 15 ноября 2013

Попробуйте delayed_job драгоценный камень. Это фоновое задание на основе базы данных. Мы использовали его на веб-сайте электронной коммерции. Например, отправка пользователю электронного письма с подтверждением заказа является идеальным кандидатом на отложенную работу.

Кроме того, вы можете попробовать многопоточность, которая поддерживается Ruby. Это может заставить вещи работать быстрее. Формирование всего процесса обходится дорого из-за использования памяти.

...