Skip to content

Commit

Permalink
Prepare db for modsequence RFC9051
Browse files Browse the repository at this point in the history
  • Loading branch information
MTRNord committed Jul 29, 2023
1 parent 5fefb58 commit 3a21d04
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE mails
DROP COLUMN modseq;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE mails
ADD COLUMN modseq BIGSERIAL constraint NOT NULL;
72 changes: 32 additions & 40 deletions crates/erooster_core/src/backend/storage/maildir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,21 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
.collect()
.await;
maildir.find(id).map(|entry| {
let uid = mail_rows
.iter()
.find(|x| x.maildir_id == id)
.map_or(0, |x| x.id);
let db_item = mail_rows.iter().find(|y: &&DbMails| y.maildir_id == id);
let uid: i32 = db_item.map_or(0, |y| y.id);
let modseq = db_item.map_or(0, |y| y.modseq);

let mail_state = if entry.is_seen() {
MailState::Read
} else {
MailState::New
};
MaildirMailEntry {
uid: uid.try_into().expect("Invalid UID"),
modseq: modseq.try_into().expect("Invalid UID"),
entry,
mail_state,
sequence_number: None,
date: None,
}
})
}
Expand Down Expand Up @@ -150,8 +150,9 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
.collect::<Vec<_>>()
.join("");
let maildir_id = maildir.store_cur_with_flags(data, &maildir_flags)?;
sqlx::query("INSERT INTO mails (maildir_id) VALUES ($1)")
sqlx::query("INSERT INTO mails (maildir_id, modseq) VALUES ($1, $2)")
.bind(maildir_id.clone())
.bind(1i64)
.execute(self.db.get_pool())
.await?;
Ok(maildir_id)
Expand All @@ -161,8 +162,9 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
async fn store_new(&self, path: &Path, data: &[u8]) -> color_eyre::eyre::Result<String> {
let maildir = Maildir::from(path.to_path_buf());
let maildir_id = maildir.store_new(data)?;
sqlx::query("INSERT INTO mails (maildir_id) VALUES ($1)")
sqlx::query("INSERT INTO mails (maildir_id, modseq) VALUES ($1, $2)")
.bind(maildir_id.clone())
.bind(1i64)
.execute(self.db.get_pool())
.await?;
Ok(maildir_id)
Expand Down Expand Up @@ -205,16 +207,17 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
.filter_map(|x| match x {
Ok(x) => {
let maildir_id = x.id();
let uid = mail_rows
.iter()
.find(|y| y.maildir_id == maildir_id)
.map_or(0, |y| y.id);

let db_item = mail_rows.iter().find(|y| y.maildir_id == maildir_id);
let uid: i32 = db_item.map_or(0, |y| y.id);
let modseq = db_item.map_or(0, |y| y.modseq);

Some(MaildirMailEntry {
uid: uid.try_into().expect("Invalid UID"),
modseq: modseq.try_into().expect("Invalid UID"),
entry: x,
mail_state: MailState::Read,
sequence_number: None,
date: None,
})
}
Err(_) => None,
Expand All @@ -236,16 +239,17 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
.filter_map(|x| match x {
Ok(x) => {
let maildir_id = x.id();
let uid = mail_rows
.iter()
.find(|y| y.maildir_id == maildir_id)
.map_or(0, |y| y.id);

let db_item = mail_rows.iter().find(|y| y.maildir_id == maildir_id);
let uid: i32 = db_item.map_or(0, |y| y.id);
let modseq = db_item.map_or(0, |y| y.modseq);

Some(MaildirMailEntry {
uid: uid.try_into().expect("Invalid UID"),
modseq: modseq.try_into().expect("Invalid UID"),
entry: x,
mail_state: MailState::New,
sequence_number: None,
date: None,
})
}
Err(_) => None,
Expand All @@ -269,21 +273,20 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
.filter_map(|x| match x {
Ok(x) => {
let maildir_id = x.id();
let uid = mail_rows
.iter()
.find(|y| y.maildir_id == maildir_id)
.map_or(0, |y| y.id);
let db_item = mail_rows.iter().find(|y| y.maildir_id == maildir_id);
let uid: i32 = db_item.map_or(0, |y| y.id);
let modseq = db_item.map_or(0, |y| y.modseq);
let state = if x.is_seen() {
MailState::Read
} else {
MailState::New
};
Some(MaildirMailEntry {
uid: uid.try_into().expect("Invalid UID"),
modseq: modseq.try_into().expect("Invalid Modseq"),
entry: x,
mail_state: state,
sequence_number: None,
date: None,
})
}
Err(_) => None,
Expand Down Expand Up @@ -440,38 +443,32 @@ impl MailStorage<MaildirMailEntry> for MaildirStorage {
#[derive(sqlx::FromRow)]
struct DbMails {
id: i32,
#[allow(dead_code)]
maildir_id: String,
modseq: i64,
}

/// Wrapper for the mailentries from the Maildir crate
pub struct MaildirMailEntry {
entry: maildir::MailEntry,
uid: u32,
modseq: u64,
/// The sequence number. It is None until used
pub sequence_number: Option<u32>,
date: Option<i64>,
mail_state: MailState,
}

impl MaildirMailEntry {
/// Loads async data in memory for non mut usage
/// FIXME: This should probably return the error somewhere
pub fn load(&mut self) {
self.date = match self.entry.date() {
Ok(date) => Some(date),
Err(_) => None,
};
}
}

#[async_trait::async_trait]
impl MailEntry for MaildirMailEntry {
#[instrument(skip(self))]
fn uid(&self) -> u32 {
self.uid
}

#[instrument(skip(self))]
fn modseq(&self) -> u64 {
self.modseq
}

#[instrument(skip(self))]
fn mail_state(&self) -> MailState {
self.mail_state
Expand Down Expand Up @@ -502,11 +499,6 @@ impl MailEntry for MaildirMailEntry {
self.entry.received().map_err(Into::into)
}

#[instrument(skip(self))]
fn date(&self) -> Option<i64> {
self.date
}

#[instrument(skip(self))]
fn flags(&self) -> &str {
self.entry.flags()
Expand Down
4 changes: 2 additions & 2 deletions crates/erooster_core/src/backend/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub enum MailState {
pub trait MailEntry {
/// The uid of the mail entry
fn uid(&self) -> u32;
/// The metadata modification sequence of the mail entry
fn modseq(&self) -> u64;
/// The state (new or read) of the mail entry
fn mail_state(&self) -> MailState;
/// The sequence number of the mail entry
Expand All @@ -48,8 +50,6 @@ pub trait MailEntry {
fn headers(&mut self) -> color_eyre::eyre::Result<Vec<MailHeader>>;
/// The received time of the email
fn received(&mut self) -> color_eyre::eyre::Result<i64>;
/// The date of the email
fn date(&self) -> Option<i64>;
/// The flags of the email
fn flags(&self) -> &str;
/// Whether the email is a draft
Expand Down
3 changes: 2 additions & 1 deletion crates/erooster_imap/src/commands/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ where
{
let count = storage.count_cur(&mailbox_path) + storage.count_new(&mailbox_path);
lines.feed(format!("* {count} EXISTS")).await?;
// TODO: Also send UNSEEN
// FIXME: This is fundamentaly invalid and instead should refer to the timestamp a mailbox was created

Check warning on line 80 in crates/erooster_imap/src/commands/select.rs

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"fundamentaly" should be "fundamentally".
let current_time = SystemTime::now();
let unix_timestamp = current_time.duration_since(UNIX_EPOCH)?;
Expand All @@ -101,7 +102,7 @@ where
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\*)] Limited",
))
.await?;
// TODO generate proper list command
// TODO: generate proper list command
lines.feed(format!("* LIST () \".\" \"{folder}\"")).await?;
let sub_folders = storage.list_subdirs(&mailbox_path)?;
for sub_folder in sub_folders {
Expand Down

0 comments on commit 3a21d04

Please sign in to comment.