use super::MessageIndex;
use crate::error::Result;
use crate::notmuch::Notmuch;
use ecr_core::revision::Revision;
use std::time::{Duration, Instant};
const CHUNK: u64 = 2_000;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Refreshed {
pub revision: Revision,
pub messages: u64,
pub rebuilt: bool,
pub took: Duration,
}
pub async fn refresh(index: &MessageIndex, notmuch: &Notmuch) -> Result<Refreshed> {
Ok(run(index, notmuch, true)
.await?
.expect("a rebuild is allowed"))
}
pub async fn refresh_incremental(
index: &MessageIndex,
notmuch: &Notmuch,
) -> Result<Option<Refreshed>> {
run(index, notmuch, false).await
}
async fn run(
index: &MessageIndex,
notmuch: &Notmuch,
may_rebuild: bool,
) -> Result<Option<Refreshed>> {
let started = Instant::now();
let (revision, total) = notmuch.revision_and_total().await?;
let held = index.revision()?;
let deletions = held.is_some() && index.message_count()? > total;
let rebuilt = match &held {
Some(held) if held.uuid == revision.uuid && held.lastmod <= revision.lastmod => deletions,
_ => true,
};
if rebuilt && !may_rebuild {
return Ok(None);
}
if rebuilt {
index.clear()?;
}
let mut from = match (rebuilt, &held) {
(false, Some(held)) => held.lastmod + 1,
_ => 0,
};
while from <= revision.lastmod {
let to = (from + CHUNK - 1).min(revision.lastmod);
let messages = notmuch.messages_between(from, to).await?;
index.apply(&messages, &Revision::new(&revision.uuid, to))?;
from = to + 1;
}
Ok(Some(Refreshed {
revision,
messages: index.message_count()?,
rebuilt,
took: started.elapsed(),
}))
}