From ed47855ef1a6c9d10d48080367ff8b280530e362 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 20 Mar 2024 17:31:54 +0100 Subject: [PATCH] Share UniqueIdent between collections --- aero-collections/src/calendar/mod.rs | 6 ++- aero-collections/src/calendar/namespace.rs | 47 +++++++++++++++++++ aero-collections/src/lib.rs | 1 + aero-collections/src/mail/incoming.rs | 2 +- aero-collections/src/mail/mailbox.rs | 2 +- aero-collections/src/mail/mod.rs | 1 - aero-collections/src/mail/namespace.rs | 2 +- aero-collections/src/mail/query.rs | 2 +- aero-collections/src/mail/snapshot.rs | 2 +- aero-collections/src/mail/uidindex.rs | 2 +- .../src/{mail => }/unique_ident.rs | 4 +- aero-collections/src/user.rs | 19 ++++++-- aero-proto/src/dav.rs | 13 ++++- aero-proto/src/imap/index.rs | 2 +- aero-proto/src/imap/mailbox_view.rs | 2 +- 15 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 aero-collections/src/calendar/namespace.rs rename aero-collections/src/{mail => }/unique_ident.rs (95%) diff --git a/aero-collections/src/calendar/mod.rs b/aero-collections/src/calendar/mod.rs index 19e3340..708e1f1 100644 --- a/aero-collections/src/calendar/mod.rs +++ b/aero-collections/src/calendar/mod.rs @@ -1 +1,5 @@ -//@FIXME Event Index +pub mod namespace; + +pub struct Calendar { + a: u64, +} diff --git a/aero-collections/src/calendar/namespace.rs b/aero-collections/src/calendar/namespace.rs new file mode 100644 index 0000000..cf8a159 --- /dev/null +++ b/aero-collections/src/calendar/namespace.rs @@ -0,0 +1,47 @@ +use anyhow::Result; +use std::collections::{HashMap, BTreeMap}; +use std::sync::{Weak, Arc}; + +use serde::{Deserialize, Serialize}; + +use aero_user::storage; + +use crate::unique_ident::UniqueIdent; +use crate::user::User; +use super::Calendar; + +pub(crate) const CAL_LIST_PK: &str = "calendars"; +pub(crate) const CAL_LIST_SK: &str = "list"; + +pub(crate) struct CalendarNs(std::sync::Mutex>>); +impl CalendarNs { + pub fn new() -> Self { + Self(std::sync::Mutex::new(HashMap::new())) + } + + pub fn list(&self) { + todo!(); + } +} + +#[derive(Serialize, Deserialize)] +pub(crate) struct CalendarList(BTreeMap); + +#[derive(Serialize, Deserialize, Clone, Copy, Debug)] +pub(crate) struct CalendarListEntry { + id_lww: (u64, Option), +} + +impl CalendarList { + pub(crate) async fn load(user: &Arc) -> Result<(Self, Option)> { + todo!(); + } + + pub(crate) async fn save(user: &Arc, ct: Option) -> Result<()> { + todo!(); + } + + pub(crate) fn new() -> Self { + Self(BTreeMap::new()) + } +} diff --git a/aero-collections/src/lib.rs b/aero-collections/src/lib.rs index adcfc93..269cd13 100644 --- a/aero-collections/src/lib.rs +++ b/aero-collections/src/lib.rs @@ -1,3 +1,4 @@ +pub mod unique_ident; pub mod user; pub mod mail; pub mod calendar; diff --git a/aero-collections/src/mail/incoming.rs b/aero-collections/src/mail/incoming.rs index 8220461..cd2f8fd 100644 --- a/aero-collections/src/mail/incoming.rs +++ b/aero-collections/src/mail/incoming.rs @@ -15,7 +15,7 @@ use aero_bayou::timestamp::now_msec; use crate::mail::mailbox::Mailbox; use crate::mail::uidindex::ImapUidvalidity; -use crate::mail::unique_ident::*; +use crate::unique_ident::*; use crate::user::User; use crate::mail::IMF; diff --git a/aero-collections/src/mail/mailbox.rs b/aero-collections/src/mail/mailbox.rs index a767678..25aacf5 100644 --- a/aero-collections/src/mail/mailbox.rs +++ b/aero-collections/src/mail/mailbox.rs @@ -9,7 +9,7 @@ use aero_bayou::Bayou; use aero_bayou::timestamp::now_msec; use crate::mail::uidindex::*; -use crate::mail::unique_ident::*; +use crate::unique_ident::*; use crate::mail::IMF; pub struct Mailbox { diff --git a/aero-collections/src/mail/mod.rs b/aero-collections/src/mail/mod.rs index 85361f3..ca9b08b 100644 --- a/aero-collections/src/mail/mod.rs +++ b/aero-collections/src/mail/mod.rs @@ -3,7 +3,6 @@ pub mod mailbox; pub mod query; pub mod snapshot; pub mod uidindex; -pub mod unique_ident; pub mod namespace; // Internet Message Format diff --git a/aero-collections/src/mail/namespace.rs b/aero-collections/src/mail/namespace.rs index 452ac68..b1f6a70 100644 --- a/aero-collections/src/mail/namespace.rs +++ b/aero-collections/src/mail/namespace.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use aero_bayou::timestamp::now_msec; use crate::mail::uidindex::ImapUidvalidity; -use crate::mail::unique_ident::{gen_ident, UniqueIdent}; +use crate::unique_ident::{gen_ident, UniqueIdent}; pub const MAILBOX_HIERARCHY_DELIMITER: char = '.'; diff --git a/aero-collections/src/mail/query.rs b/aero-collections/src/mail/query.rs index 3e6fe99..7faba41 100644 --- a/aero-collections/src/mail/query.rs +++ b/aero-collections/src/mail/query.rs @@ -1,6 +1,6 @@ use super::mailbox::MailMeta; use super::snapshot::FrozenMailbox; -use super::unique_ident::UniqueIdent; +use crate::unique_ident::UniqueIdent; use anyhow::Result; use futures::future::FutureExt; use futures::stream::{BoxStream, Stream, StreamExt}; diff --git a/aero-collections/src/mail/snapshot.rs b/aero-collections/src/mail/snapshot.rs index ed756b5..9503d4d 100644 --- a/aero-collections/src/mail/snapshot.rs +++ b/aero-collections/src/mail/snapshot.rs @@ -2,10 +2,10 @@ use std::sync::Arc; use anyhow::Result; +use crate::unique_ident::UniqueIdent; use super::mailbox::Mailbox; use super::query::{Query, QueryScope}; use super::uidindex::UidIndex; -use super::unique_ident::UniqueIdent; /// A Frozen Mailbox has a snapshot of the current mailbox /// state that is desynchronized with the real mailbox state. diff --git a/aero-collections/src/mail/uidindex.rs b/aero-collections/src/mail/uidindex.rs index 637a1ac..ca975a3 100644 --- a/aero-collections/src/mail/uidindex.rs +++ b/aero-collections/src/mail/uidindex.rs @@ -4,7 +4,7 @@ use im::{HashMap, OrdMap, OrdSet}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use aero_bayou::*; -use crate::mail::unique_ident::UniqueIdent; +use crate::unique_ident::UniqueIdent; pub type ModSeq = NonZeroU64; pub type ImapUid = NonZeroU32; diff --git a/aero-collections/src/mail/unique_ident.rs b/aero-collections/src/unique_ident.rs similarity index 95% rename from aero-collections/src/mail/unique_ident.rs rename to aero-collections/src/unique_ident.rs index 0987a2c..e4eea7a 100644 --- a/aero-collections/src/mail/unique_ident.rs +++ b/aero-collections/src/unique_ident.rs @@ -7,7 +7,7 @@ use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use aero_bayou::timestamp::now_msec; -/// An internal Mail Identifier is composed of two components: +/// An internal Aerogramme identifier is composed of two components: /// - a process identifier, 128 bits, itself composed of: /// - the timestamp of when the process started, 64 bits /// - a 64-bit random number @@ -15,7 +15,7 @@ use aero_bayou::timestamp::now_msec; /// They are not part of the protocol but an internal representation /// required by Aerogramme. /// Their main property is to be unique without having to rely -/// on synchronization between IMAP processes. +/// on synchronization between (IMAP) processes. #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct UniqueIdent(pub [u8; 24]); diff --git a/aero-collections/src/user.rs b/aero-collections/src/user.rs index 193ce90..0c6b931 100644 --- a/aero-collections/src/user.rs +++ b/aero-collections/src/user.rs @@ -12,19 +12,27 @@ use aero_user::storage; use crate::mail::incoming::incoming_mail_watch_process; use crate::mail::mailbox::Mailbox; use crate::mail::uidindex::ImapUidvalidity; -use crate::mail::unique_ident::UniqueIdent; +use crate::unique_ident::UniqueIdent; use crate::mail::namespace::{MAILBOX_HIERARCHY_DELIMITER, INBOX, DRAFTS, ARCHIVE, SENT, TRASH, MAILBOX_LIST_PK, MAILBOX_LIST_SK,MailboxList,CreatedMailbox}; +use crate::calendar::Calendar; //@FIXME User should be totally rewriten -//to extract the local mailbox list -//to the mail/namespace.rs file (and mailbox list should be reworded as mail namespace) +// to extract the local mailbox list +// to the mail/namespace.rs file (and mailbox list should be reworded as mail namespace) + +//@FIXME User should be run in a LocalSet +// to remove most - if not all - synchronizations types. +// Especially RwLock & co. pub struct User { pub username: String, pub creds: Credentials, pub storage: storage::Store, pub mailboxes: std::sync::Mutex>>, + pub calendars: std::sync::Mutex>>, + // Handle on worker processing received email + // (moving emails from the mailqueue to the user's INBOX) tx_inbox_id: watch::Sender>, } @@ -178,6 +186,7 @@ impl User { storage, tx_inbox_id, mailboxes: std::sync::Mutex::new(HashMap::new()), + calendars: std::sync::Mutex::new(HashMap::new()), }); // Ensure INBOX exists (done inside load_mailbox_list) @@ -204,6 +213,10 @@ impl User { } } + // The idea here is that: + // 1. Opening a mailbox that is not already opened takes a significant amount of time + // 2. We don't want to lock the whole HashMap that contain the mailboxes during this + // operation which is why we droppped the lock above but take it again below. let mb = Arc::new(Mailbox::open(&self.creds, id, min_uidvalidity).await?); let mut cache = self.mailboxes.lock().unwrap(); diff --git a/aero-proto/src/dav.rs b/aero-proto/src/dav.rs index 0ef615a..3420f86 100644 --- a/aero-proto/src/dav.rs +++ b/aero-proto/src/dav.rs @@ -27,6 +27,8 @@ use aero_dav::acltypes as acl; use aero_dav::realization::{All, self as all}; use aero_dav::xml as dxml; +type ArcUser = std::sync::Arc; + pub struct Server { bind_addr: SocketAddr, login_provider: ArcLoginProvider, @@ -359,7 +361,15 @@ async fn propfind(user: std::sync::Arc, req: Request, base_node: async fn report(user: std::sync::Arc, req: Request, node: Box) -> Result>> { let status = hyper::StatusCode::from_u16(207)?; - let report = deserialize::>(req).await?; + let report = match deserialize::>(req).await { + Ok(v) => v, + Err(e) => { + tracing::error!(err=?e, "unable to decode REPORT body"); + return Ok(Response::builder() + .status(400) + .body(text_body("Bad request"))?) + } + }; // Multiget is really like a propfind where Depth: 0|1|Infinity is replaced by an arbitrary // list of URLs @@ -492,7 +502,6 @@ async fn deserialize>(req: Request) -> Result { //--- -type ArcUser = std::sync::Arc; trait DavNode: Send { // ------- specialized logic diff --git a/aero-proto/src/imap/index.rs b/aero-proto/src/imap/index.rs index 3de46be..afe6991 100644 --- a/aero-proto/src/imap/index.rs +++ b/aero-proto/src/imap/index.rs @@ -4,7 +4,7 @@ use anyhow::{anyhow, Result}; use imap_codec::imap_types::sequence::{SeqOrUid, Sequence, SequenceSet}; use aero_collections::mail::uidindex::{ImapUid, ModSeq, UidIndex}; -use aero_collections::mail::unique_ident::UniqueIdent; +use aero_collections::unique_ident::UniqueIdent; pub struct Index<'a> { pub imap_index: Vec>, diff --git a/aero-proto/src/imap/mailbox_view.rs b/aero-proto/src/imap/mailbox_view.rs index 5154359..0ef33d6 100644 --- a/aero-proto/src/imap/mailbox_view.rs +++ b/aero-proto/src/imap/mailbox_view.rs @@ -17,7 +17,7 @@ use aero_collections::mail::mailbox::Mailbox; use aero_collections::mail::query::QueryScope; use aero_collections::mail::snapshot::FrozenMailbox; use aero_collections::mail::uidindex::{ImapUid, ImapUidvalidity, ModSeq}; -use aero_collections::mail::unique_ident::UniqueIdent; +use aero_collections::unique_ident::UniqueIdent; use crate::imap::attributes::AttributesProxy; use crate::imap::flags;