Merge branch 'ss/cleanup-idle' into next
This commit is contained in:
commit
78a67ac73c
@ -458,9 +458,12 @@ class IMAPServer:
|
|||||||
|
|
||||||
class IdleThread(object):
|
class IdleThread(object):
|
||||||
def __init__(self, parent, folder=None):
|
def __init__(self, parent, folder=None):
|
||||||
|
"""If invoked without 'folder', perform a NOOP and wait for
|
||||||
|
self.stop() to be called. If invoked with folder, switch to IDLE
|
||||||
|
mode and synchronize once we have a new message"""
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.folder = folder
|
self.folder = folder
|
||||||
self.event = Event()
|
self.stop_sig = Event()
|
||||||
self.ui = getglobalui()
|
self.ui = getglobalui()
|
||||||
if folder is None:
|
if folder is None:
|
||||||
self.thread = Thread(target=self.noop)
|
self.thread = Thread(target=self.noop)
|
||||||
@ -472,7 +475,7 @@ class IdleThread(object):
|
|||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.event.set()
|
self.stop_sig.set()
|
||||||
|
|
||||||
def join(self):
|
def join(self):
|
||||||
self.thread.join()
|
self.thread.join()
|
||||||
@ -480,7 +483,7 @@ class IdleThread(object):
|
|||||||
def noop(self):
|
def noop(self):
|
||||||
imapobj = self.parent.acquireconnection()
|
imapobj = self.parent.acquireconnection()
|
||||||
imapobj.noop()
|
imapobj.noop()
|
||||||
self.event.wait()
|
self.stop_sig.wait()
|
||||||
self.parent.releaseconnection(imapobj)
|
self.parent.releaseconnection(imapobj)
|
||||||
|
|
||||||
def dosync(self):
|
def dosync(self):
|
||||||
@ -495,21 +498,22 @@ class IdleThread(object):
|
|||||||
ui.unregisterthread(currentThread())
|
ui.unregisterthread(currentThread())
|
||||||
|
|
||||||
def idle(self):
|
def idle(self):
|
||||||
while True:
|
"""Invoke IDLE mode until timeout or self.stop() is invoked"""
|
||||||
if self.event.isSet():
|
|
||||||
return
|
|
||||||
self.needsync = False
|
|
||||||
self.imapaborted = False
|
|
||||||
def callback(args):
|
def callback(args):
|
||||||
|
"""IDLE callback function invoked by imaplib2
|
||||||
|
|
||||||
|
This is invoked when a) The IMAP server tells us something
|
||||||
|
while in IDLE mode, b) we get an Exception (e.g. on dropped
|
||||||
|
connections, or c) the standard imaplib IDLE timeout of 29
|
||||||
|
minutes kicks in."""
|
||||||
result, cb_arg, exc_data = args
|
result, cb_arg, exc_data = args
|
||||||
if exc_data is None:
|
if exc_data is None and not self.stop_sig.isSet():
|
||||||
if not self.event.isSet():
|
# No Exception, and we are not supposed to stop:
|
||||||
self.needsync = True
|
self.needsync = True
|
||||||
self.event.set()
|
self.stop_sig.set() # continue to sync
|
||||||
else:
|
|
||||||
# We got an "abort" signal.
|
while not self.stop_sig.isSet():
|
||||||
self.imapaborted = True
|
self.needsync = False
|
||||||
self.stop()
|
|
||||||
|
|
||||||
success = False # successfully selected FOLDER?
|
success = False # successfully selected FOLDER?
|
||||||
while not success:
|
while not success:
|
||||||
@ -520,7 +524,7 @@ class IdleThread(object):
|
|||||||
if e.severity == OfflineImapError.ERROR.FOLDER_RETRY:
|
if e.severity == OfflineImapError.ERROR.FOLDER_RETRY:
|
||||||
# Connection closed, release connection and retry
|
# Connection closed, release connection and retry
|
||||||
self.ui.error(e, exc_info()[2])
|
self.ui.error(e, exc_info()[2])
|
||||||
self.parent.releaseconnection(imapobj)
|
self.parent.releaseconnection(imapobj, True)
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
else:
|
else:
|
||||||
@ -528,19 +532,22 @@ class IdleThread(object):
|
|||||||
if "IDLE" in imapobj.capabilities:
|
if "IDLE" in imapobj.capabilities:
|
||||||
imapobj.idle(callback=callback)
|
imapobj.idle(callback=callback)
|
||||||
else:
|
else:
|
||||||
self.ui.warn("IMAP IDLE not supported on connection to %s."
|
self.ui.warn("IMAP IDLE not supported on server '%s'."
|
||||||
"Falling back to old behavior: sleeping until next"
|
"Sleep until next refresh cycle." % imapobj.identifier)
|
||||||
"refresh cycle."
|
|
||||||
%(imapobj.identifier,))
|
|
||||||
imapobj.noop()
|
imapobj.noop()
|
||||||
self.event.wait()
|
self.stop_sig.wait() # self.stop() or IDLE callback are invoked
|
||||||
if self.event.isSet():
|
try:
|
||||||
# Can't NOOP on a bad connection.
|
# End IDLE mode with noop, imapobj can point to a dropped conn.
|
||||||
if not self.imapaborted:
|
|
||||||
imapobj.noop()
|
imapobj.noop()
|
||||||
# We don't do event.clear() so that we'll fall out
|
except imapobj.abort():
|
||||||
# of the loop next time around.
|
self.ui.warn('Attempting NOOP on dropped connection %s' % \
|
||||||
|
imapobj.identifier)
|
||||||
|
self.parent.releaseconnection(imapobj, True)
|
||||||
|
else:
|
||||||
self.parent.releaseconnection(imapobj)
|
self.parent.releaseconnection(imapobj)
|
||||||
|
|
||||||
if self.needsync:
|
if self.needsync:
|
||||||
self.event.clear()
|
# here not via self.stop, but because IDLE responded. Do
|
||||||
|
# another round and invoke actual syncing.
|
||||||
|
self.stop_sig.clear()
|
||||||
self.dosync()
|
self.dosync()
|
||||||
|
Loading…
Reference in New Issue
Block a user