{"action":"opened","issue":{"url":"https://api.github.com/repos/gmailgem/gmail/issues/157","labels_url":"https://api.github.com/repos/gmailgem/gmail/issues/157/labels{/name}","comments_url":"https://api.github.com/repos/gmailgem/gmail/issues/157/comments","events_url":"https://api.github.com/repos/gmailgem/gmail/issues/157/events","html_url":"https://github.com/gmailgem/gmail/issues/157","id":54896582,"number":157,"title":"IDLE support","user":{"login":"jcarbo","id":847027,"avatar_url":"https://avatars.githubusercontent.com/u/847027?v=3","gravatar_id":"","url":"https://api.github.com/users/jcarbo","html_url":"https://github.com/jcarbo","followers_url":"https://api.github.com/users/jcarbo/followers","following_url":"https://api.github.com/users/jcarbo/following{/other_user}","gists_url":"https://api.github.com/users/jcarbo/gists{/gist_id}","starred_url":"https://api.github.com/users/jcarbo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcarbo/subscriptions","organizations_url":"https://api.github.com/users/jcarbo/orgs","repos_url":"https://api.github.com/users/jcarbo/repos","events_url":"https://api.github.com/users/jcarbo/events{/privacy}","received_events_url":"https://api.github.com/users/jcarbo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-01-20T15:31:28Z","updated_at":"2015-01-20T15:31:28Z","closed_at":null,"body":"This is one of the more exciting features for me. I was looking into the PR that's currently open for it #136 and it got me thinking *how should this actually work?*\r\n\r\nI was pretty unaware how IDLE works, but [this stack overflow answer](http://stackoverflow.com/a/21345164) explains the principles pretty succinctly. Also checkout [the source code for `idle` and `idle_done`](https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L918-L959) \r\n\r\nBasically it opens a blocking connection that listens for events in the mailbox (which is pretty obvious), but less obvious is that you can't reuse that connection until you stop idling. Meaning that even within the handler for a new message you cannot do something like a `uid_fetch` (at least not using that came connection). Also IDLE connections will close down after 30 minutes so if you want to have them always running, the best practice is to set a timeout for 29 minutes and close/reopen the IDLE connection.\r\n\r\nThere's some complexity here so my question is how much of this should we abstract away in this gem vs leave for the user to handle?\r\n\r\nSome ideas (with pseudocode):\r\n```ruby\r\n# blocks until it receives the next message then shuts down the connection and\r\n# either calls the block if one was given or returns the response\r\ndef idle(mailbox, &block)\r\n  imap.idle do |response|\r\n    # Message received!\r\n    imap.idle_stop\r\n\r\n    if block_given?\r\n      yield response\r\n    else\r\n      response\r\n    end\r\n  end\r\nend\r\n\r\n# same as the above but loops forever\r\ndef idle(mailbox, &block)\r\n  # need a block here because this method doesn't return\r\n  raise LocalJumpError, \"no block given\" unless block\r\n  loop do\r\n    imap.idle do |response|\r\n      # Message received!\r\n      imap.idle_stop\r\n\r\n      yield response\r\n    end\r\n  end\r\nend\r\n\r\n# same as the above but give the user an option to loop forever or not\r\ndef idle(mailbox, options = {}, &block)\r\n  # need a block here because this method doesn't return\r\n  raise LocalJumpError, \"no block given\" unless block\r\n  loop do\r\n    imap.idle do |response|\r\n      # Message received!\r\n      imap.idle_stop\r\n\r\n      yield response\r\n    end\r\n\r\n    break unless options[:keepalive]\r\n  end\r\nend\r\n```\r\n\r\nAdditional thoughts:\r\n- The `yield response` could potentially be wrapped inside a separate IMAP connection so that you can interact with message as you'd expect and we wouldn't have to call `idle_stop`.\r\n- These can be thrown inside threads so they're non-blocking for the user. Or we can use EventMachine (in fact, someone is already doing that for this: https://github.com/ConradIrwin/em-imap).\r\n\r\n@gmailgem/owners I'd love to get your thoughts here :thought_balloon: "}}