Ticket #9177: 0001-Use-IMAP-IDLE-to-reduce-polling.patch

File 0001-Use-IMAP-IDLE-to-reduce-polling.patch, 4.4 KB (added by arlolra, 6 years ago)
  • facilitator/facilitator-email-poller

    From 67156fab0a6b8abb343588135f1d38657f4e2c49 Mon Sep 17 00:00:00 2001
    From: Arlo Breault <arlolra@gmail.com>
    Date: Wed, 3 Jul 2013 13:56:50 -0700
    Subject: [PATCH] Use IMAP IDLE to reduce polling
    
    See #9177
    ---
     facilitator/facilitator-email-poller | 79 +++++++++++++++++++++---------------
     1 file changed, 47 insertions(+), 32 deletions(-)
    
    diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller
    index f520033..a04c963 100755
    a b def imap_get_uid(imap, index): 
    289289# delete it from there. Messages in Trash are deleted automatically after 30
    290290# days, but we do it immediately.
    291291def imap_loop(imap):
     292    # Copy all messages to Trash, and work on them from there. This is a
     293    # failsafe so that messages will eventually be deleted if we are not
     294    # able to retrieve them. This act of copying also deletes from All Mail.
     295    typ, data = imap.select("[Gmail]/All Mail")
     296    check_imap_return(typ, data)
     297    imap.copy("1:*", "[Gmail]/Trash")
     298
     299    typ, data = imap.select("[Gmail]/Trash")
     300    check_imap_return(typ, data)
     301    exists = int(data[0])
     302    if exists > 0:
     303        while True:
     304            # Grab message 1 on each iteration; remaining messages shift down so
     305            # the next message we process is also message 1.
     306            uid = imap_get_uid(imap, "1")
     307            if uid is None:
     308                break
     309
     310            typ, data = imap.uid("FETCH", uid, "(BODY[])")
     311            check_imap_return(typ, data)
     312            msg_text = data[0][1]
     313            typ, data = imap.uid("STORE", uid, "+FLAGS", "\\Deleted")
     314            check_imap_return(typ, data)
     315            typ, data = imap.expunge()
     316            check_imap_return(typ, data)
     317
     318            try:
     319                msg = email.message_from_string(msg_text)
     320                if message_ok(msg):
     321                    handle_message(msg)
     322            except Exception, e:
     323                log("Error processing message, deleting anyway: %s" % str(e))
     324
     325def imap_idle(imap):
    292326    while True:
    293         # Copy all messages to Trash, and work on them from there. This is a
    294         # failsafe so that messages will eventually be deleted if we are not
    295         # able to retrieve them. This act of copying also deletes from All Mail.
    296327        typ, data = imap.select("[Gmail]/All Mail")
    297328        check_imap_return(typ, data)
    298         imap.copy("1:*", "[Gmail]/Trash")
    299 
    300         typ, data = imap.select("[Gmail]/Trash")
    301         check_imap_return(typ, data)
    302         exists = int(data[0])
    303         if exists > 0:
    304             while True:
    305                 # Grab message 1 on each iteration; remaining messages shift down so
    306                 # the next message we process is also message 1.
    307                 uid = imap_get_uid(imap, "1")
    308                 if uid is None:
    309                     break
    310 
    311                 typ, data = imap.uid("FETCH", uid, "(BODY[])")
    312                 check_imap_return(typ, data)
    313                 msg_text = data[0][1]
    314                 typ, data = imap.uid("STORE", uid, "+FLAGS", "\\Deleted")
    315                 check_imap_return(typ, data)
    316                 typ, data = imap.expunge()
    317                 check_imap_return(typ, data)
    318 
    319                 try:
    320                     msg = email.message_from_string(msg_text)
    321                     if message_ok(msg):
    322                         handle_message(msg)
    323                 except Exception, e:
    324                     log("Error processing message, deleting anyway: %s" % str(e))
    325 
    326         time.sleep(POLL_INTERVAL)
     329        tag = imap._new_tag()
     330        imap.send("%s IDLE\r\n" % tag)
     331        resp = imap.readline()
     332        if resp != '+ idling\r\n':
     333            raise Exception("IDLE not handled? : %s" % resp)
     334        while True:
     335            resp = imap.readline()
     336            if re.search(r'EXISTS', resp):
     337                imap.send("DONE\r\n")
     338                imap_loop(imap)
     339                break
    327340
    328341def imap_login():
    329342    """Make an IMAP connection, check the certificate and public key, and log in."""
    while True: 
    376389    try:
    377390        imap = imap_login()
    378391        imap_loop(imap)
     392        imap_idle(imap)
    379393    except (imaplib.IMAP4.abort, ssl.SSLError, socket.error), e:
    380394        # Try again after a disconnection.
    381395        log(u"lost server connection: %s" % str(e))
    382396    except KeyboardInterrupt:
     397        imap.send("DONE\r\n")
    383398        break
    384399
    385400    try: