mirror of
https://github.com/chatmail/core.git
synced 2026-04-06 07:32:12 +03:00
107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
|
|
import threading
|
|
import time
|
|
|
|
from contextlib import contextmanager
|
|
|
|
from .capi import lib
|
|
|
|
|
|
class IOThreads:
|
|
def __init__(self, account):
|
|
self.account = account
|
|
self._dc_context = account._dc_context
|
|
self._thread_quitflag = False
|
|
self._name2thread = {}
|
|
|
|
def is_started(self):
|
|
return len(self._name2thread) > 0
|
|
|
|
def start(self, callback_thread):
|
|
assert not self.is_started()
|
|
self._start_one_thread("inbox", self.imap_thread_run)
|
|
self._start_one_thread("smtp", self.smtp_thread_run)
|
|
|
|
if callback_thread:
|
|
self._start_one_thread("cb", self.cb_thread_run)
|
|
|
|
if int(self.account.get_config("mvbox_watch")):
|
|
self._start_one_thread("mvbox", self.mvbox_thread_run)
|
|
|
|
if int(self.account.get_config("sentbox_watch")):
|
|
self._start_one_thread("sentbox", self.sentbox_thread_run)
|
|
|
|
def _start_one_thread(self, name, func):
|
|
self._name2thread[name] = t = threading.Thread(target=func, name=name)
|
|
t.setDaemon(1)
|
|
t.start()
|
|
|
|
@contextmanager
|
|
def log_execution(self, message):
|
|
self.account.ac_log_line(message + " START")
|
|
yield
|
|
self.account.ac_log_line(message + " FINISHED")
|
|
|
|
def stop(self, wait=False):
|
|
self._thread_quitflag = True
|
|
|
|
# Workaround for a race condition. Make sure that thread is
|
|
# not in between checking for quitflag and entering idle.
|
|
time.sleep(0.5)
|
|
|
|
lib.dc_interrupt_imap_idle(self._dc_context)
|
|
lib.dc_interrupt_smtp_idle(self._dc_context)
|
|
if "mvbox" in self._name2thread:
|
|
lib.dc_interrupt_mvbox_idle(self._dc_context)
|
|
if "sentbox" in self._name2thread:
|
|
lib.dc_interrupt_sentbox_idle(self._dc_context)
|
|
if wait:
|
|
for name, thread in self._name2thread.items():
|
|
if thread != threading.currentThread():
|
|
thread.join()
|
|
|
|
def cb_thread_run(self):
|
|
with self.log_execution("CALLBACK THREAD START"):
|
|
it = self.account.iter_events()
|
|
while not self._thread_quitflag:
|
|
try:
|
|
ev = next(it)
|
|
except StopIteration:
|
|
break
|
|
self.account.ac_log_line("calling hook name={} kwargs={}".format(ev.name, ev.kwargs))
|
|
ev.call_hook()
|
|
|
|
def imap_thread_run(self):
|
|
with self.log_execution("INBOX THREAD START"):
|
|
while not self._thread_quitflag:
|
|
lib.dc_perform_imap_jobs(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_imap_fetch(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_imap_idle(self._dc_context)
|
|
|
|
def mvbox_thread_run(self):
|
|
with self.log_execution("MVBOX THREAD"):
|
|
while not self._thread_quitflag:
|
|
lib.dc_perform_mvbox_jobs(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_mvbox_fetch(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_mvbox_idle(self._dc_context)
|
|
|
|
def sentbox_thread_run(self):
|
|
with self.log_execution("SENTBOX THREAD"):
|
|
while not self._thread_quitflag:
|
|
lib.dc_perform_sentbox_jobs(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_sentbox_fetch(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_sentbox_idle(self._dc_context)
|
|
|
|
def smtp_thread_run(self):
|
|
with self.log_execution("SMTP THREAD"):
|
|
while not self._thread_quitflag:
|
|
lib.dc_perform_smtp_jobs(self._dc_context)
|
|
if not self._thread_quitflag:
|
|
lib.dc_perform_smtp_idle(self._dc_context)
|