Асинхронные вызовы методов с Ruby, как с Ajax

#ruby #asynchronous #io #xmpp #blocking

#ruby #асинхронный #io #xmpp #блокировка

Вопрос:

Я работаю с XMPP, и у меня есть обратный вызов сообщения, который активируется в случае отправки каждого сообщения. Моя цель — отправить данные, поступающие с сообщением, в API в рамках обратного вызова и на основе ответа отправить что-то обратно, используя XMPP-клиент.

  1. Сообщение пользовательского типа (клиент чата браузера)
  2. Сообщение поступает на сервер через XMPP
  3. Сообщение отправляется в API
  4. Получен ответ
  5. Ответ отправляется обратно клиенту чата.

Мой код для этого следующий

 admin_muc_client.activate_message_callbacks do |m|            
  sender    = m.from.resource
  room_slug = m.from.node
  message   = m.body                  

  r = HTTParty.get('http://example.com/api/v1/query?msg=message')
  Rails.logger.debug(r.inspect)
  admin_muc_client.send_message("Message #{r.body}") if m.from.resource != 'admin'
end
  

Меня беспокоит то, что, поскольку обратный вызов выполняется, а запрос к API будет блокирующим вызовом, это может стать узким местом для всего приложения.
Я бы предпочел использовать что-то вроде AJAX для Javascript, который запускал бы запрос и, когда ответ доступен, отправлял данные. Как я мог бы реализовать это в Ruby?

Я посмотрел на delayed_job и backgrounddrb, которые выглядят как инструменты для запуска и забывания операций. Мне нужно что-то, что активирует обратный вызов асинхронным образом с ответом.

Я был бы действительно очень признателен за некоторую помощь в том, как добиться асинхронного поведения, которое я хочу. Я также знаком с очередями сообщений, такими как RabbitMQ, которые, как я чувствую, были бы дополнением к значительной сложности.

Ответ №1:

Вы смотрели на girl_friday? Из вики —

girl_friday — это библиотека Ruby для выполнения асинхронных задач. Часто вы не хотите блокировать веб-ответ, выполняя какую-либо задачу, например, отправляя электронное письмо, поэтому вы можете просто использовать этот gem для выполнения его в фоновом режиме. Это работает с любым приложением Ruby, включая приложения Rails 3.

Почему бы не использовать любое из миллиардов других асинхронных решений (Resque, dj и т.д.)? Поскольку girl_friday проще и эффективнее, чем эти решения: girl_friday запускается в вашем процессе Rails и использует шаблон actor для безопасного параллелизма. Поскольку он выполняется в том же процессе, вам не нужно отслеживать отдельный набор процессов, развертывать отдельную кодовую базу, тратить сотни дополнительных МБ ОЗУ на эти процессы и т.д. Смотрите мое введение к Actors в Ruby для более подробной информации.

Вам действительно нужно написать потокобезопасный код. Это не сложно сделать: шаблон actor означает, что вы получаете сообщение и обрабатываете это сообщение. Нет общих данных, которые требуют блокировок и могут привести к взаимоблокировке в коде вашего приложения. Поскольку girl_friday использует потоки под прикрытием, вам необходимо убедиться, что ваша среда Ruby может эффективно выполнять потоки. JRuby, Rubinius 1.2 и Ruby 1.9.2 должно быть достаточно для большинства приложений. Я не поддерживаю Ruby 1.8 из-за его плохой поддержки потоков.

Я думаю, это то, что вы ищете.

Комментарии:

1. Awesome даст этому шанс. Может быть, это оно.

2. Я нахожу, что это работает в консоли, но не добавляет задачу в очередь при запуске в приложении в режиме разработки. Кстати, я запускаю passenger и apache в режиме разработки.