mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
chore: remove bb8 pool for IMAP; create a new session per operation to avoid stale connections
This commit is contained in:
Vendored
+38
-24
@@ -30,8 +30,8 @@ use crate::{
|
||||
},
|
||||
SEMAPHORE,
|
||||
},
|
||||
context::executors::MAIL_CONTEXT,
|
||||
error::{code::ErrorCode, BichonError, BichonResult},
|
||||
imap::executor::ImapExecutor,
|
||||
indexer::manager::ENVELOPE_INDEX_MANAGER,
|
||||
},
|
||||
raise_error,
|
||||
@@ -55,16 +55,15 @@ pub async fn fetch_and_save_by_date(
|
||||
direction: FetchDirection,
|
||||
) -> BichonResult<usize> {
|
||||
let account_id = account.id;
|
||||
let executor = MAIL_CONTEXT.imap(account_id).await?;
|
||||
let mut session = ImapExecutor::create_connection(account_id).await?;
|
||||
|
||||
let search_criteria = match direction {
|
||||
FetchDirection::Since => format!("SINCE {date}"),
|
||||
FetchDirection::Before => format!("BEFORE {date}"),
|
||||
};
|
||||
|
||||
let uid_list = executor
|
||||
.uid_search(&mailbox.encoded_name(), &search_criteria)
|
||||
.await?;
|
||||
let uid_list =
|
||||
ImapExecutor::uid_search(&mut session, &mailbox.encoded_name(), &search_criteria).await?;
|
||||
|
||||
let len = uid_list.len();
|
||||
if len == 0 {
|
||||
@@ -109,12 +108,18 @@ pub async fn fetch_and_save_by_date(
|
||||
(index + 1) as u32,
|
||||
)
|
||||
.await?;
|
||||
let executor = MAIL_CONTEXT.imap(account_id).await?;
|
||||
|
||||
// Fetch metadata for the current batch of UIDs
|
||||
executor
|
||||
.uid_batch_retrieve_emails(account_id, mailbox.id, &batch, &mailbox.encoded_name())
|
||||
.await?;
|
||||
ImapExecutor::uid_batch_retrieve_emails(
|
||||
&mut session,
|
||||
account_id,
|
||||
mailbox.id,
|
||||
&batch,
|
||||
&mailbox.encoded_name(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
session.logout().await.ok();
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
@@ -153,26 +158,29 @@ pub async fn fetch_and_save_full_mailbox(
|
||||
"Starting full mailbox sync for '{}', total={}, limit={:?}, batches={}, desc={}",
|
||||
mailbox.name, total, folder_limit, total_batches, desc
|
||||
);
|
||||
|
||||
let mut session = ImapExecutor::create_connection(account_id).await?;
|
||||
|
||||
for page in 1..=total_batches {
|
||||
AccountRunningState::set_current_sync_batch_number(account_id, mailbox.name.clone(), page)
|
||||
.await?;
|
||||
let executor = MAIL_CONTEXT.imap(account_id).await?;
|
||||
let count = executor
|
||||
.batch_retrieve_emails(
|
||||
account_id,
|
||||
mailbox_id,
|
||||
page as u64,
|
||||
page_size as u64,
|
||||
&mailbox.encoded_name(),
|
||||
desc,
|
||||
)
|
||||
.await?;
|
||||
let count = ImapExecutor::batch_retrieve_emails(
|
||||
&mut session,
|
||||
account_id,
|
||||
mailbox_id,
|
||||
page as u64,
|
||||
page_size as u64,
|
||||
&mailbox.encoded_name(),
|
||||
desc,
|
||||
)
|
||||
.await?;
|
||||
inserted_count += count;
|
||||
info!(
|
||||
"Batch insertion completed for mailbox: {}, current page: {}, inserted count: {}",
|
||||
&mailbox.name, page, count
|
||||
);
|
||||
}
|
||||
session.logout().await.ok();
|
||||
Ok(inserted_count)
|
||||
}
|
||||
|
||||
@@ -423,16 +431,22 @@ async fn perform_incremental_sync(
|
||||
.await?;
|
||||
match local_max_uid {
|
||||
Some(max_uid) => {
|
||||
let executor = MAIL_CONTEXT.imap(account.id).await?;
|
||||
let mut session = ImapExecutor::create_connection(account.id).await?;
|
||||
let before_date = account
|
||||
.date_before
|
||||
.as_ref()
|
||||
.map(|r| r.calculate_date())
|
||||
.transpose()?;
|
||||
|
||||
executor
|
||||
.fetch_new_mail(account, local_mailbox, max_uid + 1, before_date.as_deref())
|
||||
.await?;
|
||||
ImapExecutor::fetch_new_mail(
|
||||
&mut session,
|
||||
account,
|
||||
local_mailbox,
|
||||
max_uid + 1,
|
||||
before_date.as_deref(),
|
||||
)
|
||||
.await?;
|
||||
session.logout().await.ok();
|
||||
}
|
||||
None => {
|
||||
info!(
|
||||
|
||||
Vendored
+15
-2
@@ -25,6 +25,7 @@ use crate::{
|
||||
},
|
||||
cache::imap::{mailbox::MailBox, sync::flow::FetchDirection},
|
||||
error::BichonResult,
|
||||
imap::executor::ImapExecutor,
|
||||
},
|
||||
utc_now,
|
||||
};
|
||||
@@ -33,7 +34,7 @@ use rebuild::{rebuild_cache, rebuild_cache_by_date};
|
||||
use std::time::Instant;
|
||||
use sync_folders::get_sync_folders;
|
||||
use sync_type::{determine_sync_type, SyncType};
|
||||
use tracing::debug;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
pub mod flow;
|
||||
pub mod rebuild;
|
||||
@@ -48,7 +49,19 @@ pub async fn execute_imap_sync(account: &AccountModel) -> BichonResult<()> {
|
||||
if matches!(sync_type, SyncType::SkipSync) {
|
||||
return Ok(());
|
||||
}
|
||||
let remote_mailboxes = get_sync_folders(account).await?;
|
||||
let mut session = ImapExecutor::create_connection(account_id).await?;
|
||||
let remote_mailboxes = match get_sync_folders(account, &mut session).await {
|
||||
Ok(mailboxes) => mailboxes,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
account_id = account.id,
|
||||
error = %err,
|
||||
"Failed to get sync folders, logging out and skipping this account"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
session.logout().await.ok();
|
||||
if matches!(sync_type, SyncType::InitialSync) {
|
||||
AccountRunningState::add(account.id).await?;
|
||||
// AccountRunningState::set_initial_sync_start(account_id).await?;
|
||||
|
||||
-2
@@ -121,7 +121,6 @@ pub async fn rebuild_cache_by_date(
|
||||
MailBox::batch_insert(remote_mailboxes).await?;
|
||||
|
||||
let mut handles = Vec::new();
|
||||
|
||||
let local_semaphore = Arc::new(Semaphore::new(DEFAULT_MAX_CONCURRENT_PER_ACCOUNT));
|
||||
|
||||
for mailbox in remote_mailboxes {
|
||||
@@ -164,7 +163,6 @@ pub async fn rebuild_cache_by_date(
|
||||
tokio::spawn(async move {
|
||||
let _global_permit = global_permit;
|
||||
let _local_permit = local_permit;
|
||||
|
||||
fetch_and_save_by_date(&account, date.as_str(), &mailbox, direction).await
|
||||
});
|
||||
handles.push(handle);
|
||||
|
||||
+8
-7
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::{
|
||||
@@ -24,19 +23,21 @@ use crate::{
|
||||
modules::{
|
||||
account::migration::{AccountModel, AccountType},
|
||||
cache::imap::mailbox::{AttributeEnum, MailBox},
|
||||
context::executors::MAIL_CONTEXT,
|
||||
error::{code::ErrorCode, BichonResult},
|
||||
imap::{executor::ImapExecutor, session::SessionStream},
|
||||
mailbox::list::convert_names_to_mailboxes,
|
||||
},
|
||||
raise_error,
|
||||
};
|
||||
use async_imap::types::Name;
|
||||
use async_imap::{types::Name, Session};
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
pub async fn get_sync_folders(account: &AccountModel) -> BichonResult<Vec<MailBox>> {
|
||||
pub async fn get_sync_folders(
|
||||
account: &AccountModel,
|
||||
session: &mut Session<Box<dyn SessionStream>>,
|
||||
) -> BichonResult<Vec<MailBox>> {
|
||||
assert_eq!(account.account_type, AccountType::IMAP);
|
||||
let executor = MAIL_CONTEXT.imap(account.id).await?;
|
||||
let names = executor.list_all_mailboxes().await?;
|
||||
let names = ImapExecutor::list_all_mailboxes(session).await?;
|
||||
if names.is_empty() {
|
||||
warn!(
|
||||
"Account {}: No mailboxes returned from IMAP server.",
|
||||
@@ -121,7 +122,7 @@ pub async fn get_sync_folders(account: &AccountModel) -> BichonResult<Vec<MailBo
|
||||
), ErrorCode::ImapUnexpectedResult));
|
||||
}
|
||||
}
|
||||
convert_names_to_mailboxes(account.id, matched_mailboxes).await
|
||||
convert_names_to_mailboxes(account.id, session, matched_mailboxes).await
|
||||
}
|
||||
|
||||
pub async fn detect_mailbox_changes(
|
||||
|
||||
Reference in New Issue
Block a user