mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-31 01:52:30 +00:00
130 lines
4.5 KiB
Rust
130 lines
4.5 KiB
Rust
//
|
|
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
|
//
|
|
// This file is part of the Bichon Email Archiving Project
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// 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 crate::{
|
|
modules::{
|
|
account::{
|
|
dispatcher::STATUS_DISPATCHER,
|
|
migration::{AccountModel, AccountType},
|
|
state::AccountRunningState,
|
|
},
|
|
cache::imap::{mailbox::MailBox, sync::flow::FetchDirection},
|
|
error::BichonResult,
|
|
},
|
|
utc_now,
|
|
};
|
|
use flow::reconcile_mailboxes;
|
|
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;
|
|
|
|
pub mod flow;
|
|
pub mod rebuild;
|
|
pub mod sync_folders;
|
|
pub mod sync_type;
|
|
|
|
pub async fn execute_imap_sync(account: &AccountModel) -> BichonResult<()> {
|
|
assert_eq!(account.account_type, AccountType::IMAP);
|
|
let start_time = Instant::now();
|
|
let account_id = account.id;
|
|
let sync_type = determine_sync_type(account).await?;
|
|
if matches!(sync_type, SyncType::SkipSync) {
|
|
return Ok(());
|
|
}
|
|
let remote_mailboxes = get_sync_folders(account).await?;
|
|
if matches!(sync_type, SyncType::InitialSync) {
|
|
AccountRunningState::add(account.id).await?;
|
|
// AccountRunningState::set_initial_sync_start(account_id).await?;
|
|
let result = match &account.date_since {
|
|
Some(date_since) => {
|
|
rebuild_cache_by_date(
|
|
account,
|
|
&remote_mailboxes,
|
|
&date_since.since_date()?,
|
|
FetchDirection::Since,
|
|
)
|
|
.await
|
|
}
|
|
None => match &account.date_before {
|
|
Some(r) => {
|
|
rebuild_cache_by_date(
|
|
account,
|
|
&remote_mailboxes,
|
|
&r.calculate_date()?,
|
|
FetchDirection::Before,
|
|
)
|
|
.await
|
|
}
|
|
None => rebuild_cache(account, &remote_mailboxes).await,
|
|
},
|
|
};
|
|
match result {
|
|
Ok(_) => {
|
|
AccountRunningState::set_initial_sync_completed(account_id).await?;
|
|
}
|
|
Err(e) => {
|
|
STATUS_DISPATCHER
|
|
.append_error(
|
|
account_id,
|
|
format!("Initial sync failed for the account, error: {:#?}", e),
|
|
)
|
|
.await;
|
|
AccountRunningState::set_initial_sync_failed(account_id).await?;
|
|
}
|
|
}
|
|
return Ok(());
|
|
}
|
|
|
|
if let Some(state) = AccountRunningState::get(account_id).await? {
|
|
let now = utc_now!();
|
|
const COOLDOWN_MS: i64 = 60 * 1000;
|
|
let mut should_skip = false;
|
|
if let Some(time) = state.initial_sync_end_time {
|
|
if now - time < COOLDOWN_MS {
|
|
should_skip = true;
|
|
}
|
|
}
|
|
if let Some(time) = state.initial_sync_failed_time {
|
|
if now - time < COOLDOWN_MS {
|
|
should_skip = true;
|
|
}
|
|
}
|
|
if should_skip {
|
|
return Ok(());
|
|
}
|
|
}
|
|
AccountRunningState::set_incremental_sync_start(account.id).await?;
|
|
let local_mailboxes = MailBox::list_all(account_id).await?;
|
|
reconcile_mailboxes(account, &remote_mailboxes, &local_mailboxes).await?;
|
|
let elapsed_time = start_time.elapsed().as_secs();
|
|
debug!(
|
|
"Account{{{}}} Incremental sync completed: {} seconds elapsed.",
|
|
account.email, elapsed_time
|
|
);
|
|
|
|
if let Some(state) = AccountRunningState::get(account.id).await? {
|
|
if !state.is_initial_sync_completed {
|
|
AccountRunningState::set_initial_sync_completed(account_id).await?;
|
|
}
|
|
}
|
|
AccountRunningState::set_incremental_sync_end(account_id).await?;
|
|
Ok(())
|
|
}
|