imap: update cache on set_flags
Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>pull/315/head
parent
0500e451da
commit
23507932f9
|
@ -38,7 +38,7 @@ impl Account {
|
|||
let handle = self
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("set_unseen".into(), fut);
|
||||
.spawn_specialized("set_flags".into(), fut);
|
||||
let job_id = handle.job_id;
|
||||
self.insert_job(
|
||||
job_id,
|
||||
|
|
|
@ -42,7 +42,7 @@ nom = { version = "7" }
|
|||
notify = { version = "4.0.15", optional = true }
|
||||
polling = "2.8"
|
||||
regex = { version = "1" }
|
||||
rusqlite = { version = "^0.29", default-features = false, optional = true }
|
||||
rusqlite = { version = "^0.29", default-features = false, features = ["array"], optional = true }
|
||||
serde = { version = "1.0", features = ["rc"] }
|
||||
serde_derive = "1.0"
|
||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||
|
|
|
@ -92,6 +92,13 @@ pub trait ImapCache: Send + std::fmt::Debug {
|
|||
identifier: std::result::Result<UID, EnvelopeHash>,
|
||||
mailbox_hash: MailboxHash,
|
||||
) -> Result<Option<Vec<u8>>>;
|
||||
|
||||
fn update_flags(
|
||||
&mut self,
|
||||
env_hashes: EnvelopeHashBatch,
|
||||
mailbox_hash: MailboxHash,
|
||||
flags: SmallVec<[FlagOp; 8]>,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait ImapCacheReset: Send + std::fmt::Debug {
|
||||
|
@ -108,7 +115,7 @@ pub mod sqlite3_m {
|
|||
use super::*;
|
||||
use crate::utils::sqlite3::{
|
||||
self,
|
||||
rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput},
|
||||
rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, Value},
|
||||
Connection, DatabaseDescription,
|
||||
};
|
||||
|
||||
|
@ -151,6 +158,12 @@ pub mod sqlite3_m {
|
|||
version: 3,
|
||||
};
|
||||
|
||||
impl From<EnvelopeHash> for Value {
|
||||
fn from(env_hash: EnvelopeHash) -> Self {
|
||||
(env_hash.0 as i64).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql for ModSequence {
|
||||
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
|
||||
Ok(ToSqlOutput::from(self.0.get() as i64))
|
||||
|
@ -539,6 +552,67 @@ pub mod sqlite3_m {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_flags(
|
||||
&mut self,
|
||||
env_hashes: EnvelopeHashBatch,
|
||||
mailbox_hash: MailboxHash,
|
||||
flags: SmallVec<[FlagOp; 8]>,
|
||||
) -> Result<()> {
|
||||
if self.mailbox_state(mailbox_hash)?.is_none() {
|
||||
return Err(Error::new("Mailbox is not in cache").set_kind(ErrorKind::Bug));
|
||||
}
|
||||
let Self {
|
||||
ref mut connection,
|
||||
ref uid_store,
|
||||
loaded_mailboxes: _,
|
||||
} = self;
|
||||
let tx = connection.transaction()?;
|
||||
let values =
|
||||
std::rc::Rc::new(env_hashes.iter().map(Value::from).collect::<Vec<Value>>());
|
||||
|
||||
let mut stmt =
|
||||
tx.prepare("SELECT uid, envelope FROM envelopes WHERE hash IN rarray(?1);")?;
|
||||
let rows = stmt
|
||||
.query_map([values], |row| Ok((row.get(0)?, row.get(1)?)))?
|
||||
.filter_map(|r| r.ok())
|
||||
.collect::<Vec<(UID, Envelope)>>();
|
||||
drop(stmt);
|
||||
let mut stmt = tx.prepare(
|
||||
"UPDATE envelopes SET envelope = ?1 WHERE mailbox_hash = ?2 AND uid = ?3;",
|
||||
)?;
|
||||
for (uid, mut env) in rows {
|
||||
for op in flags.iter() {
|
||||
match op {
|
||||
FlagOp::UnSet(flag) | FlagOp::Set(flag) => {
|
||||
let mut f = env.flags();
|
||||
f.set(*flag, op.as_bool());
|
||||
env.set_flags(f);
|
||||
}
|
||||
FlagOp::UnSetTag(tag) | FlagOp::SetTag(tag) => {
|
||||
let hash = TagHash::from_bytes(tag.as_bytes());
|
||||
if op.as_bool() {
|
||||
env.tags_mut().insert(hash);
|
||||
} else {
|
||||
env.tags_mut().remove(&hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt.execute(sqlite3::params![&env, mailbox_hash, uid as Sqlite3UID])?;
|
||||
uid_store
|
||||
.envelopes
|
||||
.lock()
|
||||
.unwrap()
|
||||
.entry(env.hash())
|
||||
.and_modify(|entry| {
|
||||
entry.inner = env;
|
||||
});
|
||||
}
|
||||
drop(stmt);
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
mailbox_hash: MailboxHash,
|
||||
|
@ -829,5 +903,14 @@ pub mod default_m {
|
|||
) -> Result<Option<Vec<u8>>> {
|
||||
Err(Error::new("melib is not built with any imap cache").set_kind(ErrorKind::Bug))
|
||||
}
|
||||
|
||||
fn update_flags(
|
||||
&mut self,
|
||||
_env_hashes: EnvelopeHashBatch,
|
||||
_mailbox_hash: MailboxHash,
|
||||
_flags: SmallVec<[FlagOp; 8]>,
|
||||
) -> Result<()> {
|
||||
Err(Error::new("melib is not built with any imap cache").set_kind(ErrorKind::Bug))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -857,6 +857,12 @@ impl MailBackend for ImapType {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlite3")]
|
||||
if *uid_store.keep_offline_cache.lock().unwrap() {
|
||||
let mut cache_handle = cache::Sqlite3Cache::get(uid_store.clone())?;
|
||||
let res = cache_handle.update_flags(env_hashes, mailbox_hash, flags);
|
||||
log::trace!("update_flags in cache: {:?}", res);
|
||||
}
|
||||
Ok(())
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -102,11 +102,6 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
|||
mailbox_hash,
|
||||
kind: RefreshEventKind::Rescan,
|
||||
});
|
||||
/*
|
||||
uid_store.uid_index.lock().unwrap().clear();
|
||||
uid_store.hash_index.lock().unwrap().clear();
|
||||
uid_store.byte_cache.lock().unwrap().clear();
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
uidvalidities.insert(mailbox_hash, select_response.uidvalidity);
|
||||
|
|
|
@ -45,7 +45,10 @@ pub fn open_db(db_path: PathBuf) -> Result<Connection> {
|
|||
if !db_path.exists() {
|
||||
return Err(Error::new("Database doesn't exist"));
|
||||
}
|
||||
Connection::open(&db_path).map_err(|e| Error::new(e.to_string()))
|
||||
Ok(Connection::open(&db_path).and_then(|db| {
|
||||
rusqlite::vtab::array::load_module(&db)?;
|
||||
Ok(db)
|
||||
})?)
|
||||
}
|
||||
|
||||
pub fn open_or_create_db(
|
||||
|
@ -66,7 +69,8 @@ pub fn open_or_create_db(
|
|||
db_path.display()
|
||||
);
|
||||
}
|
||||
let conn = Connection::open(&db_path).map_err(|e| Error::new(e.to_string()))?;
|
||||
let conn = Connection::open(&db_path)?;
|
||||
rusqlite::vtab::array::load_module(&conn)?;
|
||||
if set_mode {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let file = std::fs::File::open(&db_path)?;
|
||||
|
|
Loading…
Reference in New Issue