mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
as discussed during camp and otherwise ... add dc_perform_{mvbox,sentbox}_jobs hooks which, however, for now have an empty implementation. They can already be called from UIs, though. Next step is refactoring imap-job handling to only execute jobs belonging to the respective imap folder.
This commit is contained in:
@@ -610,12 +610,8 @@ void dc_interrupt_imap_idle (dc_context_t* context);
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch new messages from the MVBOX, if any.
|
* Execute pending mvbox-jobs.
|
||||||
* The MVBOX is a folder on the account where chat messages are moved to.
|
* This function and dc_perform_mvbox_fetch() and dc_perform_mvbox_idle()
|
||||||
* The moving is done to not disturb shared accounts that are used by both,
|
|
||||||
* Delta Chat and a classical MUA.
|
|
||||||
*
|
|
||||||
* This function and dc_perform_mvbox_idle()
|
|
||||||
* must be called from the same thread, typically in a loop.
|
* must be called from the same thread, typically in a loop.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
@@ -623,6 +619,7 @@ void dc_interrupt_imap_idle (dc_context_t* context);
|
|||||||
* void* mvbox_thread_func(void* context)
|
* void* mvbox_thread_func(void* context)
|
||||||
* {
|
* {
|
||||||
* while (true) {
|
* while (true) {
|
||||||
|
* dc_perform_mvbox_jobs(context);
|
||||||
* dc_perform_mvbox_fetch(context);
|
* dc_perform_mvbox_fetch(context);
|
||||||
* dc_perform_mvbox_idle(context);
|
* dc_perform_mvbox_idle(context);
|
||||||
* }
|
* }
|
||||||
@@ -636,13 +633,26 @@ void dc_interrupt_imap_idle (dc_context_t* context);
|
|||||||
*
|
*
|
||||||
* // network becomes available again -
|
* // network becomes available again -
|
||||||
* // the interrupt causes dc_perform_mvbox_idle() in the thread above
|
* // the interrupt causes dc_perform_mvbox_idle() in the thread above
|
||||||
* // to return so that and messages are fetched.
|
* // to return so that jobs are executed and messages are fetched.
|
||||||
* dc_maybe_network(context);
|
* dc_maybe_network(context);
|
||||||
*
|
*
|
||||||
* @memberof dc_context_t
|
* @memberof dc_context_t
|
||||||
* @param context The context as created by dc_context_new().
|
* @param context The context as created by dc_context_new().
|
||||||
* @return None.
|
* @return None.
|
||||||
*/
|
*/
|
||||||
|
void dc_perform_mvbox_jobs (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch new messages from the MVBOX, if any.
|
||||||
|
* The MVBOX is a folder on the account where chat messages are moved to.
|
||||||
|
* The moving is done to not disturb shared accounts that are used by both,
|
||||||
|
* Delta Chat and a classical MUA.
|
||||||
|
*
|
||||||
|
* @memberof dc_context_t
|
||||||
|
* @param context The context as created by dc_context_new().
|
||||||
|
* @return None.
|
||||||
|
*/
|
||||||
void dc_perform_mvbox_fetch (dc_context_t* context);
|
void dc_perform_mvbox_fetch (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
@@ -679,6 +689,39 @@ void dc_perform_mvbox_idle (dc_context_t* context);
|
|||||||
*/
|
*/
|
||||||
void dc_interrupt_mvbox_idle (dc_context_t* context);
|
void dc_interrupt_mvbox_idle (dc_context_t* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute pending sentbox-jobs.
|
||||||
|
* This function and dc_perform_sentbox_fetch() and dc_perform_sentbox_idle()
|
||||||
|
* must be called from the same thread, typically in a loop.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* void* sentbox_thread_func(void* context)
|
||||||
|
* {
|
||||||
|
* while (true) {
|
||||||
|
* dc_perform_sentbox_jobs(context);
|
||||||
|
* dc_perform_sentbox_fetch(context);
|
||||||
|
* dc_perform_sentbox_idle(context);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // start sentbox-thread that runs forever
|
||||||
|
* pthread_t sentbox_thread;
|
||||||
|
* pthread_create(&sentbox_thread, NULL, sentbox_thread_func, context);
|
||||||
|
*
|
||||||
|
* ... program runs ...
|
||||||
|
*
|
||||||
|
* // network becomes available again -
|
||||||
|
* // the interrupt causes dc_perform_sentbox_idle() in the thread above
|
||||||
|
* // to return so that jobs are executed and messages are fetched.
|
||||||
|
* dc_maybe_network(context);
|
||||||
|
*
|
||||||
|
* @memberof dc_context_t
|
||||||
|
* @param context The context as created by dc_context_new().
|
||||||
|
* @return None.
|
||||||
|
*/
|
||||||
|
void dc_perform_sentbox_jobs (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch new messages from the Sent folder, if any.
|
* Fetch new messages from the Sent folder, if any.
|
||||||
|
|||||||
@@ -471,6 +471,18 @@ pub unsafe extern "C" fn dc_perform_mvbox_fetch(context: *mut dc_context_t) {
|
|||||||
.unwrap_or(())
|
.unwrap_or(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn dc_perform_mvbox_jobs(context: *mut dc_context_t) {
|
||||||
|
if context.is_null() {
|
||||||
|
eprintln!("ignoring careless call to dc_perform_mvbox_jobs()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ffi_context = &*context;
|
||||||
|
ffi_context
|
||||||
|
.with_inner(|ctx| job::perform_mvbox_jobs(ctx))
|
||||||
|
.unwrap_or(())
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn dc_perform_mvbox_idle(context: *mut dc_context_t) {
|
pub unsafe extern "C" fn dc_perform_mvbox_idle(context: *mut dc_context_t) {
|
||||||
if context.is_null() {
|
if context.is_null() {
|
||||||
@@ -507,6 +519,18 @@ pub unsafe extern "C" fn dc_perform_sentbox_fetch(context: *mut dc_context_t) {
|
|||||||
.unwrap_or(())
|
.unwrap_or(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn dc_perform_sentbox_jobs(context: *mut dc_context_t) {
|
||||||
|
if context.is_null() {
|
||||||
|
eprintln!("ignoring careless call to dc_perform_sentbox_jobs()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ffi_context = &*context;
|
||||||
|
ffi_context
|
||||||
|
.with_inner(|ctx| job::perform_sentbox_jobs(ctx))
|
||||||
|
.unwrap_or(())
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn dc_perform_sentbox_idle(context: *mut dc_context_t) {
|
pub unsafe extern "C" fn dc_perform_sentbox_idle(context: *mut dc_context_t) {
|
||||||
if context.is_null() {
|
if context.is_null() {
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ class Account(object):
|
|||||||
ev = self._evlogger.get_matching("DC_EVENT_INCOMING_MSG")
|
ev = self._evlogger.get_matching("DC_EVENT_INCOMING_MSG")
|
||||||
return self.get_message_by_id(ev[2])
|
return self.get_message_by_id(ev[2])
|
||||||
|
|
||||||
def start_threads(self):
|
def start_threads(self, mvbox=False, sentbox=False):
|
||||||
""" start IMAP/SMTP threads (and configure account if it hasn't happened).
|
""" start IMAP/SMTP threads (and configure account if it hasn't happened).
|
||||||
|
|
||||||
:raises: ValueError if 'addr' or 'mail_pw' are not configured.
|
:raises: ValueError if 'addr' or 'mail_pw' are not configured.
|
||||||
@@ -395,7 +395,7 @@ class Account(object):
|
|||||||
"""
|
"""
|
||||||
if not self.is_configured():
|
if not self.is_configured():
|
||||||
self.configure()
|
self.configure()
|
||||||
self._threads.start()
|
self._threads.start(mvbox=mvbox, sentbox=sentbox)
|
||||||
|
|
||||||
def stop_threads(self, wait=True):
|
def stop_threads(self, wait=True):
|
||||||
""" stop IMAP/SMTP threads. """
|
""" stop IMAP/SMTP threads. """
|
||||||
@@ -436,10 +436,14 @@ class IOThreads:
|
|||||||
def is_started(self):
|
def is_started(self):
|
||||||
return len(self._name2thread) > 0
|
return len(self._name2thread) > 0
|
||||||
|
|
||||||
def start(self, imap=True, smtp=True):
|
def start(self, imap=True, smtp=True, mvbox=False, sentbox=False):
|
||||||
assert not self.is_started()
|
assert not self.is_started()
|
||||||
if imap:
|
if imap:
|
||||||
self._start_one_thread("imap", self.imap_thread_run)
|
self._start_one_thread("inbox", self.imap_thread_run)
|
||||||
|
if mvbox:
|
||||||
|
self._start_one_thread("mvbox", self.mvbox_thread_run)
|
||||||
|
if sentbox:
|
||||||
|
self._start_one_thread("sentbox", self.sentbox_thread_run)
|
||||||
if smtp:
|
if smtp:
|
||||||
self._start_one_thread("smtp", self.smtp_thread_run)
|
self._start_one_thread("smtp", self.smtp_thread_run)
|
||||||
|
|
||||||
@@ -452,17 +456,35 @@ class IOThreads:
|
|||||||
self._thread_quitflag = True
|
self._thread_quitflag = True
|
||||||
lib.dc_interrupt_imap_idle(self._dc_context)
|
lib.dc_interrupt_imap_idle(self._dc_context)
|
||||||
lib.dc_interrupt_smtp_idle(self._dc_context)
|
lib.dc_interrupt_smtp_idle(self._dc_context)
|
||||||
|
lib.dc_interrupt_mvbox_idle(self._dc_context)
|
||||||
|
lib.dc_interrupt_sentbox_idle(self._dc_context)
|
||||||
if wait:
|
if wait:
|
||||||
for name, thread in self._name2thread.items():
|
for name, thread in self._name2thread.items():
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
||||||
def imap_thread_run(self):
|
def imap_thread_run(self):
|
||||||
self._log_event("py-bindings-info", 0, "IMAP THREAD START")
|
self._log_event("py-bindings-info", 0, "INBOX THREAD START")
|
||||||
while not self._thread_quitflag:
|
while not self._thread_quitflag:
|
||||||
lib.dc_perform_imap_jobs(self._dc_context)
|
lib.dc_perform_imap_jobs(self._dc_context)
|
||||||
lib.dc_perform_imap_fetch(self._dc_context)
|
lib.dc_perform_imap_fetch(self._dc_context)
|
||||||
lib.dc_perform_imap_idle(self._dc_context)
|
lib.dc_perform_imap_idle(self._dc_context)
|
||||||
self._log_event("py-bindings-info", 0, "IMAP THREAD FINISHED")
|
self._log_event("py-bindings-info", 0, "INBOX THREAD FINISHED")
|
||||||
|
|
||||||
|
def mvbox_thread_run(self):
|
||||||
|
self._log_event("py-bindings-info", 0, "MVBOX THREAD START")
|
||||||
|
while not self._thread_quitflag:
|
||||||
|
lib.dc_perform_mvbox_jobs(self._dc_context)
|
||||||
|
lib.dc_perform_mvbox_fetch(self._dc_context)
|
||||||
|
lib.dc_perform_mvbox_idle(self._dc_context)
|
||||||
|
self._log_event("py-bindings-info", 0, "MVBOX THREAD FINISHED")
|
||||||
|
|
||||||
|
def sentbox_thread_run(self):
|
||||||
|
self._log_event("py-bindings-info", 0, "SENTBOX THREAD START")
|
||||||
|
while not self._thread_quitflag:
|
||||||
|
lib.dc_perform_sentbox_jobs(self._dc_context)
|
||||||
|
lib.dc_perform_sentbox_fetch(self._dc_context)
|
||||||
|
lib.dc_perform_sentbox_idle(self._dc_context)
|
||||||
|
self._log_event("py-bindings-info", 0, "SENTBOX THREAD FINISHED")
|
||||||
|
|
||||||
def smtp_thread_run(self):
|
def smtp_thread_run(self):
|
||||||
self._log_event("py-bindings-info", 0, "SMTP THREAD START")
|
self._log_event("py-bindings-info", 0, "SMTP THREAD START")
|
||||||
|
|||||||
@@ -163,10 +163,10 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig):
|
|||||||
ac._evlogger.set_timeout(30)
|
ac._evlogger.set_timeout(30)
|
||||||
return ac, dict(configdict)
|
return ac, dict(configdict)
|
||||||
|
|
||||||
def get_online_configuring_account(self):
|
def get_online_configuring_account(self, mvbox=False, sentbox=False):
|
||||||
ac, configdict = self.get_online_config()
|
ac, configdict = self.get_online_config()
|
||||||
ac.configure(**configdict)
|
ac.configure(**configdict)
|
||||||
ac.start_threads()
|
ac.start_threads(mvbox=mvbox, sentbox=sentbox)
|
||||||
return ac
|
return ac
|
||||||
|
|
||||||
def get_two_online_accounts(self):
|
def get_two_online_accounts(self):
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class TestOfflineChat:
|
|||||||
def chat1(self, ac1):
|
def chat1(self, ac1):
|
||||||
contact1 = ac1.create_contact("some1@hello.com", name="some1")
|
contact1 = ac1.create_contact("some1@hello.com", name="some1")
|
||||||
chat = ac1.create_chat_by_contact(contact1)
|
chat = ac1.create_chat_by_contact(contact1)
|
||||||
assert chat.id >= const.DC_CHAT_ID_LAST_SPECIAL, chat.id
|
assert chat.id > const.DC_CHAT_ID_LAST_SPECIAL, chat.id
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
def test_display(self, chat1):
|
def test_display(self, chat1):
|
||||||
@@ -337,14 +337,14 @@ class TestOnlineAccount:
|
|||||||
def get_chat(self, ac1, ac2):
|
def get_chat(self, ac1, ac2):
|
||||||
c2 = ac1.create_contact(email=ac2.get_config("addr"))
|
c2 = ac1.create_contact(email=ac2.get_config("addr"))
|
||||||
chat = ac1.create_chat_by_contact(c2)
|
chat = ac1.create_chat_by_contact(c2)
|
||||||
assert chat.id >= const.DC_CHAT_ID_LAST_SPECIAL
|
assert chat.id > const.DC_CHAT_ID_LAST_SPECIAL
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
def test_one_account_send(self, acfactory):
|
def test_one_account_send(self, acfactory):
|
||||||
ac1 = acfactory.get_online_configuring_account()
|
ac1 = acfactory.get_online_configuring_account()
|
||||||
c2 = ac1.create_contact(email=ac1.get_config("addr"))
|
c2 = ac1.create_contact(email=ac1.get_config("addr"))
|
||||||
chat = ac1.create_chat_by_contact(c2)
|
chat = ac1.create_chat_by_contact(c2)
|
||||||
assert chat.id >= const.DC_CHAT_ID_LAST_SPECIAL
|
assert chat.id > const.DC_CHAT_ID_LAST_SPECIAL
|
||||||
wait_successful_IMAP_SMTP_connection(ac1)
|
wait_successful_IMAP_SMTP_connection(ac1)
|
||||||
wait_configuration_progress(ac1, 1000)
|
wait_configuration_progress(ac1, 1000)
|
||||||
|
|
||||||
@@ -365,6 +365,16 @@ class TestOnlineAccount:
|
|||||||
msg_in = ac2.get_message_by_id(msg_out.id)
|
msg_in = ac2.get_message_by_id(msg_out.id)
|
||||||
assert msg_in.text == "message1"
|
assert msg_in.text == "message1"
|
||||||
|
|
||||||
|
def test_mvbox_sentbox_threads(self, acfactory):
|
||||||
|
ac1 = acfactory.get_online_configuring_account(mvbox=True, sentbox=True)
|
||||||
|
ac2 = acfactory.get_online_configuring_account()
|
||||||
|
wait_configuration_progress(ac2, 1000)
|
||||||
|
wait_configuration_progress(ac1, 1000)
|
||||||
|
chat = self.get_chat(ac1, ac2)
|
||||||
|
chat.send_text("message1")
|
||||||
|
ev = ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED")
|
||||||
|
assert ev[2] > const.DC_CHAT_ID_LAST_SPECIAL
|
||||||
|
|
||||||
def test_forward_messages(self, acfactory):
|
def test_forward_messages(self, acfactory):
|
||||||
ac1, ac2 = acfactory.get_two_online_accounts()
|
ac1, ac2 = acfactory.get_two_online_accounts()
|
||||||
chat = self.get_chat(ac1, ac2)
|
chat = self.get_chat(ac1, ac2)
|
||||||
@@ -430,8 +440,8 @@ class TestOnlineAccount:
|
|||||||
ac2.mark_seen_messages([msg_in])
|
ac2.mark_seen_messages([msg_in])
|
||||||
lp.step("1")
|
lp.step("1")
|
||||||
ev = ac1._evlogger.get_matching("DC_EVENT_MSG_READ")
|
ev = ac1._evlogger.get_matching("DC_EVENT_MSG_READ")
|
||||||
assert ev[1] >= const.DC_CHAT_ID_LAST_SPECIAL
|
assert ev[1] > const.DC_CHAT_ID_LAST_SPECIAL
|
||||||
assert ev[2] >= const.DC_MSG_ID_LAST_SPECIAL
|
assert ev[2] > const.DC_MSG_ID_LAST_SPECIAL
|
||||||
lp.step("2")
|
lp.step("2")
|
||||||
assert msg_out.is_out_mdn_received()
|
assert msg_out.is_out_mdn_received()
|
||||||
|
|
||||||
|
|||||||
@@ -761,6 +761,14 @@ pub fn perform_imap_jobs(context: &Context) {
|
|||||||
info!(context, "dc_perform_imap_jobs ended.",);
|
info!(context, "dc_perform_imap_jobs ended.",);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn perform_mvbox_jobs(context: &Context) {
|
||||||
|
info!(context, "dc_perform_mbox_jobs EMPTY (for now).",);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn perform_sentbox_jobs(context: &Context) {
|
||||||
|
info!(context, "dc_perform_sentbox_jobs EMPTY (for now).",);
|
||||||
|
}
|
||||||
|
|
||||||
fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||||
let query = if !probe_network {
|
let query = if !probe_network {
|
||||||
// processing for first-try and after backoff-timeouts:
|
// processing for first-try and after backoff-timeouts:
|
||||||
|
|||||||
Reference in New Issue
Block a user