用光纤进行异步编程

时间:2016-09-23 23:03:07

标签: ruby asynchronous eventmachine fibers

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)我们进行异步数据库查询。据推测,在执行此查询时,synchrony会在后台使用Fiber.yield控制EM事件循环。

3)我们为每个用户记录创建一个新的光纤。 resume调用执行新光纤实例中的代码块。

4)我们执行异步IMAP调用。在等待回调时,我们产生光纤(然后允许我们使用新光纤检查另一个用户的电子邮件)。

5)当调用回调时,恢复旧光纤并检查其消息。

6)然后继续使用较新的光纤,并继续为每个用户记录继续。

这是对的吗?我想确保此代码中没有阻止。

0 个答案:

没有答案