Ruby IMAP IDLE 并发 - 如何解决?
我正在尝试构建一个(目前是私有的)Web 应用程序,该应用程序将利用 IMAP IDLE 连接在人们到达时显示电子邮件。
我很难弄清楚如何将其组合在一起 - 以及它如何与我的 Heroku RoR 服务器结合在一起。
我已经编写了一个用于连接到 IMAP 服务器并闲置的基本脚本,看起来像这样(简化):
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
这将建立一个到 IMAP 服务器的连接并开始闲置。正如你所看到的,这是循环阻塞的。
我希望我的用户有多个 IMAP 连接同时处于空闲状态。最初,我只是想将它们每个都放在一个线程中,如下所示:
Thread.new do
start_imap_idling(server, port, usessl, username, password)
end
我对线程还不是那么敏锐,但是使用这个解决方案,我仍然需要阻塞我的主线程来等待线程?因此,如果我这样做:
User.each do |user|
Thread.new do
start_imap_idling(server, port, usessl, username, password)
end
end
loop do
# Wait
end
那会起作用,但如果没有底部的循环来允许线程运行,就不行了?
我的问题是如何最好地将其与 Heroku 上的 Ruby On Rails 应用程序融合在一起?我不能用最后一个循环阻塞线程 - 那么我该如何运行它呢?另一个服务器?一个dyno more - 也许是一个工人?我一直在阅读一些有关事件机器的内容 - 这可以解决我的问题吗?如果可以,我应该如何写这个?
另一件事是,我希望能够添加新的 imap 客户端并动态删除当前的客户端。看起来怎么样?也许需要排队?
非常感谢任何帮助和评论!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不熟悉 RoR、Event Machine 等的细节——但看起来你想设置一个生产者/消费者。
生产者是监听 IMAP 服务器更改的线程。当它收到更改时,会将它们写入队列。您似乎想要设置多个生成器,每个 IMAP 连接一个。
您的消费者是一个在从队列读取时阻塞的线程。当有东西进入队列时,它会解除阻塞并处理该事件。
然后你的主线程就可以自由地做任何你想做的事情。听起来您希望主线程执行诸如添加新的 IMAP 客户端(即生产者)和动态删除当前客户端之类的操作。
至于你在哪里运行这些东西:你可以在一个可执行文件中运行消费者和生产者,在同一台机器上的单独可执行文件中运行,或者在不同的机器上运行......这一切都取决于你的情况。
华泰
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