Ruby IMAP IDLE concurrency - how to tackle?

蹲街弑〆低调 提交于 2019-12-20 17:34:09

问题


I'm trying to build a (private, for now) web application that will utilize IMAP IDLE connections to show peoples emails as they arrive.

I'm having a hard time figuring out how to hack this together - and how it would fit together with my Heroku RoR server.

I've written a basic script for connecting to an IMAP server and idling, looks something like this (simplified):

imap = Net::IMAP.new server, port, usessl
imap.login username, password
imap.select "INBOX"

imap.add_response_handler do |response|
  if resp.kind_of(Net::IMAP::UntaggedResponse) && resp.name == "EXISTS"
    # New mail recieved. Ping back and process.
  end
end

imap.idle
loop do
  sleep 10*60
  imap.renew_idle
end

This will make one connection to the IMAP server and start idling. As you see, this is blocking with the loop.

I would like to have multiple IMAP connections idling at the same time for my users. Initially, I just wanted to put each of them in a thread, like so:

Thread.new do
  start_imap_idling(server, port, usessl, username, password)
end

I'm not that sharp on threads yet, but with this solution I will still have to block my main thread to wait for the threads? So if I do something like:

User.each do |user|
  Thread.new do
    start_imap_idling(server, port, usessl, username, password)
  end
end

loop do
  # Wait
end

That would work, but not without the loop at the bottom to allow the threads to run?

My question is how I best melt this together with my Ruby On Rails application on Heroku? I can't be blocking the thread with that last loop - so how do I run this? Another server? A dyno more - perhaps a worker? I've been reading a bit about Event Machine - could this solve my problem, if so, how should I go about writing this?

Another thing is, that I would like to be able to add new imap clients and remove current ones on the fly. How might that look? Something with a queue perhaps?

Any help and comments are very much appreciated!


回答1:


I'm not familiar with the specifics of RoR, Event Machine, etc. -- but it seems like you'd want to set up a producer/consumer.

The producer is your thread that's listening for changes from the IMAP server. When it gets changes it writes them to a queue. It seems like you'd want to set up multiple producers, one for each IMAP connection.

Your consumer is a thread that blocks on read from the queue. When something enters the queue it unblocks and processes the event.

Your main thread would then be free to do whatever you want. It sounds like you'd want your main thread doing things like adding new IMAP clients (i.e., producers) and removing current ones on the fly.

As for where you'd run these things: You could run the consumers and producer in one executable, in separate executables on the same machine, or on different machines... all depending upon your circumstances.

HTH



来源:https://stackoverflow.com/questions/5604480/ruby-imap-idle-concurrency-how-to-tackle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!