Асинхронное программирование с волокнами

em-synchrony оборачивает цикл событий EM в волокне. Хотя намерение состоит в том, чтобы удалить уродство вложенных блоков обратного вызова, это добавило слой путаницы. Я хочу иметь асинхронное программирование, но при этом избегать ошибки "невозможно получить из корневого волокна", возникающей при смешивании вечерних программ и волокон.

Я создал этот код и хотел бы знать, правильное ли мое понимание его работы (я постарался максимально упростить его):

require "eventmachine"
require "em-synchrony"
require "em-synchrony/mysql2"
require "em-synchrony/activerecord"

EM.synchrony do
  User.all.each do |user|
    Fiber.new {
      ImapClient.new(user).check
    }.resume 
  end  
end


class ImapClient
  attr_accessor :user
  def initialize(user)
    @user = user
  end

  def imap_call
    client = EM::IMAP.new('imap.gmail.com',993,true)
    f = Fiber.current

    client.connect.bind! do
          client.login(@user.email,@user.password)
    end.bind! do
          client.select('INBOX')
    end.bind! do
          client.search(['1:20'])
    end.bind! do |ids|
          client.fetch(ids, "(UID ENVELOPE BODY[TEXT])")
    end.callback do |msgs|
          f.resume(msgs)
    end.errback do |error|
          puts "Connecting or logging in failed: #{error}"
    end

    return Fiber.yield
  end

  def check
    msgs = imap_call
    msgs.each do |msg|
      @user.email_messages.create! {body: msg.attr['BODY[TEXT]'], uid: msg.attr['UID']}
    end
  end
end

1) EM.synchrony оборачивает цикл событий EM (блок кода) в волокне.

2) Делаем асинхронный запрос к базе данных. Предположительно, пока этот запрос выполняется, синхронизация передает управление циклу событий EM, используя Fiber.yield за кулисами.

3) Мы создаем новое волокно для каждой записи пользователя. вызов возобновления выполняет блок кода в новом экземпляре волокна.

4) Выполняем асинхронный вызов IMAP. В ожидании обратного вызова мы выдаем Fiber (который затем позволяет нам проверять электронную почту другого пользователя, используя новое волокно).

5) Когда вызывается обратный вызов, старое волокно возобновляется, и мы проверяем его сообщения.

6) Затем новое волокно продолжается, и это продолжается и продолжается для каждой пользовательской записи.

Это правильно? Я хочу убедиться, что в этом коде нет блокировки.

0 ответов

Другие вопросы по тегам