fixed race condition, added systemctl integration
This commit is contained in:
@@ -10,8 +10,9 @@ from .config import ImapConfig
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
IDLE_TIMEOUT = 300 # 5 minutes, per RFC 2177
|
||||
MAX_BACKOFF = 300 # 5 minutes max backoff
|
||||
IDLE_TIMEOUT = 300 # 5 minutes total IDLE before re-idle (RFC 2177)
|
||||
IDLE_POLL = 30 # check shutdown every 30 seconds within an IDLE
|
||||
MAX_BACKOFF = 300 # 5 minutes max backoff
|
||||
|
||||
|
||||
def run_idle_loop(
|
||||
@@ -60,23 +61,31 @@ def _idle_session(
|
||||
while not (shutdown_event and shutdown_event.is_set()):
|
||||
client.idle()
|
||||
try:
|
||||
responses = client.idle_check(timeout=IDLE_TIMEOUT)
|
||||
# Poll in short intervals so we can check shutdown_event
|
||||
# between iterations, rather than blocking for the full
|
||||
# IDLE_TIMEOUT (which causes a hang on Ctrl-C).
|
||||
responses = []
|
||||
deadline = time.monotonic() + IDLE_TIMEOUT
|
||||
while time.monotonic() < deadline:
|
||||
if shutdown_event and shutdown_event.is_set():
|
||||
break
|
||||
chunk = client.idle_check(timeout=IDLE_POLL)
|
||||
if chunk:
|
||||
responses.extend(chunk)
|
||||
break # got activity, exit IDLE to process
|
||||
finally:
|
||||
client.idle_done()
|
||||
done_result = client.idle_done()
|
||||
if done_result and done_result[0]:
|
||||
responses.extend(done_result[0])
|
||||
|
||||
if shutdown_event and shutdown_event.is_set():
|
||||
break
|
||||
|
||||
# Check if any EXISTS response indicates new mail
|
||||
has_new = any(
|
||||
isinstance(resp, tuple) and len(resp) >= 2 and resp[1] == b"EXISTS"
|
||||
for resp in responses
|
||||
)
|
||||
|
||||
if not has_new:
|
||||
continue
|
||||
|
||||
# Fetch new messages since last_uid
|
||||
# Always search for new UIDs, not just when we see EXISTS.
|
||||
# A message can arrive between idle_done() and the next idle()
|
||||
# call — the server already sent EXISTS while we weren't
|
||||
# listening, so we'd never see it. The UID SEARCH is cheap
|
||||
# and eliminates this race condition entirely.
|
||||
new_uids = _fetch_new_uids(client, last_uid)
|
||||
if not new_uids:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user