JMAP eventsource WIP
parent
c5a99a9cf9
commit
2a001ee2ef
|
@ -28,6 +28,7 @@ use crate::email::*;
|
|||
use crate::error::{MeliError, Result};
|
||||
use fnv::FnvHashMap;
|
||||
use reqwest::blocking::Client;
|
||||
use reqwest::Url;
|
||||
use std::collections::BTreeMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
@ -75,6 +76,7 @@ pub mod mailbox;
|
|||
use mailbox::*;
|
||||
|
||||
pub mod eventsource;
|
||||
use eventsource::client::EventSourceClient;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EnvelopeCache {
|
||||
|
@ -236,9 +238,39 @@ impl MailBackend for JmapType {
|
|||
fn watch(
|
||||
&self,
|
||||
_sender: RefreshEventConsumer,
|
||||
_work_context: WorkContext,
|
||||
work_context: WorkContext,
|
||||
) -> Result<std::thread::ThreadId> {
|
||||
Err(MeliError::from("JMAP watch for updates is unimplemented"))
|
||||
let connection = JmapConnection::new(&self.server_conf, self.online.clone())?;
|
||||
|
||||
let handle = std::thread::Builder::new()
|
||||
.name(format!("{} jmap connection", self.account_name.as_str(),))
|
||||
.spawn(move || {
|
||||
let thread = std::thread::current();
|
||||
work_context
|
||||
.set_status
|
||||
.send((thread.id(), "watching".to_string()))
|
||||
.unwrap();
|
||||
|
||||
let event_source_url = connection.session.event_source_url.clone();
|
||||
debug!(&event_source_url);
|
||||
let client = EventSourceClient::new(
|
||||
Url::parse(&event_source_url).unwrap(),
|
||||
vec![
|
||||
(
|
||||
"types".to_string(),
|
||||
"Email,EmailDelivery,Mailbox".to_string(),
|
||||
),
|
||||
("closeafter".to_string(), "no".to_string()),
|
||||
("ping".to_string(), "1".to_string()),
|
||||
],
|
||||
connection,
|
||||
);
|
||||
for event in client {
|
||||
debug!(&event);
|
||||
println!("{}", event.unwrap());
|
||||
}
|
||||
})?;
|
||||
Ok(handle.thread().id())
|
||||
}
|
||||
|
||||
fn mailboxes(&self) -> Result<FnvHashMap<MailboxHash, Mailbox>> {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
//! # Reqwest-based EventSource client
|
||||
|
||||
use super::event::{parse_event_line, Event, ParseResult};
|
||||
use crate::backends::jmap::JmapConnection;
|
||||
use crate::error::*;
|
||||
use reqwest;
|
||||
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE};
|
||||
|
@ -56,10 +57,11 @@ impl MeliError {
|
|||
/// A client for a Server-Sent Events endpoint.
|
||||
///
|
||||
/// Read events by iterating over the client.
|
||||
pub struct Client {
|
||||
client: reqwest::blocking::Client,
|
||||
pub struct EventSourceClient {
|
||||
connection: JmapConnection,
|
||||
response: Option<BufReader<reqwest::blocking::Response>>,
|
||||
url: reqwest::Url,
|
||||
query: Vec<(String, String)>,
|
||||
last_event_id: Option<String>,
|
||||
last_try: Option<Instant>,
|
||||
|
||||
|
@ -68,15 +70,23 @@ pub struct Client {
|
|||
pub retry: Duration,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
impl EventSourceClient {
|
||||
/// Constructs a new EventSource client for the given URL.
|
||||
///
|
||||
/// This does not start an HTTP request.
|
||||
pub fn new(url: reqwest::Url) -> Client {
|
||||
Client {
|
||||
client: reqwest::blocking::Client::new(),
|
||||
pub fn new(
|
||||
url: reqwest::Url,
|
||||
query: Vec<(String, String)>,
|
||||
connection: JmapConnection,
|
||||
) -> EventSourceClient {
|
||||
debug!("&url = {:#?}", &url);
|
||||
debug!("&connection.session = {:#?}", &connection.session);
|
||||
debug!("&connection.server_conf = {:#?}", &connection.server_conf);
|
||||
EventSourceClient {
|
||||
connection,
|
||||
response: None,
|
||||
url: url,
|
||||
url,
|
||||
query,
|
||||
last_event_id: None,
|
||||
last_try: None,
|
||||
retry: Duration::from_millis(DEFAULT_RETRY),
|
||||
|
@ -90,7 +100,20 @@ impl Client {
|
|||
headers.insert("Last-Event-ID", HeaderValue::from_str(id).unwrap());
|
||||
}
|
||||
|
||||
let res = self.client.get(self.url.clone()).headers(headers).send()?;
|
||||
let res = debug!(self
|
||||
.connection
|
||||
.client
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(self.url.clone())
|
||||
.basic_auth(
|
||||
&self.connection.server_conf.server_username,
|
||||
Some(&self.connection.server_conf.server_password),
|
||||
)
|
||||
.query(&self.query)
|
||||
.headers(headers))
|
||||
.send()?;
|
||||
debug!(&res);
|
||||
|
||||
// Check status code and Content-Type.
|
||||
{
|
||||
|
@ -128,7 +151,7 @@ macro_rules! try_option {
|
|||
/// Iterate over the client to get events.
|
||||
///
|
||||
/// HTTP requests are made transparently while iterating.
|
||||
impl Iterator for Client {
|
||||
impl Iterator for EventSourceClient {
|
||||
type Item = Result<Event>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<Event>> {
|
||||
|
|
Loading…
Reference in New Issue