#ruby #asynchronous #io #xmpp #blocking
#ruby #асинхронный #io #xmpp #блокировка
Вопрос:
Я работаю с XMPP, и у меня есть обратный вызов сообщения, который активируется в случае отправки каждого сообщения. Моя цель — отправить данные, поступающие с сообщением, в API в рамках обратного вызова и на основе ответа отправить что-то обратно, используя XMPP-клиент.
- Сообщение пользовательского типа (клиент чата браузера)
- Сообщение поступает на сервер через XMPP
- Сообщение отправляется в API
- Получен ответ
- Ответ отправляется обратно клиенту чата.
Мой код для этого следующий
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 в режиме разработки.