Множественные асинхронные обратные вызовы из EventMachine — есть ли лучший способ справиться с этим?

#ruby #event-handling

#ruby #обработка событий

Вопрос:

Я использую библиотеку EventMachine от Ruby для асинхронного доступа к внешним API RESTful с сервера Ruby, который я пишу. Один из методов, которые я делаю доступными через мой сервер, требует, чтобы был доступен доступ к нескольким внешним API и агрегированные ответы, прежде чем возвращать ответ клиенту, обращающемуся к моему серверу. Вот как я это делаю сейчас…

 def aggregate
  responses = Array.new
  done      = 0

  # clients are EM::Deferrable objects...
  clients.each do |client|
    client.callback do |response|
      responses << response
      done  = 1
    end

    client.errback do |response|
      done  = 1
    end
  end

  until done == clients.length
    sleep 1
  end

  return responses
end
  

Есть ли лучшие способы справиться с ситуацией такого типа? Возможно ли, что класс EM::Completion, поставляемый в версии 1.0.0 EventMachine, обеспечит подключение, которое лучше поддерживает такой вариант использования?

Я уверен, что эта проблема возникала раньше (хотя я не смог найти аналогичный вопрос в StackOverflow), поэтому мне любопытно посмотреть, как другие подошли к проблеме.

Ответ №1:

Прежде всего, использование sleep полностью противоречит назначению EventMachine. Этим вы блокируете цикл событий. Мне нужна большая картина для предложения о том, как сделать это лучше, но ваш код должен привыкнуть к тому факту, что метод возвращается до выполнения всех запросов. В качестве альтернативы посмотрите на em-synchrony, как выполнять событийное программирование в процедурном стиле с использованием волокон Ruby (прозрачно для вас).

Один из способов уменьшить количество склеиваемого кода для параллельного выполнения нескольких запросов — это использовать что-то вроде мультиинтерфейса em-http-requests, который работает как с обратным вызовом EventMachine, так и с em-синхронией.

EM::Завершение, с другой стороны, скорее отсрочено, оно точно не поможет вам в этом случае.

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

1. Спасибо roidrage, класс MultiRequest для em-http-request — это именно тот тип, который я искал.