From adf6176a8ff78b8ea557c9ca911e5e89d56c6c29 Mon Sep 17 00:00:00 2001 From: Mauro D Date: Tue, 5 Jul 2022 18:10:32 +0000 Subject: [PATCH] Moved Session inside Arc<> --- Cargo.toml | 3 ++- src/client.rs | 37 +++++++++++++++++++++---------------- src/client_ws.rs | 3 ++- src/core/query.rs | 2 +- src/core/request.rs | 11 ++++++++--- src/event_source/stream.rs | 2 +- src/mailbox/get.rs | 4 ++-- src/mailbox/mod.rs | 2 +- 8 files changed, 38 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ba54ebc..cdedf8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ async-stream = "0.3" base64 = "0.13" tokio-tungstenite = { version = "0.17", features = ["rustls-tls-webpki-roots"], optional = true} tokio = { version = "1.16", default-features = false, features = ["io-util"], optional = true } +parking_lot = "0.12.0" [features] default = [] @@ -28,4 +29,4 @@ websockets = ["tokio", "tokio-tungstenite"] debug = [] [profile.bench] -debug = true \ No newline at end of file +debug = true diff --git a/src/client.rs b/src/client.rs index b9c0094..b8a038a 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,5 +1,8 @@ use std::{ - sync::atomic::{AtomicBool, Ordering}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, time::Duration, }; @@ -20,7 +23,7 @@ use crate::{ }; const DEFAULT_TIMEOUT_MS: u64 = 10 * 1000; -static USER_AGENT: &str = concat!("stalwart-jmap/", env!("CARGO_PKG_VERSION")); +static USER_AGENT: &str = concat!("jmap-client/", env!("CARGO_PKG_VERSION")); pub enum Credentials { Basic(String), @@ -28,17 +31,21 @@ pub enum Credentials { } pub struct Client { - session: Session, + session: parking_lot::Mutex>, session_url: String, + api_url: String, session_updated: AtomicBool, - #[cfg(feature = "websockets")] - pub(crate) authorization: String, + upload_url: Vec>, download_url: Vec>, event_source_url: Vec>, - timeout: u64, + headers: header::HeaderMap, default_account_id: String, + timeout: u64, + + #[cfg(feature = "websockets")] + pub(crate) authorization: String, #[cfg(feature = "websockets")] pub(crate) ws: tokio::sync::Mutex>, } @@ -89,7 +96,8 @@ impl Client { download_url: URLPart::parse(session.download_url())?, upload_url: URLPart::parse(session.upload_url())?, event_source_url: URLPart::parse(session.event_source_url())?, - session, + api_url: session.api_url().to_string(), + session: parking_lot::Mutex::new(Arc::new(session)), session_url: url.to_string(), session_updated: true.into(), #[cfg(feature = "websockets")] @@ -111,8 +119,8 @@ impl Client { self.timeout } - pub fn session(&self) -> &Session { - &self.session + pub fn session(&self) -> Arc { + self.session.lock().clone() } pub fn session_url(&self) -> &str { @@ -136,7 +144,7 @@ impl Client { .timeout(Duration::from_millis(self.timeout)) .default_headers(self.headers.clone()) .build()? - .post(self.session.api_url()) + .post(&self.api_url) .body(serde_json::to_string(&request)?) .send() .await?, @@ -146,14 +154,14 @@ impl Client { .await?, )?; - if response.session_state() != self.session.state() { + if response.session_state() != self.session.lock().state() { self.session_updated.store(false, Ordering::Relaxed); } Ok(response) } - pub async fn refresh_session(&mut self) -> crate::Result<()> { + pub async fn refresh_session(&self) -> crate::Result<()> { let session: Session = serde_json::from_slice( &Client::handle_error( reqwest::Client::builder() @@ -168,10 +176,7 @@ impl Client { .bytes() .await?, )?; - self.download_url = URLPart::parse(session.download_url())?; - self.upload_url = URLPart::parse(session.upload_url())?; - self.event_source_url = URLPart::parse(session.event_source_url())?; - self.session = session; + *self.session.lock() = Arc::new(session); self.session_updated.store(true, Ordering::Relaxed); Ok(()) } diff --git a/src/client_ws.rs b/src/client_ws.rs index 237e21c..6f76023 100644 --- a/src/client_ws.rs +++ b/src/client_ws.rs @@ -154,7 +154,8 @@ impl Client { pub async fn connect_ws( &self, ) -> crate::Result>>>> { - let capabilities = self.session().websocket_capabilities().ok_or_else(|| { + let session = self.session(); + let capabilities = session.websocket_capabilities().ok_or_else(|| { crate::Error::Internal( "JMAP server does not advertise any websocket capabilities.".to_string(), ) diff --git a/src/core/query.rs b/src/core/query.rs index 1f8fa0e..1b94536 100644 --- a/src/core/query.rs +++ b/src/core/query.rs @@ -63,7 +63,7 @@ pub struct FilterOperator { conditions: Vec>, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq)] pub enum Operator { #[serde(rename = "AND")] And, diff --git a/src/core/request.rs b/src/core/request.rs index c54451e..e13c208 100644 --- a/src/core/request.rs +++ b/src/core/request.rs @@ -35,7 +35,7 @@ pub struct Request<'x> { #[serde(skip)] client: &'x Client, #[serde(skip)] - default_account_id: String, + account_id: String, pub using: Vec, @@ -421,11 +421,16 @@ impl<'x> Request<'x> { using: vec![URI::Core, URI::Mail], method_calls: vec![], created_ids: None, - default_account_id: client.default_account_id().to_string(), + account_id: client.default_account_id().to_string(), client, } } + pub fn account_id(mut self, account_id: impl Into) -> Self { + self.account_id = account_id.into(); + self + } + pub async fn send(self) -> crate::Result> { self.client.send(&self).await } @@ -452,7 +457,7 @@ impl<'x> Request<'x> { pub fn params(&self, method: Method) -> RequestParams { RequestParams { - account_id: self.default_account_id.clone(), + account_id: self.account_id.clone(), method, call_id: self.method_calls.len(), } diff --git a/src/event_source/stream.rs b/src/event_source/stream.rs index 7e83cb5..0187b6e 100644 --- a/src/event_source/stream.rs +++ b/src/event_source/stream.rs @@ -8,7 +8,7 @@ use super::Changes; impl Client { pub async fn event_source( - &mut self, + &self, mut types: Option>, close_after_state: bool, ping: Option, diff --git a/src/mailbox/get.rs b/src/mailbox/get.rs index d9cad9c..fe80859 100644 --- a/src/mailbox/get.rs +++ b/src/mailbox/get.rs @@ -13,8 +13,8 @@ impl Mailbox { self.id.unwrap() } - pub fn name(&self) -> &str { - self.name.as_ref().unwrap() + pub fn name(&self) -> Option<&str> { + self.name.as_deref() } pub fn parent_id(&self) -> Option<&str> { diff --git a/src/mailbox/mod.rs b/src/mailbox/mod.rs index 80d41fd..d1398f0 100644 --- a/src/mailbox/mod.rs +++ b/src/mailbox/mod.rs @@ -96,7 +96,7 @@ pub struct Mailbox { acl_patch: Option>>, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum Role { #[serde(rename = "archive", alias = "ARCHIVE")]