diff --git a/src/elastic/Cargo.toml b/src/elastic/Cargo.toml index e5fce24a7b..661a4a9334 100644 --- a/src/elastic/Cargo.toml +++ b/src/elastic/Cargo.toml @@ -16,9 +16,22 @@ appveyor = { repository = "elastic-rs/elastic" } [features] default = [ + "sync_sender", + "async_sender", "geo-types" ] +sync_sender = [ + "reqwest" +] + +async_sender = [ + "reqwest", + "futures", + "tokio", + "tokio-threadpool" +] + rustls-tls = [ "reqwest/rustls-tls" ] @@ -40,16 +53,16 @@ quick-error = "~1" error-chain = "~0.11" log = "~0.4" uuid = { version = "~0.7", features = [ "v4" ] } -url = "~2" +url = "~1" bytes = "~0.4" http = "~0.1" serde = "~1" serde_json = "~1" serde_derive = "~1" -reqwest = { version = "~0.9", default-features = false } -futures = "~0.1" -tokio = "~0.1" -tokio-threadpool = "~0.1" +reqwest = { version = "~0.9", optional = true, default-features = false } +futures = { version = "~0.1", optional = true } +tokio = { version = "~0.1", optional = true } +tokio-threadpool = { version = "~0.1", optional = true } fluent_builder = "~0.6" crossbeam-channel = "~0.3" chrono = { version = "~0.4.0", features = [ "serde" ]} diff --git a/src/elastic/src/client/asynchronous.rs b/src/elastic/src/client/asynchronous.rs index e9d18f7d7b..b88a47ed0f 100644 --- a/src/elastic/src/client/asynchronous.rs +++ b/src/elastic/src/client/asynchronous.rs @@ -291,7 +291,7 @@ impl AsyncClientBuilder { pre_send: self.pre_send, }; - let addresses = self.nodes.build(params, sender.clone()); + let addresses = self.nodes.build(params); Ok(AsyncClient { sender, addresses }) } diff --git a/src/elastic/src/client/mod.rs b/src/elastic/src/client/mod.rs index b2c2cb2a21..d9e2d5c0c5 100644 --- a/src/elastic/src/client/mod.rs +++ b/src/elastic/src/client/mod.rs @@ -543,13 +543,15 @@ For more details see the [`responses`][responses-mod] module. pub mod requests; pub mod responses; +#[cfg(feature="async_sender")] mod asynchronous; +#[cfg(feature="sync_sender")] mod synchronous; -pub use self::{ - asynchronous::*, - synchronous::*, -}; +#[cfg(feature="async_sender")] +pub use self::asynchronous::*; +#[cfg(feature="sync_sender")] +pub use self::synchronous::*; #[doc(inline)] pub use crate::http::sender::{ @@ -615,7 +617,7 @@ tokio::runtime::current_thread::block_on_all(response_future)?; #[derive(Clone)] pub struct Client { sender: TSender, - addresses: NodeAddresses, + addresses: NodeAddresses, } impl Client @@ -644,6 +646,16 @@ where index: index.into(), } } + + /** + Creates a new client with a manually created sender and list of node addresses. + */ + pub fn from_sender(sender: TSender, addresses: NodeAddresses) -> Self { + Self { + sender, + addresses, + } + } } /** @@ -674,10 +686,18 @@ pub mod prelude { pub use super::{ requests::prelude::*, responses::prelude::*, - AsyncClient, - AsyncClientBuilder, PreRequestParams, RequestParams, + }; + + #[cfg(feature="async_sender")] + pub use super::{ + AsyncClient, + AsyncClientBuilder, + }; + + #[cfg(feature="sync_sender")] + pub use super::{ SyncClient, SyncClientBuilder, }; diff --git a/src/elastic/src/client/requests/bulk/mod.rs b/src/elastic/src/client/requests/bulk/mod.rs index 8923af425f..61e260833e 100644 --- a/src/elastic/src/client/requests/bulk/mod.rs +++ b/src/elastic/src/client/requests/bulk/mod.rs @@ -8,10 +8,10 @@ use std::{ error::Error as StdError, fmt, marker::PhantomData, - time::Duration, }; +#[cfg(feature="async_sender")] +use std::time::Duration; -use futures::Future; use serde::{ de::DeserializeOwned, ser::Serialize, @@ -20,8 +20,7 @@ use serde::{ use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::{ @@ -29,7 +28,6 @@ use crate::{ BulkResponse, }, Client, - RequestParams, }, endpoints::BulkRequest, error::{ @@ -38,13 +36,7 @@ use crate::{ }, http::{ receiver::IsOk, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, - AsyncBody, - SyncBody, + sender::Sender, }, params::{ Index, @@ -53,6 +45,12 @@ use crate::{ types::document::DEFAULT_DOC_TYPE, }; +#[cfg(feature="async_sender")] +use crate::{ + client::RequestParams, + http::sender::AsyncSender, +}; + /** A [bulk request][docs-bulk] builder that can be configured before sending. @@ -71,12 +69,13 @@ pub type BulkRequestBuilder = RequestBuilder>; mod operation; +#[cfg(feature="async_sender")] mod stream; -pub use self::{ - operation::*, - stream::*, -}; +pub use self::operation::*; + +#[cfg(feature="async_sender")] +pub use self::stream::*; #[doc(hidden)] pub struct BulkRequestInner { @@ -86,6 +85,33 @@ pub struct BulkRequestInner { _marker: PhantomData, } +impl RequestInner for BulkRequestInner +where + TBody: BulkBody + Send + 'static, + TResponse: IsOk + DeserializeOwned + Send + 'static, +{ + type Request = BulkRequest<'static, TBody>; + type Response = TResponse; + + fn into_request(self) -> Result { + let body = self.body.try_into_inner()?; + + match (self.index, self.ty) { + (Some(index), ty) => match ty { + None => Ok(BulkRequest::for_index(index, body)), + Some(ref ty) if &ty[..] == DEFAULT_DOC_TYPE => { + Ok(BulkRequest::for_index(index, body)) + } + Some(ty) => Ok(BulkRequest::for_index_ty(index, ty, body)), + }, + (None, None) => Ok(BulkRequest::new(body)), + (None, Some(_)) => Err(error::request(BulkRequestError( + "missing `index` parameter".to_owned(), + ))), + } + } +} + /** # Bulk request */ @@ -165,6 +191,7 @@ where /** # Bulk stream request */ +#[cfg(feature="async_sender")] impl Client { /** Create a [`BulkRequestBuilder`][BulkRequestBuilder] with this `Client` that can be configured before sending. @@ -451,6 +478,7 @@ where Configure a `SearchRequestBuilder` before sending it. */ +#[cfg(feature="async_sender")] impl BulkRequestBuilder, TResponse> { /** Specify a timeout for filling up the request buffer. @@ -515,178 +543,22 @@ impl BulkRequestBuilder, } } -impl BulkRequestInner -where - TBody: BulkBody, -{ - fn into_request(self) -> Result, Error> { - let body = self.body.try_into_inner()?; - - match (self.index, self.ty) { - (Some(index), ty) => match ty { - None => Ok(BulkRequest::for_index(index, body)), - Some(ref ty) if &ty[..] == DEFAULT_DOC_TYPE => { - Ok(BulkRequest::for_index(index, body)) - } - Some(ty) => Ok(BulkRequest::for_index_ty(index, ty, body)), - }, - (None, None) => Ok(BulkRequest::new(body)), - (None, Some(_)) => Err(error::request(BulkRequestError( - "missing `index` parameter".to_owned(), - ))), - } - } -} - -/** -# Send synchronously -*/ -impl BulkRequestBuilder -where - TBody: Into + BulkBody + Send + 'static, - TResponse: DeserializeOwned + IsOk + Send + 'static, -{ - /** - Send a `BulkRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Send a bulk request to index some documents: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # } - # let client = SyncClientBuilder::new().build()?; - let ops = (0..1000) - .into_iter() - .map(|i| bulk::().index(MyType { - id: i.to_string(), - title: "some string value".into() - }) - .id(i)); - - let response = client.bulk() - .index("myindex") - .ty(MyType::static_ty()) - .extend(ops) - .send()?; - - for op in response { - match op { - Ok(op) => println!("ok: {:?}", op), - Err(op) => println!("err: {:?}", op), - } - } - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request()?; - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl BulkRequestBuilder -where - TBody: Into + BulkBody + Send + 'static, - TResponse: DeserializeOwned + IsOk + Send + 'static, -{ - /** - Send a `BulkRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised search response. - - # Examples - - Send a bulk request to index some documents: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # } - # let client = AsyncClientBuilder::new().build()?; - let ops = (0..1000) - .into_iter() - .map(|i| bulk::().index(MyType { - id: i.to_string(), - title: "some string value".into() - }) - .id(i)); - - let future = client.bulk() - .index("myindex") - .ty(MyType::static_ty()) - .extend(ops) - .send(); - - future.and_then(|response| { - for op in response { - match op { - Ok(op) => println!("ok: {:?}", op), - Err(op) => println!("err: {:?}", op), - } - } - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let (client, params_builder, inner) = (self.client, self.params_builder, self.inner); - - let req_future = client.sender.maybe_async(move || inner.into_request()); - - let res_future = req_future.and_then(move |req| { - RequestBuilder::new(client, params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()) - }); - - Pending::new(res_future) - } -} - +#[cfg(feature="async_sender")] const DEFAULT_BODY_SIZE: usize = 1024 * 1024 * 5; +#[cfg(feature="async_sender")] const DEFAULT_TIMEOUT_SECS: u64 = 30; /** A streaming bulk request body. */ +#[cfg(feature="async_sender")] pub struct Streamed { body_size: usize, timeout: Duration, _marker: PhantomData, } +#[cfg(feature="async_sender")] impl Streamed { fn new() -> Self { Streamed { @@ -791,9 +663,6 @@ impl BulkBody for Vec { } } -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - #[doc(hidden)] pub trait ChangeIndex { type WithNewIndex; @@ -838,15 +707,10 @@ impl ChangeId for BulkErrorsResponse>(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); diff --git a/src/elastic/src/client/requests/bulk/stream.rs b/src/elastic/src/client/requests/bulk/stream.rs index 35d5545804..7c52ddc6cb 100644 --- a/src/elastic/src/client/requests/bulk/stream.rs +++ b/src/elastic/src/client/requests/bulk/stream.rs @@ -38,7 +38,6 @@ use super::{ BulkOperation, BulkRequestBuilder, BulkRequestInner, - Pending, WrappedBody, }; use crate::{ @@ -52,6 +51,7 @@ use crate::{ Error, }, http::{ + Pending, receiver::IsOk, sender::AsyncSender, }, diff --git a/src/elastic/src/client/requests/document_delete.rs b/src/elastic/src/client/requests/document_delete.rs index 0041d7e9ee..874ec787ab 100644 --- a/src/elastic/src/client/requests/document_delete.rs +++ b/src/elastic/src/client/requests/document_delete.rs @@ -4,14 +4,12 @@ Builders for [delete document requests][docs-delete]. [docs-delete]: http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html */ -use futures::Future; use std::marker::PhantomData; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::DeleteResponse, @@ -19,11 +17,7 @@ use crate::{ }, endpoints::DeleteRequest, error::Error, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::{ Id, Index, @@ -59,6 +53,15 @@ pub struct DeleteRequestInner { _marker: PhantomData, } +impl RequestInner for DeleteRequestInner { + type Request = DeleteRequest<'static>; + type Response = DeleteResponse; + + fn into_request(self) -> Result { + Ok(DeleteRequest::for_index_ty_id(self.index, self.ty, self.id)) + } +} + /** # Delete document request */ @@ -116,8 +119,8 @@ where RequestBuilder::initial( self.inner, DeleteRequestInner { - index, - ty, + index: index, + ty: ty, id: id.into(), _marker: PhantomData, }, @@ -180,12 +183,6 @@ where } } -impl DeleteRequestInner { - fn into_request(self) -> DeleteRequest<'static> { - DeleteRequest::for_index_ty_id(self.index, self.ty, self.id) - } -} - /** # Builder methods @@ -208,120 +205,13 @@ where } } -/** -# Send synchronously -*/ -impl DeleteRequestBuilder { - /** - Send a `DeleteRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Delete a [`DocumentType`][documents-mod] called `MyType` with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # pub timestamp: Date - # } - # let client = SyncClientBuilder::new().build()?; - let response = client.document::() - .delete(1) - .send()?; - - assert!(response.deleted()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - [documents-mod]: ../types/document/index.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl DeleteRequestBuilder { - /** - Send a `DeleteRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised delete document response. - - # Examples - - Delete a [`DocumentType`][documents-mod] called `MyType` with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_json; - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use serde_json::Value; - # use futures::Future; - # use elastic::prelude::*; - # #[derive(ElasticType)] - # struct MyType { } - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.document::() - .delete(1) - .ty("mytype") - .send(); - - future.and_then(|response| { - assert!(response.deleted()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - [documents-mod]: ../types/document/index.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[derive(ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} @@ -334,7 +224,8 @@ mod tests { .document::() .delete("1") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/testdoc/_doc/1", req.url.as_ref()); } @@ -348,7 +239,8 @@ mod tests { .delete("1") .index("new-idx") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/new-idx/_doc/1", req.url.as_ref()); } @@ -362,7 +254,8 @@ mod tests { .delete("1") .ty("new-ty") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/testdoc/new-ty/1", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/document_get.rs b/src/elastic/src/client/requests/document_get.rs index 5de7e45dab..a992059b61 100644 --- a/src/elastic/src/client/requests/document_get.rs +++ b/src/elastic/src/client/requests/document_get.rs @@ -4,15 +4,13 @@ Builders for [get document requests][docs-get]. [docs-get]: http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html */ -use futures::Future; use serde::de::DeserializeOwned; use std::marker::PhantomData; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::GetResponse, @@ -20,11 +18,7 @@ use crate::{ }, endpoints::GetRequest, error::Error, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::{ Id, Index, @@ -60,6 +54,18 @@ pub struct GetRequestInner { _marker: PhantomData, } +impl RequestInner for GetRequestInner +where + TDocument: DeserializeOwned + Send + 'static, +{ + type Request = GetRequest<'static>; + type Response = GetResponse; + + fn into_request(self) -> Result { + Ok(GetRequest::for_index_ty_id(self.index, self.ty, self.id)) + } +} + /** # Get document request */ @@ -179,12 +185,6 @@ where } } -impl GetRequestInner { - fn into_request(self) -> GetRequest<'static> { - GetRequest::for_index_ty_id(self.index, self.ty, self.id) - } -} - /** # Builder methods @@ -207,127 +207,13 @@ where } } -/** -# Send synchronously -*/ -impl GetRequestBuilder -where - TDocument: DeserializeOwned, -{ - /** - Send a `GetRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Get a [`DocumentType`][documents-mod] called `MyType` with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_json; - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use serde_json::Value; - # use elastic::prelude::*; - # #[derive(Debug, ElasticType, Deserialize)] - # struct MyType { } - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.document::() - .get(1) - .send()?; - - if let Some(doc) = response.into_document() { - println!("{:?}", doc); - } - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - [documents-mod]: ../types/document/index.html - */ - pub fn send(self) -> Result, Error> { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl GetRequestBuilder -where - TDocument: DeserializeOwned + Send + 'static, -{ - /** - Send a `GetRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised get document response. - - # Examples - - Get a [`DocumentType`][documents-mod] called `MyType` with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_json; - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use serde_json::Value; - # use futures::Future; - # use elastic::prelude::*; - # #[derive(Debug, ElasticType, Deserialize)] - # struct MyType { } - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.document::() - .get(1) - .send(); - - future.and_then(|response| { - if let Some(doc) = response.into_document() { - println!("{:?}", doc); - } - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - [documents-mod]: ../types/document/index.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending>; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::>(); - } - #[derive(Deserialize, ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} @@ -336,7 +222,7 @@ mod tests { fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.document::().get("1").inner.into_request(); + let req = client.document::().get("1").inner.into_request().unwrap(); assert_eq!("/testdoc/_doc/1", req.url.as_ref()); } @@ -350,7 +236,8 @@ mod tests { .get("1") .index("new-idx") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/new-idx/_doc/1", req.url.as_ref()); } @@ -364,7 +251,8 @@ mod tests { .get("1") .ty("new-ty") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/testdoc/new-ty/1", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/document_index.rs b/src/elastic/src/client/requests/document_index.rs index 679a6ba407..20924e94a8 100644 --- a/src/elastic/src/client/requests/document_index.rs +++ b/src/elastic/src/client/requests/document_index.rs @@ -4,15 +4,13 @@ Builders for [index requests][docs-index]. [docs-index]: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html */ -use futures::Future; use serde::Serialize; use serde_json; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::IndexResponse, @@ -23,11 +21,7 @@ use crate::{ self, Error, }, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::{ Id, Index, @@ -61,6 +55,25 @@ pub struct IndexRequestInner { doc: TDocument, } +impl RequestInner for IndexRequestInner +where + TDocument: Serialize, +{ + type Request = IndexRequest<'static, Vec>; + type Response = IndexResponse; + + fn into_request(self) -> Result { + let body = serde_json::to_vec(&self.doc).map_err(error::request)?; + + let request = match self.id { + Some(id) => IndexRequest::for_index_ty_id(self.index, self.ty, id, body), + None => IndexRequest::for_index_ty(self.index, self.ty, body), + }; + + Ok(request) + } +} + /** # Index document request */ @@ -199,22 +212,6 @@ where } } -impl IndexRequestInner -where - TDocument: Serialize, -{ - fn into_request(self) -> Result>, Error> { - let body = serde_json::to_vec(&self.doc).map_err(error::request)?; - - let request = match self.id { - Some(id) => IndexRequest::for_index_ty_id(self.index, self.ty, id, body), - None => IndexRequest::for_index_ty(self.index, self.ty, body), - }; - - Ok(request) - } -} - /** # Builder methods @@ -243,140 +240,13 @@ where } } -/** -# Send synchronously -*/ -impl IndexRequestBuilder -where - TDocument: Serialize, -{ - /** - Send a `IndexRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Index a document with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # pub timestamp: Date - # } - # let client = SyncClientBuilder::new().build()?; - let doc = MyType { - id: "1".to_owned(), - title: String::from("A title"), - timestamp: Date::now() - }; - - let response = client.document() - .index(doc) - .send()?; - - assert!(response.created()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request()?; - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexRequestBuilder -where - TDocument: Serialize + Send + 'static, -{ - /** - Send a `IndexRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised index response. - - # Examples - - Index a document with an id of `1`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # pub timestamp: Date - # } - # let client = AsyncClientBuilder::new().build()?; - let doc = MyType { - id: "1".to_owned(), - title: String::from("A title"), - timestamp: Date::now() - }; - - let future = client.document() - .index(doc) - .send(); - - future.and_then(|response| { - assert!(response.created()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let (client, params_builder, inner) = (self.client, self.params_builder, self.inner); - - let req_future = client.sender.maybe_async(move || inner.into_request()); - - let res_future = req_future.and_then(move |req| { - RequestBuilder::new(client, params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()) - }); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[derive(Serialize, ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} diff --git a/src/elastic/src/client/requests/document_put_mapping.rs b/src/elastic/src/client/requests/document_put_mapping.rs index cf6a7c2c9c..83896e3b4a 100644 --- a/src/elastic/src/client/requests/document_put_mapping.rs +++ b/src/elastic/src/client/requests/document_put_mapping.rs @@ -4,15 +4,13 @@ Builders for [put mapping requests][docs-mapping]. [docs-mapping]: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html */ -use futures::Future; use serde_json; use std::marker::PhantomData; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::CommandResponse, @@ -23,11 +21,7 @@ use crate::{ self, Error, }, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::{ Index, Type, @@ -61,6 +55,26 @@ pub struct PutMappingRequestInner { _marker: PhantomData, } +impl RequestInner for PutMappingRequestInner +where + TDocument: DocumentType, +{ + type Request = IndicesPutMappingRequest<'static, Vec>; + type Response = CommandResponse; + + fn into_request(self) -> Result { + let body = serde_json::to_vec(&TDocument::index_mapping()).map_err(error::request)?; + + if &self.ty[..] == DEFAULT_DOC_TYPE { + Ok(IndicesPutMappingRequest::for_index(self.index, body)) + } else { + Ok(IndicesPutMappingRequest::for_index_ty( + self.index, self.ty, body, + )) + } + } +} + /** # Put mapping request */ @@ -125,23 +139,6 @@ where } } -impl PutMappingRequestInner -where - TDocument: DocumentType, -{ - fn into_request(self) -> Result>, Error> { - let body = serde_json::to_vec(&TDocument::index_mapping()).map_err(error::request)?; - - if &self.ty[..] == DEFAULT_DOC_TYPE { - Ok(IndicesPutMappingRequest::for_index(self.index, body)) - } else { - Ok(IndicesPutMappingRequest::for_index_ty( - self.index, self.ty, body, - )) - } - } -} - /** # Builder methods @@ -164,124 +161,17 @@ where } } -/** -# Send synchronously -*/ -impl PutMappingRequestBuilder -where - TDocument: DocumentType, -{ - /** - Send a `PutMappingRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Put the mapping for a document type called `MyType`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = SyncClientBuilder::new().build()?; - let response = client.document::() - .put_mapping() - .send()?; - - assert!(response.acknowledged()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request()?; - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl PutMappingRequestBuilder -where - TDocument: DocumentType + Send + 'static, -{ - /** - Send a `PutMappingRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Put the mapping for a document type called `MyType`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = AsyncClientBuilder::new().build()?; - let future = client.document::() - .put_mapping() - .send(); - - future.and_then(|response| { - assert!(response.acknowledged()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let (client, params_builder, inner) = (self.client, self.params_builder, self.inner); - - let req_future = client.sender.maybe_async(move || inner.into_request()); - - let res_future = req_future.and_then(move |req| { - RequestBuilder::new(client, params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()) - }); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; use serde_json::{ self, Value, }; - #[test] - fn is_send() { - assert_send::(); - } - #[derive(ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} diff --git a/src/elastic/src/client/requests/document_update.rs b/src/elastic/src/client/requests/document_update.rs index 9a472357ae..e2ee67b46d 100644 --- a/src/elastic/src/client/requests/document_update.rs +++ b/src/elastic/src/client/requests/document_update.rs @@ -4,7 +4,6 @@ Builders for [update document requests][docs-update]. [docs-update]: http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html */ -use futures::Future; use serde::ser::Serialize; use serde_json; use std::marker::PhantomData; @@ -12,8 +11,7 @@ use std::marker::PhantomData; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::UpdateResponse, @@ -24,11 +22,7 @@ use crate::{ self, Error, }, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::{ Id, Index, @@ -71,6 +65,22 @@ pub struct UpdateRequestInner { _marker: PhantomData, } +impl RequestInner for UpdateRequestInner +where + TBody: Serialize, +{ + type Request = UpdateRequest<'static, Vec>; + type Response = UpdateResponse; + + fn into_request(self) -> Result>, Error> { + let body = serde_json::to_vec(&self.body).map_err(error::request)?; + + Ok(UpdateRequest::for_index_ty_id( + self.index, self.ty, self.id, body, + )) + } +} + /** # Update document request */ @@ -273,19 +283,6 @@ where } } -impl UpdateRequestInner -where - TBody: Serialize, -{ - fn into_request(self) -> Result>, Error> { - let body = serde_json::to_vec(&self.body).map_err(error::request)?; - - Ok(UpdateRequest::for_index_ty_id( - self.index, self.ty, self.id, body, - )) - } -} - /** # Builder methods @@ -539,12 +536,7 @@ where self.script(builder) } -} -impl UpdateRequestBuilder -where - TSender: Sender, -{ /** Request that the [`UpdateResponse`] include the `source` of the updated document. @@ -602,141 +594,18 @@ where } } -/** -# Send synchronously -*/ -impl UpdateRequestBuilder -where - TBody: Serialize, -{ - /** - Send an `UpdateRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Update a [`DocumentType`][documents-mod] called `MyType` with an id of `1` using a new document value: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # pub timestamp: Date - # } - # let client = SyncClientBuilder::new().build()?; - # let new_doc = MyType { id: "1".to_owned(), title: String::new(), timestamp: Date::now() }; - let response = client.document::() - .update(1) - .doc(new_doc) - .send()?; - - assert!(response.updated()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - [documents-mod]: ../../types/document/index.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request()?; - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl UpdateRequestBuilder -where - TBody: Serialize + Send + 'static, -{ - /** - Send an `UpdateRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised update document response. - - # Examples - - Update a [`DocumentType`][documents-mod] called `MyType` with an id of `1` using a new document value: - - ```no_run - # #[macro_use] extern crate serde_json; - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use serde_json::Value; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Serialize, Deserialize, ElasticType)] - # struct MyType { - # pub id: String, - # pub title: String, - # pub timestamp: Date - # } - # let client = AsyncClientBuilder::new().build()?; - # let new_doc = MyType { id: "1".to_owned(), title: String::new(), timestamp: Date::now() }; - let future = client.document::() - .update(1) - .doc(new_doc) - .send(); - - future.and_then(|response| { - assert!(response.updated()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - [documents-mod]: ../../types/document/index.html - */ - pub fn send(self) -> Pending { - let (client, params_builder, inner) = (self.client, self.params_builder, self.inner); - - let req_future = client.sender.maybe_async(move || inner.into_request()); - - let res_future = req_future.and_then(move |req| { - RequestBuilder::new(client, params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()) - }); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use super::ScriptBuilder; use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; use serde_json::{ self, Value, }; - #[test] - fn is_send() { - assert_send::(); - } - #[derive(Serialize, ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} diff --git a/src/elastic/src/client/requests/index_close.rs b/src/elastic/src/client/requests/index_close.rs index 9b0726b721..a92330d37a 100644 --- a/src/elastic/src/client/requests/index_close.rs +++ b/src/elastic/src/client/requests/index_close.rs @@ -4,13 +4,10 @@ Builders for [close index requests][docs-close-index]. [docs-close-index]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::CommandResponse, @@ -20,11 +17,7 @@ use crate::{ error::Error, http::{ empty_body, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, + sender::Sender, DefaultBody, }, params::Index, @@ -48,6 +41,15 @@ pub struct IndexCloseRequestInner { index: Index<'static>, } +impl RequestInner for IndexCloseRequestInner { + type Request = IndicesCloseRequest<'static, DefaultBody>; + type Response = CommandResponse; + + fn into_request(self) -> Result { + Ok(IndicesCloseRequest::for_index(self.index, empty_body())) + } +} + /** # Close index request */ @@ -88,110 +90,18 @@ where } } -impl IndexCloseRequestInner { - fn into_request(self) -> IndicesCloseRequest<'static, DefaultBody> { - IndicesCloseRequest::for_index(self.index, empty_body()) - } -} - -/** -# Send synchronously -*/ -impl IndexCloseRequestBuilder { - /** - Send an `IndexCloseRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Close an index called `myindex`: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.index("myindex").close().send()?; - - assert!(response.acknowledged()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexCloseRequestBuilder { - /** - Send an `IndexCloseRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Close an index called `myindex`: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.index("myindex").close().send(); - - future.and_then(|response| { - assert!(response.acknowledged()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.index("testindex").close().inner.into_request(); + let req = client.index("testindex").close().inner.into_request().unwrap(); assert_eq!("/testindex/_close", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/index_create.rs b/src/elastic/src/client/requests/index_create.rs index 78f7eecfc8..4d728eca33 100644 --- a/src/elastic/src/client/requests/index_create.rs +++ b/src/elastic/src/client/requests/index_create.rs @@ -4,13 +4,10 @@ Builders for [create index requests][docs-create-index]. [docs-create-index]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::CommandResponse, @@ -20,11 +17,7 @@ use crate::{ error::Error, http::{ empty_body, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, + sender::Sender, DefaultBody, }, params::Index, @@ -50,6 +43,18 @@ pub struct IndexCreateRequestInner { body: TBody, } +impl RequestInner for IndexCreateRequestInner +where + TBody: Send + 'static +{ + type Request = IndicesCreateRequest<'static, TBody>; + type Response = CommandResponse; + + fn into_request(self) -> Result { + Ok(IndicesCreateRequest::for_index(self.index, self.body)) + } +} + /** # Create index request */ @@ -136,12 +141,6 @@ where } } -impl IndexCreateRequestInner { - fn into_request(self) -> IndicesCreateRequest<'static, TBody> { - IndicesCreateRequest::for_index(self.index, self.body) - } -} - /** # Builder methods @@ -172,110 +171,18 @@ where } } -/** -# Send synchronously -*/ -impl IndexCreateRequestBuilder -where - TBody: Into<::Body> + Send + 'static, -{ - /** - Send an `IndexCreateRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Create an index called `myindex`: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.index("myindex").create().send()?; - - assert!(response.acknowledged()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexCreateRequestBuilder -where - TBody: Into<::Body> + Send + 'static, -{ - /** - Send an `IndexCreateRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Create an index called `myindex`: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.index("myindex").create().send(); - - future.and_then(|response| { - assert!(response.acknowledged()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ prelude::*, - tests::*, + client::requests::RequestInner, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.index("testindex").create().inner.into_request(); + let req = client.index("testindex").create().inner.into_request().unwrap(); assert_eq!("/testindex", req.url.as_ref()); } @@ -289,7 +196,8 @@ mod tests { .create() .body("{}") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("{}", req.body); } diff --git a/src/elastic/src/client/requests/index_delete.rs b/src/elastic/src/client/requests/index_delete.rs index 180cbb59e6..69a91af7db 100644 --- a/src/elastic/src/client/requests/index_delete.rs +++ b/src/elastic/src/client/requests/index_delete.rs @@ -4,13 +4,10 @@ Builders for [delete index requests][docs-delete-index]. [docs-delete-index]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-delete-index.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::CommandResponse, @@ -18,11 +15,7 @@ use crate::{ }, endpoints::IndicesDeleteRequest, error::Error, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::Index, }; @@ -44,6 +37,15 @@ pub struct IndexDeleteRequestInner { index: Index<'static>, } +impl RequestInner for IndexDeleteRequestInner { + type Request = IndicesDeleteRequest<'static>; + type Response = CommandResponse; + + fn into_request(self) -> Result { + Ok(IndicesDeleteRequest::for_index(self.index)) + } +} + /** # Delete index request */ @@ -84,110 +86,18 @@ where } } -impl IndexDeleteRequestInner { - fn into_request(self) -> IndicesDeleteRequest<'static> { - IndicesDeleteRequest::for_index(self.index) - } -} - -/** -# Send synchronously -*/ -impl IndexDeleteRequestBuilder { - /** - Send a `IndexDeleteRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Delete an index called `myindex`: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.index("myindex").delete().send()?; - - assert!(response.acknowledged()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexDeleteRequestBuilder { - /** - Send a `IndexDeleteRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Delete an index called `myindex`: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.index("myindex").delete().send(); - - future.and_then(|response| { - assert!(response.acknowledged()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.index("testindex").delete().inner.into_request(); + let req = client.index("testindex").delete().inner.into_request().unwrap(); assert_eq!("/testindex", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/index_exists.rs b/src/elastic/src/client/requests/index_exists.rs index 0018a07fbc..7b105bbfe6 100644 --- a/src/elastic/src/client/requests/index_exists.rs +++ b/src/elastic/src/client/requests/index_exists.rs @@ -4,13 +4,10 @@ Builders for [index exists requests][docs-index-exists]. [docs-index-exists]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::IndicesExistsResponse, @@ -18,11 +15,7 @@ use crate::{ }, endpoints::IndicesExistsRequest, error::Error, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, params::Index, }; @@ -44,6 +37,15 @@ pub struct IndexExistsRequestInner { index: Index<'static>, } +impl RequestInner for IndexExistsRequestInner { + type Request = IndicesExistsRequest<'static>; + type Response = IndicesExistsResponse; + + fn into_request(self) -> Result { + Ok(IndicesExistsRequest::for_index(self.index)) + } +} + /** # Index exists request */ @@ -84,110 +86,18 @@ where } } -impl IndexExistsRequestInner { - fn into_request(self) -> IndicesExistsRequest<'static> { - IndicesExistsRequest::for_index(self.index) - } -} - -/** -# Send synchronously -*/ -impl IndexExistsRequestBuilder { - /** - Send an `IndexExistsRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Check whether an index called `myindex` exists: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.index("myindex").exists().send()?; - - assert!(response.exists()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexExistsRequestBuilder { - /** - Send an `IndexExistsRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Check whether an index called `myindex` exists: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.index("myindex").exists().send(); - - future.and_then(|response| { - assert!(response.exists()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.index("testindex").exists().inner.into_request(); + let req = client.index("testindex").exists().inner.into_request().unwrap(); assert_eq!("/testindex", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/index_open.rs b/src/elastic/src/client/requests/index_open.rs index 98c206b8db..ed6b91db79 100644 --- a/src/elastic/src/client/requests/index_open.rs +++ b/src/elastic/src/client/requests/index_open.rs @@ -4,13 +4,10 @@ Builders for [open index requests][docs-open-index]. [docs-open-index]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::CommandResponse, @@ -20,11 +17,7 @@ use crate::{ error::Error, http::{ empty_body, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, + sender::Sender, DefaultBody, }, params::Index, @@ -48,6 +41,15 @@ pub struct IndexOpenRequestInner { index: Index<'static>, } +impl RequestInner for IndexOpenRequestInner { + type Request = IndicesOpenRequest<'static, DefaultBody>; + type Response = CommandResponse; + + fn into_request(self) -> Result { + Ok(IndicesOpenRequest::for_index(self.index, empty_body())) + } +} + /** # Open index request */ @@ -88,110 +90,18 @@ where } } -impl IndexOpenRequestInner { - fn into_request(self) -> IndicesOpenRequest<'static, DefaultBody> { - IndicesOpenRequest::for_index(self.index, empty_body()) - } -} - -/** -# Send synchronously -*/ -impl IndexOpenRequestBuilder { - /** - Send an `IndexOpenRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Open an index called `myindex`: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.index("myindex").open().send()?; - - assert!(response.acknowledged()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl IndexOpenRequestBuilder { - /** - Send an `IndexOpenRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised command response. - - # Examples - - Open an index called `myindex`: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.index("myindex").open().send(); - - future.and_then(|response| { - assert!(response.acknowledged()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.index("testindex").open().inner.into_request(); + let req = client.index("testindex").open().inner.into_request().unwrap(); assert_eq!("/testindex/_open", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/mod.rs b/src/elastic/src/client/requests/mod.rs index beb1b875f4..327ef631dc 100644 --- a/src/elastic/src/client/requests/mod.rs +++ b/src/elastic/src/client/requests/mod.rs @@ -4,28 +4,33 @@ Request types for the Elasticsearch REST API. This module contains implementation details that are useful if you want to customise the request process, but aren't generally important for sending requests. */ -use std::{ - marker::PhantomData, - sync::Arc, +use fluent_builder::{ + SharedFluentBuilder, + TryIntoValue, }; - -use fluent_builder::SharedFluentBuilder; -use futures::{ - Future, - Poll, -}; - +use serde::de::DeserializeOwned; +#[cfg(feature="async_sender")] +use std::sync::Arc; +#[cfg(feature="async_sender")] use tokio_threadpool::ThreadPool; use crate::{ client::Client, + endpoints::IntoEndpoint, error::Error, - http::sender::{ - AsyncSender, - RequestParams, - Sender, + http::{ + receiver::IsOk, + sender::{ + RequestParams, + SendableRequest, + SendableRequestParams, + Sender, + TypedSender, + }, }, }; +#[cfg(feature="async_sender")] +use crate::http::sender::AsyncSender; pub mod raw; @@ -88,6 +93,29 @@ pub use self::{ pub mod common; +/** +Trait for inner request object, that varies based on what request is being made. + +Note that `RawRequestInner` does _not_ implement this, since it passes the response +as a raw object without deserialization. +*/ +pub trait RequestInner { + /** + Full request type for this request. + */ + type Request: IntoEndpoint<'static> + Send + 'static; + + /** + Type for the response of the request. + */ + type Response: IsOk + DeserializeOwned + Send + 'static; + + /** + Converts this request builder to its corresponding request type. + */ + fn into_request(self) -> Result; +} + /** A builder for a request. @@ -209,11 +237,50 @@ where } } +impl RequestBuilder +where + TReqInner: RequestInner, + TSender: TypedSender, + >::BodyType: Send + Into, +{ + /** + Sends the request. + + The returned object is a `Sender`-implementation-specific handle to the results + of the query. For example, for the `SyncSender` this is a plain `Result`, + while for the `AsyncSender` this is an object implementing `Future`. + + For information on the result type, consult the page for the request. + */ + pub fn send(self) -> TSender::TypedResponse { + let client = self.client; + let params_builder = self.params_builder; + let request_res = self.inner + .into_request() + .map(|req| { + let endpoint = req.into_endpoint(); + + // Only try fetch a next address if an explicit `RequestParams` hasn't been given + let params = match params_builder.try_into_value() { + TryIntoValue::Value(value) => SendableRequestParams::Value(value), + TryIntoValue::Builder(builder) => SendableRequestParams::Builder { + params: client.sender.next_params(&client.addresses), + builder, + }, + }; + + SendableRequest::new(endpoint, params) + }); + client.sender.typed_send(request_res) + } +} + /** # Methods for asynchronous request builders The following methods can be called on any asynchronous request builder. */ +#[cfg(feature="async_sender")] impl RequestBuilder { /** Override the thread pool used for deserialisation for this request. @@ -243,7 +310,8 @@ impl RequestBuilder { # extern crate tokio_threadpool; # use tokio_threadpool::ThreadPool; # use elastic::prelude::*; - # fn main() -> Result<(), Box> { + # fn main() { run().unwrap() } + # fn run() -> Result<(), Box> { # let client = AsyncClientBuilder::new().build()?; # fn get_req() -> PingRequest<'static> { PingRequest::new() } let builder = client.request(get_req()) @@ -259,33 +327,6 @@ impl RequestBuilder { } } -/** A future returned by calling `send`. */ -pub struct Pending { - inner: Box + Send>, - _ph: PhantomData, -} - -impl Pending { - fn new(fut: F) -> Self - where - F: Future + Send + 'static, - { - Pending { - inner: Box::new(fut), - _ph: Default::default(), - } - } -} - -impl Future for Pending { - type Item = T; - type Error = Error; - - fn poll(&mut self) -> Poll { - self.inner.poll() - } -} - pub mod prelude { /*! A glob import for convenience. */ diff --git a/src/elastic/src/client/requests/ping.rs b/src/elastic/src/client/requests/ping.rs index 769117d5b6..01a391f333 100644 --- a/src/elastic/src/client/requests/ping.rs +++ b/src/elastic/src/client/requests/ping.rs @@ -2,13 +2,10 @@ Builders for ping requests. */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::PingResponse, @@ -16,11 +13,7 @@ use crate::{ }, endpoints::PingRequest, error::Error, - http::sender::{ - AsyncSender, - Sender, - SyncSender, - }, + http::sender::Sender, }; /** @@ -38,6 +31,15 @@ pub type PingRequestBuilder = RequestBuilder #[doc(hidden)] pub struct PingRequestInner; +impl RequestInner for PingRequestInner { + type Request = PingRequest<'static>; + type Response = PingResponse; + + fn into_request(self) -> Result { + Ok(PingRequest::new()) + } +} + /** # Ping request */ @@ -82,119 +84,18 @@ where } } -impl PingRequestInner { - fn into_request(self) -> PingRequest<'static> { - PingRequest::new() - } -} - -/** -# Send synchronously -*/ -impl PingRequestBuilder { - /** - Send a `PingRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Ping an Elasticsearch node: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # #[macro_use] extern crate serde_json; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Debug, Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = SyncClientBuilder::new().build()?; - let response = client.ping().send()?; - - println!("node: {}", response.name()); - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl PingRequestBuilder { - /** - Send a `PingRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised ping response. - - # Examples - - Ping an Elasticsearch node: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Debug, Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = AsyncClientBuilder::new().build()?; - let future = client.ping().send(); - - future.and_then(|response| { - println!("node: {}", response.name()); - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.ping().inner.into_request(); + let req = client.ping().inner.into_request().unwrap(); assert_eq!("/", req.url.as_ref()); } diff --git a/src/elastic/src/client/requests/raw.rs b/src/elastic/src/client/requests/raw.rs index fc14ac9180..d8fa75aca9 100644 --- a/src/elastic/src/client/requests/raw.rs +++ b/src/elastic/src/client/requests/raw.rs @@ -12,8 +12,6 @@ use crate::{ }, endpoints::Endpoint, http::sender::{ - NextParams, - NodeAddresses, SendableRequest, SendableRequestParams, Sender, @@ -102,8 +100,6 @@ where TSender: Sender, TEndpoint: Into>, TBody: Into<::Body> + Send + 'static, - NodeAddresses: NextParams, - as NextParams>::Params: Into + Send + 'static, { /** Send a `RawRequestBuilder`. @@ -174,7 +170,7 @@ where let params = match self.params_builder.try_into_value() { TryIntoValue::Value(value) => SendableRequestParams::Value(value), TryIntoValue::Builder(builder) => SendableRequestParams::Builder { - params: client.addresses.next(), + params: client.sender.next_params(&client.addresses), builder, }, }; diff --git a/src/elastic/src/client/requests/search.rs b/src/elastic/src/client/requests/search.rs index e8d10ff484..799f4cbedf 100644 --- a/src/elastic/src/client/requests/search.rs +++ b/src/elastic/src/client/requests/search.rs @@ -4,15 +4,13 @@ Builders for [search requests][docs-search]. [docs-search]: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html */ -use futures::Future; use serde::de::DeserializeOwned; use std::marker::PhantomData; use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::SearchResponse, @@ -23,11 +21,7 @@ use crate::{ error::Error, http::{ empty_body, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, + sender::Sender, DefaultBody, }, params::{ @@ -59,6 +53,24 @@ pub struct SearchRequestInner { _marker: PhantomData, } +impl RequestInner for SearchRequestInner +where + TBody: Send + 'static, + TDocument: DeserializeOwned + Send + 'static, +{ + type Request = SearchRequest<'static, TBody>; + type Response = SearchResponse; + + fn into_request(self) -> Result { + let index = self.index.unwrap_or_else(|| "_all".into()); + + Ok(match self.ty { + Some(ty) => SearchRequest::for_index_ty(index, ty, self.body), + None => SearchRequest::for_index(index, self.body), + }) + } +} + /** # Search request */ @@ -236,15 +248,6 @@ where _marker: PhantomData, } } - - fn into_request(self) -> SearchRequest<'static, TBody> { - let index = self.index.unwrap_or_else(|| "_all".into()); - - match self.ty { - Some(ty) => SearchRequest::for_index_ty(index, ty, self.body), - None => SearchRequest::for_index(index, self.body), - } - } } /** @@ -297,131 +300,15 @@ where } } -/** -# Send synchronously -*/ -impl SearchRequestBuilder -where - TDocument: DeserializeOwned, - TBody: Into<::Body> + Send + 'static, -{ - /** - Send a `SearchRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Run a simple [Query String][docs-querystring] query for a [`DocumentType`][documents-mod] called `MyType`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Debug, Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = SyncClientBuilder::new().build()?; - let response = client.search::() - .index("myindex") - .send()?; - - // Iterate through the hits (of type `MyType`) - for hit in response.hits() { - println!("{:?}", hit); - } - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - [documents-mod]: ../../../types/document/index.html - [docs-querystring]: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html - */ - pub fn send(self) -> Result, Error> { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously -*/ -impl SearchRequestBuilder -where - TDocument: DeserializeOwned + Send + 'static, - TBody: Into<::Body> + Send + 'static, -{ - /** - Send a `SearchRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised search response. - - # Examples - - Run a simple [Query String][docs-querystring] query for a [`DocumentType`][documents-mod] called `MyType`: - - ```no_run - # #[macro_use] extern crate serde_derive; - # #[macro_use] extern crate elastic_derive; - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # #[derive(Debug, Serialize, Deserialize, ElasticType)] - # struct MyType { } - # let client = AsyncClientBuilder::new().build()?; - let future = client.search::() - .index("myindex") - .send(); - - future.and_then(|response| { - // Iterate through the hits (of type `MyType`) - for hit in response.hits() { - println!("{:?}", hit); - } - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - [documents-mod]: ../../../types/document/index.html - [docs-querystring]: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html - */ - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending>; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use serde_json::Value; use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::>(); - } - #[derive(Serialize, ElasticType)] #[elastic(crate_root = "crate::types")] struct TestDoc {} @@ -430,7 +317,7 @@ mod tests { fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.search::().inner.into_request(); + let req = client.search::().inner.into_request().unwrap(); assert_eq!("/_all/_search", req.url.as_ref()); } @@ -443,7 +330,8 @@ mod tests { .search::() .index("new-idx") .inner - .into_request(); + .into_request() + .unwrap(); assert_eq!("/new-idx/_search", req.url.as_ref()); } @@ -452,7 +340,7 @@ mod tests { fn specify_ty() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.search::().ty("new-ty").inner.into_request(); + let req = client.search::().ty("new-ty").inner.into_request().unwrap(); assert_eq!("/_all/new-ty/_search", req.url.as_ref()); } @@ -461,7 +349,7 @@ mod tests { fn specify_body() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.search::().body("{}").inner.into_request(); + let req = client.search::().body("{}").inner.into_request().unwrap(); assert_eq!("{}", req.body); } diff --git a/src/elastic/src/client/requests/sql.rs b/src/elastic/src/client/requests/sql.rs index b074baf029..26228d4b45 100644 --- a/src/elastic/src/client/requests/sql.rs +++ b/src/elastic/src/client/requests/sql.rs @@ -4,13 +4,10 @@ Builders for [sql queries][sql]. [sql]: https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-rest.html */ -use futures::Future; - use crate::{ client::{ requests::{ - raw::RawRequestInner, - Pending as BasePending, + RequestInner, RequestBuilder, }, responses::SqlQueryResponse, @@ -19,11 +16,7 @@ use crate::{ endpoints::SqlQueryRequest, http::{ empty_body, - sender::{ - AsyncSender, - Sender, - SyncSender, - }, + sender::Sender, DefaultBody, }, }; @@ -50,6 +43,18 @@ pub struct SqlRequestInner { body: TBody, } +impl RequestInner for SqlRequestInner +where + TBody: Send + 'static +{ + type Request = SqlQueryRequest<'static, TBody>; + type Response = SqlQueryResponse; + + fn into_request(self) -> Result { + Ok(SqlQueryRequest::new(self.body)) + } +} + /** # Sql request */ @@ -143,10 +148,6 @@ impl SqlRequestInner { fn new(body: TBody) -> Self { SqlRequestInner { body } } - - fn into_request(self) -> SqlQueryRequest<'static, TBody> { - SqlQueryRequest::new(self.body) - } } /** @@ -184,125 +185,18 @@ where } } -/** -# Send synchronously - */ -impl SqlRequestBuilder -where - TBody: Into<::Body> + Send + 'static, -{ - /** - Sends a `SqlRequestBuilder` synchronously using a [`SyncClient`][SyncClient]. - - This will block the current thread until a response arrives and is deserialised. - - # Examples - - Runs a simple [Query String][docs-querystring] query: - - ```no_run - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = SyncClientBuilder::new().build()?; - let response = client.sql_query("SELECT * FROM library GROUP BY author") - .send()?; - - // Iterate through the hits - for row in response.rows() { - for column in row.columns() { - println!("{:?}", column); - } - } - # Ok(()) - # } - ``` - - [SyncClient]: ../../type.SyncClient.html - [docs-querystring]: https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-commands.html - */ - pub fn send(self) -> Result { - let req = self.inner.into_request(); - - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send()? - .into_response() - } -} - -/** -# Send asynchronously - */ -impl SqlRequestBuilder -where - TBody: Into<::Body> + Send + 'static, -{ - /** - Sends a `SqlRequestBuilder` asynchronously using an [`AsyncClient`][AsyncClient]. - - This will return a future that will resolve to the deserialised search response. - - # Examples - - Runs a simple [Query String][docs-querystring] query: - - ```no_run - # use futures::Future; - # use elastic::prelude::*; - # fn main() -> Result<(), Box> { - # let client = AsyncClientBuilder::new().build()?; - let future = client.sql_query("SELECT * FROM library GROUP BY author") - .send(); - - future.and_then(|response| { - // Iterate through the hits - for row in response.rows() { - for column in row.columns() { - println!("{:?}", column); - } - } - - Ok(()) - }); - # Ok(()) - # } - ``` - - [AsyncClient]: ../../type.AsyncClient.html - [docs-querystring]: https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-commands.html - */ - - pub fn send(self) -> Pending { - let req = self.inner.into_request(); - - let res_future = - RequestBuilder::new(self.client, self.params_builder, RawRequestInner::new(req)) - .send() - .and_then(|res| res.into_response()); - - Pending::new(res_future) - } -} - -/** A future returned by calling `send`. */ -pub type Pending = BasePending; - -#[cfg(test)] +#[cfg(all(test, feature="sync_sender"))] mod tests { use crate::{ + client::requests::RequestInner, prelude::*, - tests::*, }; - #[test] - fn is_send() { - assert_send::(); - } - #[test] fn default_request() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.sql().inner.into_request(); + let req = client.sql().inner.into_request().unwrap(); assert_eq!("/_xpack/sql", req.url.as_ref()); } @@ -311,7 +205,7 @@ mod tests { fn specify_body() { let client = SyncClientBuilder::new().build().unwrap(); - let req = client.sql().body("{}").inner.into_request(); + let req = client.sql().body("{}").inner.into_request().unwrap(); assert_eq!("{}", req.body); } diff --git a/src/elastic/src/client/synchronous.rs b/src/elastic/src/client/synchronous.rs index 25d8922852..0122cfe93c 100644 --- a/src/elastic/src/client/synchronous.rs +++ b/src/elastic/src/client/synchronous.rs @@ -260,7 +260,7 @@ impl SyncClientBuilder { pre_send: self.pre_send, }; - let addresses = self.nodes.build(params, sender.clone()); + let addresses = self.nodes.build(params); Ok(SyncClient { sender, addresses }) } diff --git a/src/elastic/src/error.rs b/src/elastic/src/error.rs index 3939b2a434..e50d66497d 100644 --- a/src/elastic/src/error.rs +++ b/src/elastic/src/error.rs @@ -45,6 +45,7 @@ use crate::http::{ receiver::ResponseError, StatusCode, }; +#[cfg(any(feature="async_sender", feature="sync_sender"))] use reqwest::Error as ReqwestError; use serde_json; @@ -89,7 +90,8 @@ pub(crate) mod string_error { } } -pub(crate) struct WrappedError(Box); +/** Wraps a boxed stdlib error */ +pub struct WrappedError(Box); impl fmt::Display for WrappedError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -135,7 +137,8 @@ impl fmt::Display for ClientError { } } -pub(crate) fn build(err: E) -> Error +/** Creates a client error by wrapping an existing error */ +pub fn build(err: E) -> Error where E: StdError + Send + 'static, { @@ -144,11 +147,13 @@ where }) } -pub(crate) fn wrapped(err: Box) -> WrappedError { +/** Wraps a boxed stdlib error into a `WrappedError` */ +pub fn wrapped(err: Box) -> WrappedError { WrappedError(err) } -pub(crate) fn request(err: E) -> Error +/** Creates an error for when a request could not be generated or sent */ +pub fn request(err: E) -> Error where E: StdError + Send + 'static, { @@ -157,7 +162,8 @@ where }) } -pub(crate) fn response(status: StatusCode, err: E) -> Error +/** Creates an error from a failure response */ +pub fn response(status: StatusCode, err: E) -> Error where E: Into> + StdError + Send + 'static, { @@ -184,8 +190,11 @@ pub(crate) fn test() -> Error { }) } -pub(crate) enum MaybeApiError { +/** Error that can be either an ApiError or some other error */ +pub enum MaybeApiError { + /** An API error */ Api(ApiError), + /** A different error */ Other(E), } @@ -204,6 +213,7 @@ impl Into> for io::Error { } } +#[cfg(any(feature="async_sender", feature="sync_sender"))] impl Into> for ReqwestError { fn into(self) -> MaybeApiError { MaybeApiError::Other(self) diff --git a/src/elastic/src/genned/mod.rs b/src/elastic/src/genned/mod.rs index 2e3ed855f5..e839adf4ec 100644 --- a/src/elastic/src/genned/mod.rs +++ b/src/elastic/src/genned/mod.rs @@ -5,10 +5,8 @@ run the `tools/generate_requests.sh` script to update it pub mod endpoints { #![allow(missing_docs)] #![allow(clippy::all)] - use super::{ - http::*, - params::*, - }; + use super::http::*; + use super::params::*; #[derive(Debug, Clone, PartialEq)] enum BulkUrlParams<'a> { @@ -77,6 +75,12 @@ pub mod endpoints { } impl<'a, B> Into> for BulkRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for BulkRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -126,6 +130,12 @@ pub mod endpoints { } impl<'a> Into> for CatAliasesRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatAliasesRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -175,6 +185,12 @@ pub mod endpoints { } impl<'a> Into> for CatAllocationRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatAllocationRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -224,6 +240,12 @@ pub mod endpoints { } impl<'a> Into> for CatCountRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatCountRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -273,6 +295,12 @@ pub mod endpoints { } impl<'a> Into> for CatFielddataRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatFielddataRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -306,6 +334,12 @@ pub mod endpoints { } impl<'a> Into> for CatHealthRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatHealthRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -339,6 +373,12 @@ pub mod endpoints { } impl<'a> Into> for CatHelpRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatHelpRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -388,6 +428,12 @@ pub mod endpoints { } impl<'a> Into> for CatIndicesRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatIndicesRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -421,6 +467,12 @@ pub mod endpoints { } impl<'a> Into> for CatMasterRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatMasterRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -454,6 +506,12 @@ pub mod endpoints { } impl<'a> Into> for CatNodeattrsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatNodeattrsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -487,6 +545,12 @@ pub mod endpoints { } impl<'a> Into> for CatNodesRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatNodesRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -520,6 +584,12 @@ pub mod endpoints { } impl<'a> Into> for CatPendingTasksRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatPendingTasksRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -553,6 +623,12 @@ pub mod endpoints { } impl<'a> Into> for CatPluginsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatPluginsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -602,6 +678,12 @@ pub mod endpoints { } impl<'a> Into> for CatRecoveryRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatRecoveryRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -635,6 +717,12 @@ pub mod endpoints { } impl<'a> Into> for CatRepositoriesRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatRepositoriesRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -684,6 +772,12 @@ pub mod endpoints { } impl<'a> Into> for CatSegmentsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatSegmentsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -733,6 +827,12 @@ pub mod endpoints { } impl<'a> Into> for CatShardsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatShardsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -782,6 +882,12 @@ pub mod endpoints { } impl<'a> Into> for CatSnapshotsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatSnapshotsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -815,6 +921,12 @@ pub mod endpoints { } impl<'a> Into> for CatTasksRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatTasksRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -864,6 +976,12 @@ pub mod endpoints { } impl<'a> Into> for CatTemplatesRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatTemplatesRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -915,6 +1033,12 @@ pub mod endpoints { } impl<'a> Into> for CatThreadPoolRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for CatThreadPoolRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -967,6 +1091,12 @@ pub mod endpoints { } impl<'a, B> Into> for ClearScrollRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ClearScrollRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -1004,6 +1134,12 @@ pub mod endpoints { } impl<'a, B> Into> for ClusterAllocationExplainRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ClusterAllocationExplainRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1037,6 +1173,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterGetSettingsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterGetSettingsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1086,6 +1228,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterHealthRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterHealthRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1119,6 +1267,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterPendingTasksRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterPendingTasksRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1154,6 +1308,12 @@ pub mod endpoints { } impl<'a, B> Into> for ClusterPutSettingsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ClusterPutSettingsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::PUT, @@ -1187,6 +1347,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterRemoteInfoRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterRemoteInfoRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1222,6 +1388,12 @@ pub mod endpoints { } impl<'a, B> Into> for ClusterRerouteRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ClusterRerouteRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1290,6 +1462,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterStateRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterStateRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1339,6 +1517,12 @@ pub mod endpoints { } impl<'a> Into> for ClusterStatsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ClusterStatsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -1413,6 +1597,12 @@ pub mod endpoints { } impl<'a, B> Into> for CountRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for CountRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1489,6 +1679,12 @@ pub mod endpoints { } impl<'a, B> Into> for CreateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for CreateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1555,6 +1751,12 @@ pub mod endpoints { } impl<'a> Into> for DeleteRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for DeleteRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -1620,6 +1822,12 @@ pub mod endpoints { } impl<'a, B> Into> for DeleteByQueryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for DeleteByQueryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1664,6 +1872,12 @@ pub mod endpoints { } impl<'a, B> Into> for DeleteByQueryRethrottleRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for DeleteByQueryRethrottleRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1705,6 +1919,12 @@ pub mod endpoints { } impl<'a> Into> for DeleteScriptRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for DeleteScriptRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -1771,6 +1991,12 @@ pub mod endpoints { } impl<'a> Into> for ExistsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ExistsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -1839,6 +2065,12 @@ pub mod endpoints { } impl<'a> Into> for ExistsSourceRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for ExistsSourceRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -1915,6 +2147,12 @@ pub mod endpoints { } impl<'a, B> Into> for ExplainRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ExplainRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -1968,6 +2206,12 @@ pub mod endpoints { } impl<'a, B> Into> for FieldCapsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for FieldCapsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2034,6 +2278,12 @@ pub mod endpoints { } impl<'a> Into> for GetRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for GetRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -2075,6 +2325,12 @@ pub mod endpoints { } impl<'a> Into> for GetScriptRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for GetScriptRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -2143,6 +2399,12 @@ pub mod endpoints { } impl<'a> Into> for GetSourceRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for GetSourceRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -2255,6 +2517,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndexRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndexRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2308,6 +2576,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesAnalyzeRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesAnalyzeRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2361,6 +2635,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesClearCacheRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesClearCacheRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2405,6 +2685,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesCloseRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesCloseRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2448,6 +2734,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesCreateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesCreateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::PUT, @@ -2489,6 +2781,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesDeleteRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesDeleteRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -2533,6 +2831,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesDeleteAliasRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesDeleteAliasRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -2574,6 +2878,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesDeleteTemplateRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesDeleteTemplateRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -2615,6 +2925,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesExistsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesExistsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -2675,6 +2991,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesExistsAliasRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesExistsAliasRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -2716,6 +3038,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesExistsTemplateRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesExistsTemplateRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -2760,6 +3088,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesExistsTypeRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesExistsTypeRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -2813,6 +3147,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesFlushRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesFlushRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2866,6 +3206,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesFlushSyncedRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesFlushSyncedRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2919,6 +3265,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesForcemergeRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesForcemergeRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -2960,6 +3312,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3045,6 +3403,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetAliasRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetAliasRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3157,6 +3521,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetFieldMappingRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetFieldMappingRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3242,6 +3612,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetMappingRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetMappingRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3327,6 +3703,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetSettingsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetSettingsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3376,6 +3758,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetTemplateRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetTemplateRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3426,6 +3814,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesGetUpgradeRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesGetUpgradeRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3470,6 +3864,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesOpenRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesOpenRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3516,6 +3916,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesPutAliasRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesPutAliasRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3597,6 +4003,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesPutMappingRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesPutMappingRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3650,6 +4062,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesPutSettingsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesPutSettingsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::PUT, @@ -3693,6 +4111,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesPutTemplateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesPutTemplateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3743,6 +4167,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesRecoveryRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesRecoveryRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3796,6 +4226,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesRefreshRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesRefreshRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3864,6 +4300,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesRolloverRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesRolloverRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -3914,6 +4356,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesSegmentsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesSegmentsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -3964,6 +4412,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesShardStoresRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesShardStoresRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4010,6 +4464,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesShrinkRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesShrinkRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4056,6 +4516,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesSplitRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesSplitRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4141,6 +4607,12 @@ pub mod endpoints { } impl<'a> Into> for IndicesStatsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IndicesStatsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4176,6 +4648,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesUpdateAliasesRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesUpdateAliasesRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4229,6 +4707,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesUpgradeRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesUpgradeRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4303,6 +4787,12 @@ pub mod endpoints { } impl<'a, B> Into> for IndicesValidateQueryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IndicesValidateQueryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4336,6 +4826,12 @@ pub mod endpoints { } impl<'a> Into> for InfoRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for InfoRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4377,6 +4873,12 @@ pub mod endpoints { } impl<'a> Into> for IngestDeletePipelineRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IngestDeletePipelineRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -4426,6 +4928,12 @@ pub mod endpoints { } impl<'a> Into> for IngestGetPipelineRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IngestGetPipelineRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4459,6 +4967,12 @@ pub mod endpoints { } impl<'a> Into> for IngestProcessorGrokRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for IngestProcessorGrokRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4502,6 +5016,12 @@ pub mod endpoints { } impl<'a, B> Into> for IngestPutPipelineRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IngestPutPipelineRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::PUT, @@ -4555,6 +5075,12 @@ pub mod endpoints { } impl<'a, B> Into> for IngestSimulateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for IngestSimulateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4629,6 +5155,12 @@ pub mod endpoints { } impl<'a, B> Into> for MgetRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for MgetRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4703,6 +5235,12 @@ pub mod endpoints { } impl<'a, B> Into> for MsearchRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for MsearchRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4777,6 +5315,12 @@ pub mod endpoints { } impl<'a, B> Into> for MsearchTemplateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for MsearchTemplateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4851,6 +5395,12 @@ pub mod endpoints { } impl<'a, B> Into> for MtermvectorsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for MtermvectorsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -4901,6 +5451,12 @@ pub mod endpoints { } impl<'a> Into> for NodesHotThreadsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for NodesHotThreadsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -4985,6 +5541,12 @@ pub mod endpoints { } impl<'a> Into> for NodesInfoRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for NodesInfoRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -5040,6 +5602,12 @@ pub mod endpoints { } impl<'a, B> Into> for NodesReloadSecureSettingsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for NodesReloadSecureSettingsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5186,6 +5754,12 @@ pub mod endpoints { } impl<'a> Into> for NodesStatsRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for NodesStatsRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -5271,6 +5845,12 @@ pub mod endpoints { } impl<'a> Into> for NodesUsageRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for NodesUsageRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -5304,6 +5884,12 @@ pub mod endpoints { } impl<'a> Into> for PingRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for PingRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -5337,6 +5923,12 @@ pub mod endpoints { } impl<'a> Into> for PingHeadRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for PingHeadRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::HEAD, @@ -5400,6 +5992,12 @@ pub mod endpoints { } impl<'a, B> Into> for PutScriptRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for PutScriptRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5453,6 +6051,12 @@ pub mod endpoints { } impl<'a, B> Into> for RankEvalRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for RankEvalRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5488,6 +6092,12 @@ pub mod endpoints { } impl<'a, B> Into> for ReindexRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ReindexRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5532,6 +6142,12 @@ pub mod endpoints { } impl<'a, B> Into> for ReindexRethrottleRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ReindexRethrottleRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5584,6 +6200,12 @@ pub mod endpoints { } impl<'a, B> Into> for RenderSearchTemplateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for RenderSearchTemplateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5621,6 +6243,12 @@ pub mod endpoints { } impl<'a, B> Into> for ScriptsPainlessExecuteRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ScriptsPainlessExecuteRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5673,6 +6301,12 @@ pub mod endpoints { } impl<'a, B> Into> for ScrollRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for ScrollRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5743,6 +6377,12 @@ pub mod endpoints { } impl<'a> Into> for SimpleSearchRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SimpleSearchRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -5817,6 +6457,12 @@ pub mod endpoints { } impl<'a, B> Into> for SearchRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SearchRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5870,6 +6516,12 @@ pub mod endpoints { } impl<'a, B> Into> for SearchShardsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SearchShardsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5944,6 +6596,12 @@ pub mod endpoints { } impl<'a, B> Into> for SearchTemplateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SearchTemplateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -5999,6 +6657,12 @@ pub mod endpoints { } impl<'a, B> Into> for SnapshotCreateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SnapshotCreateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6042,6 +6706,12 @@ pub mod endpoints { } impl<'a, B> Into> for SnapshotCreateRepositoryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SnapshotCreateRepositoryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6094,6 +6764,12 @@ pub mod endpoints { } impl<'a> Into> for SnapshotDeleteRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SnapshotDeleteRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -6135,6 +6811,12 @@ pub mod endpoints { } impl<'a> Into> for SnapshotDeleteRepositoryRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SnapshotDeleteRepositoryRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::DELETE, @@ -6184,6 +6866,12 @@ pub mod endpoints { } impl<'a> Into> for SnapshotGetRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SnapshotGetRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -6233,6 +6921,12 @@ pub mod endpoints { } impl<'a> Into> for SnapshotGetRepositoryRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SnapshotGetRepositoryRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -6289,6 +6983,12 @@ pub mod endpoints { } impl<'a, B> Into> for SnapshotRestoreRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SnapshotRestoreRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6367,6 +7067,12 @@ pub mod endpoints { } impl<'a> Into> for SnapshotStatusRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for SnapshotStatusRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -6411,6 +7117,12 @@ pub mod endpoints { } impl<'a, B> Into> for SnapshotVerifyRepositoryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SnapshotVerifyRepositoryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6446,6 +7158,12 @@ pub mod endpoints { } impl<'a, B> Into> for SqlQueryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for SqlQueryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6499,6 +7217,12 @@ pub mod endpoints { } impl<'a, B> Into> for TasksCancelRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for TasksCancelRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6540,6 +7264,12 @@ pub mod endpoints { } impl<'a> Into> for TasksGetRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for TasksGetRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -6573,6 +7303,12 @@ pub mod endpoints { } impl<'a> Into> for TasksListRequest<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for TasksListRequest<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -6688,6 +7424,12 @@ pub mod endpoints { } impl<'a, B> Into> for TermvectorsRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for TermvectorsRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6764,6 +7506,12 @@ pub mod endpoints { } impl<'a, B> Into> for UpdateRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for UpdateRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6829,6 +7577,12 @@ pub mod endpoints { } impl<'a, B> Into> for UpdateByQueryRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for UpdateByQueryRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6873,6 +7627,12 @@ pub mod endpoints { } impl<'a, B> Into> for UpdateByQueryRethrottleRequest<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for UpdateByQueryRethrottleRequest<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::POST, @@ -6886,10 +7646,8 @@ pub mod http { #![allow(missing_docs)] #![allow(clippy::all)] pub use crate::http::Method; - use std::{ - borrow::Cow, - ops::Deref, - }; + use std::borrow::Cow; + use std::ops::Deref; #[doc = r" A wrapper around an owned or borrowed url path."] #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -6917,6 +7675,14 @@ pub mod http { pub method: Method, pub body: Option, } + #[doc = r" Trait for converting a request into its endpoint."] + #[doc = r""] + #[doc = r" Like `From`, but the client API doesn't need to know the exact"] + #[doc = r" type to convert into."] + pub trait IntoEndpoint<'a> { + type BodyType; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType>; + } #[doc = r" A default body type."] pub type DefaultBody = &'static [u8]; #[doc = r" A convenience method for a default, empty body."] diff --git a/src/elastic/src/http/asynchronous.rs b/src/elastic/src/http/asynchronous.rs index 83f3a95d73..f4692fef0e 100644 --- a/src/elastic/src/http/asynchronous.rs +++ b/src/elastic/src/http/asynchronous.rs @@ -7,9 +7,12 @@ use std::{ Cursor, Read, }, + marker::PhantomData, }; use futures::{ + Future, + IntoFuture, Poll, Stream, }; @@ -159,6 +162,42 @@ impl AsyncHttpResponse { } } +/** A boxed future wrapper. */ +pub struct Pending { + inner: Box + Send>, + _ph: PhantomData, +} + +impl Pending { + /** Creates a new `Pending`, wrapping an existing future */ + pub fn new(fut: F) -> Self + where + F: Future + Send + 'static, + { + Pending { + inner: Box::new(fut), + _ph: Default::default(), + } + } +} + +impl Future for Pending { + type Item = T; + type Error = Error; + + fn poll(&mut self) -> Poll { + self.inner.poll() + } +} + +impl From for Pending +where T: Send + 'static +{ + fn from(v: T) -> Pending { + Self::new(Ok(v).into_future()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/elastic/src/http/mod.rs b/src/elastic/src/http/mod.rs index a36588d814..2203e74330 100644 --- a/src/elastic/src/http/mod.rs +++ b/src/elastic/src/http/mod.rs @@ -5,22 +5,23 @@ These types are lower-level details for sending requests and receiving responses. */ +#[cfg(feature="async_sender")] mod asynchronous; +#[cfg(feature="sync_sender")] mod synchronous; -pub use self::{ - asynchronous::*, - synchronous::*, -}; +#[cfg(feature="async_sender")] +pub use self::asynchronous::*; +#[cfg(feature="sync_sender")] +pub use self::synchronous::*; pub mod receiver; pub mod sender; #[doc(inline)] -pub use reqwest::{ - header, - Url, -}; +pub use http::header; +#[doc(inline)] +pub use url::Url; #[doc(inline)] pub use http::{ @@ -47,10 +48,14 @@ A request just before being sent. */ #[derive(Clone)] pub struct HttpRequest { - pub(crate) url: Url, - pub(crate) method: Method, - pub(crate) headers: Arc, - pub(crate) body: Option, + /** URL to send to */ + pub url: Url, + /** Request method to use */ + pub method: Method, + /** Request headers */ + pub headers: Arc, + /** Request body */ + pub body: Option, } impl HttpRequest { diff --git a/src/elastic/src/http/receiver/mod.rs b/src/elastic/src/http/receiver/mod.rs index 9a51411718..5e16897bf8 100644 --- a/src/elastic/src/http/receiver/mod.rs +++ b/src/elastic/src/http/receiver/mod.rs @@ -6,14 +6,19 @@ This module contains low-level implementation details for the high-level [`Clien [Client]: ../struct.Client.html */ +#[cfg(feature="async_sender")] mod asynchronous; mod error; mod parsing; +#[cfg(feature="sync_sender")] mod synchronous; pub use self::{ - asynchronous::*, error::*, parsing::*, - synchronous::*, }; + +#[cfg(feature="async_sender")] +pub use self::asynchronous::*; +#[cfg(feature="sync_sender")] +pub use self::synchronous::*; diff --git a/src/elastic/src/http/sender/asynchronous.rs b/src/elastic/src/http/sender/asynchronous.rs index aababb35cb..a0663e5748 100644 --- a/src/elastic/src/http/sender/asynchronous.rs +++ b/src/elastic/src/http/sender/asynchronous.rs @@ -22,6 +22,10 @@ use tokio_threadpool::{ }; use crate::{ + client::{ + requests::RequestInner, + responses::nodes_info::NodesInfoResponse, + }, endpoints::Endpoint, error::{ self, @@ -33,16 +37,17 @@ use crate::{ AsyncResponseBuilder, }, sender::{ - build_reqwest_method, + build_http_method, build_url, - NextParams, NodeAddresses, - NodeAddressesInner, RequestParams, SendableRequest, SendableRequestParams, Sender, + sniffed_nodes::NextOrRefresh, + TypedSender, }, + Pending, AsyncBody, AsyncHttpRequest, Url, @@ -190,49 +195,62 @@ impl Sender for AsyncSender { PendingResponse::new(req_future) } -} -impl NextParams for NodeAddresses { - type Params = PendingParams; - - fn next(&self) -> Self::Params { - match self.inner { - NodeAddressesInner::Static(ref nodes) => PendingParams::new(nodes.next().into_future()), - NodeAddressesInner::Sniffed(ref sniffer) => PendingParams::new(sniffer.next()), + fn next_params( + &self, + addresses: &NodeAddresses, + ) -> Self::Params { + match addresses { + NodeAddresses::Static(ref nodes) => PendingParams::new(nodes.next().into_future()), + NodeAddresses::Sniffed(ref sniffer) => { + let refresher = match sniffer.next_or_start_refresh() { + Ok(NextOrRefresh::Next(address)) => { + return Pending::new(Box::new(Ok(address).into_future())); + }, + Ok(NextOrRefresh::NeedsRefresh(r)) => r, + Err(err) => { + return Pending::new(Box::new(Err(err).into_future())); + } + }; + + let req = sniffer.sendable_request(); + let refresh_nodes = self + .send(req) + .and_then(|res| res.into_response::()) + .then(move |fresh_nodes| refresher.update_nodes_and_next(fresh_nodes)); + + PendingParams::new(Box::new(refresh_nodes)) + } } } } - -/** A future returned by calling `next` on an async set of `NodeAddresses`. */ -pub struct PendingParams { - inner: Box + Send>, -} - -impl PendingParams { - fn new(fut: F) -> Self +impl TypedSender for AsyncSender +where + TReqInner: RequestInner, +{ + type TypedResponse = Pending; + fn typed_send( + &self, + request: Result, Error>, + ) -> Self::TypedResponse where - F: Future + Send + 'static, + TEndpoint: Into> + Send + 'static, + TBody: Into + Send + 'static, + TParams: Into + Send + 'static, { - PendingParams { - inner: Box::new(fut), - } + let this = self.clone(); + let fut = self.maybe_async(move || request) + .and_then(move |sendable_request| { + this.send(sendable_request) + }) + .and_then(|v| v.into_response::()); + return Pending::new(fut); } } -impl Future for PendingParams { - type Item = RequestParams; - type Error = Error; - - fn poll(&mut self) -> Poll { - self.inner.poll() - } -} -impl From for PendingParams { - fn from(params: RequestParams) -> Self { - PendingParams::new(Ok(params).into_future()) - } -} +/** A future returned by calling `next` on an async set of `NodeAddresses`. */ +pub type PendingParams = Pending; /** Build an asynchronous `reqwest::RequestBuilder` from an Elasticsearch request. */ fn build_reqwest(client: &AsyncHttpClient, req: AsyncHttpRequest) -> AsyncHttpRequestBuilder { @@ -244,7 +262,7 @@ fn build_reqwest(client: &AsyncHttpClient, req: AsyncHttpRequest) -> AsyncHttpRe .. } = req; - let method = build_reqwest_method(method); + let method = build_http_method(method); let mut req = client.request(method, url); { @@ -258,30 +276,10 @@ fn build_reqwest(client: &AsyncHttpClient, req: AsyncHttpRequest) -> AsyncHttpRe req } -/** A future returned by calling `send` on an `AsyncSender`. */ -pub struct PendingResponse { - inner: Box + Send>, -} - -impl PendingResponse { - fn new(fut: F) -> Self - where - F: Future + Send + 'static, - { - PendingResponse { - inner: Box::new(fut), - } - } -} -impl Future for PendingResponse { - type Item = AsyncResponseBuilder; - type Error = Error; - fn poll(&mut self) -> Poll { - self.inner.poll() - } -} +/** A future returned by calling `send` on an `AsyncSender`. */ +pub type PendingResponse = Pending; struct PendingLogErr { future: F, diff --git a/src/elastic/src/http/sender/mod.rs b/src/elastic/src/http/sender/mod.rs index 5992e68cf2..9050c630f0 100644 --- a/src/elastic/src/http/sender/mod.rs +++ b/src/elastic/src/http/sender/mod.rs @@ -6,7 +6,6 @@ Most of the types here aren't currently usable directly, but once the low-level Some notable types include: - `Sender`: a generic trait that can send a http request and return a response -- `NextParams`: a generic trait that can fetch a set of parameters to associate with a request - `SyncSender`: a synchronous http client - `AsyncSender`: an asynchronous http client. @@ -21,14 +20,17 @@ use fluent_builder::{ pub mod sniffed_nodes; pub mod static_nodes; -mod asynchronous; mod params; +pub use self::params::*; + +#[cfg(feature="async_sender")] +mod asynchronous; +#[cfg(feature="sync_sender")] mod synchronous; -pub use self::{ - asynchronous::*, - params::*, - synchronous::*, -}; +#[cfg(feature="async_sender")] +pub use self::asynchronous::*; +#[cfg(feature="sync_sender")] +pub use self::synchronous::*; use std::{ marker::PhantomData, @@ -44,8 +46,9 @@ use self::{ static_nodes::StaticNodes, }; use crate::{ + client::requests::RequestInner, endpoints::Endpoint, - private, + error::Error, }; /** @@ -57,9 +60,12 @@ This type encapsulates the state needed between a [`Client`][Client] and a [`Sen [Sender]: trait.Sender.html */ pub struct SendableRequest { - correlation_id: Uuid, - inner: TEndpoint, - params: SendableRequestParams, + /** Unique ID for the request. */ + pub correlation_id: Uuid, + /** Endpoint for the request */ + pub inner: TEndpoint, + /** Parameters for the request */ + pub params: SendableRequestParams, _marker: PhantomData, } @@ -74,10 +80,15 @@ impl SendableRequest { } } -pub(crate) enum SendableRequestParams { +/** Parameters for a SendableRequest */ +pub enum SendableRequestParams { + /** Parameters were explicitly defined for this specific request */ Value(RequestParams), + /** Paremeters weren't explicitly defined, so they must be built */ Builder { + /** Base parameters */ params: TParams, + /** Builder for the parameters */ builder: SharedFluentBuilder, }, } @@ -96,15 +107,15 @@ At some point in the future though this may be made more generic so you could re [Client]: struct.Client.html */ -pub trait Sender: private::Sealed + Clone { +pub trait Sender: Clone { /** The kind of request body this sender accepts. */ type Body; /** The kind of response this sender produces. */ type Response; /** The kind of request parameters this sender accepts. */ - type Params; + type Params: Send+'static; - /** Send a request. */ + /** Send a raw request. */ fn send( &self, request: SendableRequest, @@ -113,25 +124,69 @@ pub trait Sender: private::Sealed + Clone { TEndpoint: Into>, TBody: Into + Send + 'static, TParams: Into + Send + 'static; + + /** + Gets the parameters for the next query. + + A set of request parameters are fetched before each HTTP request. This method + makes it possible to load balance requests between multiple nodes in an Elasticsearch + cluster. Out of the box elastic provides implementations for a static set of nodes or + nodes sniffed from the Nodes Stats API. + */ + fn next_params( + &self, + addresses: &NodeAddresses, + ) -> Self::Params; } /** -Represents a type that can fetch request parameters. +Represents a type that can send a typed request and deserialize the result. + +You probably don't need to touch this trait directly. +See the [`Client`][Client] type for making requests. -A set of request parameters are fetched before each HTTP request. -The `NextParams` trait makes it possible to load balance requests between multiple nodes in an Elasticsearch cluster. -Out of the box `elastic` provides implementations for a static set of nodes or nodes sniffed from the [Nodes Stats API](). +Senders should implement this for every type implementing `RequestInner`, for example +via `impl TypedSender for MySender`. + +In the future, when [generic associated types][gna] are stabilized, this trait should be +folded into the `Sender` trait, using a generic associated type for the response object +(ex. `type TypedResponse`). + +[gna]: https://rust-lang.github.io/rfcs/1598-generic_associated_types.html */ -pub trait NextParams: private::Sealed + Clone { +pub trait TypedSender: Sender +where + TReqInner: RequestInner, +{ + /** - The kind of parameters produces. + Response object containing the deserialized result or an error. - This type is designed to link a `NextParams` implementation with a particular `Sender`. + This is very generic to allow flexibility between sync and async implementations, + but should ideally be some type using the `TReqInner::Response` type. + + For `SyncSender`, this is `Result`. + For `AsyncSender`, this is a type that implements `Future`. */ - type Params; + type TypedResponse; + + + /** + Sends a request and deserializes the result. - /** Get a set of request parameters. */ - fn next(&self) -> Self::Params; + The caller is responsible for converting the request object (`TEndpoint::Request`) + to a `SendableRequest`. The caller passes either the sendable request or an error if + the conversion failed. If it's an error, the implementation should return an appropriate + error type (Ex. `Err` for `SyncSender` or a pre-failed future for `AsyncSender`). + */ + fn typed_send( + &self, + request: Result, Error>, + ) -> Self::TypedResponse + where + TEndpoint: Into> + Send + 'static, + TBody: Into + Send + 'static, + TParams: Into + Send + 'static; } /** @@ -159,39 +214,36 @@ where A common container for a source of node addresses. */ #[derive(Clone)] -pub struct NodeAddresses { - inner: NodeAddressesInner, +pub enum NodeAddresses { + /** Static list of nodes */ + Static(StaticNodes), + /** Fetch set of nodes from a single node of the cluster */ + Sniffed(SniffedNodes), } -impl NodeAddresses { - pub(crate) fn static_nodes(nodes: StaticNodes) -> Self { - NodeAddresses { - inner: NodeAddressesInner::Static(nodes), - } +impl NodeAddresses { + /** Static set of nodes to connect to */ + pub fn static_nodes(nodes: StaticNodes) -> Self { + NodeAddresses::Static(nodes) } - pub(crate) fn sniffed_nodes(nodes: SniffedNodes) -> Self { - NodeAddresses { - inner: NodeAddressesInner::Sniffed(nodes), - } + /** Fetch set of nodes from a single node of the cluster */ + pub fn sniffed_nodes(nodes: SniffedNodes) -> Self { + NodeAddresses::Sniffed(nodes) } } -impl private::Sealed for NodeAddresses {} - -#[derive(Clone)] -enum NodeAddressesInner { - Static(StaticNodes), - Sniffed(SniffedNodes), -} - -pub(crate) enum NodeAddressesBuilder { +/** Builder for `NodeAddresses` */ +pub enum NodeAddressesBuilder { + /** Static list of nodes */ Static(Vec), + /** Fetch set of nodes from a single node of the cluster */ Sniffed(SharedStatefulFluentBuilder), } impl NodeAddressesBuilder { - pub(crate) fn sniff_nodes(self, builder: SniffedNodesBuilder) -> Self { + /** Sniff nodes */ + pub fn sniff_nodes(self, builder: SniffedNodesBuilder) -> Self { match self { NodeAddressesBuilder::Sniffed(fluent_builder) => { NodeAddressesBuilder::Sniffed(fluent_builder.value(builder)) @@ -200,7 +252,8 @@ impl NodeAddressesBuilder { } } - pub(crate) fn sniff_nodes_fluent(self, address: NodeAddress, fleunt_method: F) -> Self + /** Sniff nodes */ + pub fn sniff_nodes_fluent(self, address: NodeAddress, fleunt_method: F) -> Self where F: FnOnce(SniffedNodesBuilder) -> SniffedNodesBuilder + Send + 'static, { @@ -223,11 +276,11 @@ impl Default for NodeAddressesBuilder { } impl NodeAddressesBuilder { - pub(crate) fn build( + /** Builds the node addresses */ + pub fn build( self, params: PreRequestParams, - sender: TSender, - ) -> NodeAddresses { + ) -> NodeAddresses { match self { NodeAddressesBuilder::Static(nodes) => { let nodes = StaticNodes::round_robin(nodes, params); @@ -237,7 +290,7 @@ impl NodeAddressesBuilder { NodeAddressesBuilder::Sniffed(builder) => { let nodes = builder .into_value(SniffedNodesBuilder::new) - .build(params, sender); + .build(params); NodeAddresses::sniffed_nodes(nodes) } diff --git a/src/elastic/src/http/sender/params.rs b/src/elastic/src/http/sender/params.rs index 9c718dcb01..1313417f6f 100644 --- a/src/elastic/src/http/sender/params.rs +++ b/src/elastic/src/http/sender/params.rs @@ -4,8 +4,7 @@ use std::{ sync::Arc, }; -use reqwest::{ - self, +use http::{ header::{ HeaderMap, HeaderName, @@ -14,6 +13,7 @@ use reqwest::{ AUTHORIZATION, CONTENT_TYPE, }, + method::Method as HttpMethod, }; use url::form_urlencoded::Serializer; @@ -201,7 +201,8 @@ impl RequestParams { self.base_url.as_ref() } - pub(crate) fn get_headers(&self) -> Arc { + /** Gets a shared reference to the headers */ + pub fn get_headers(&self) -> Arc { self.inner.headers.clone() } @@ -236,7 +237,8 @@ impl Default for RequestParams { } } -pub(crate) fn build_url(req_url: &str, params: &RequestParams) -> String { +/** Creates the full URL for a request */ +pub fn build_url(req_url: &str, params: &RequestParams) -> String { let (qry_len, qry) = params.get_url_qry(); let mut url = String::with_capacity(params.base_url.as_ref().len() + req_url.len() + qry_len); @@ -251,16 +253,17 @@ pub(crate) fn build_url(req_url: &str, params: &RequestParams) -> String { url } -pub(crate) fn build_reqwest_method(method: Method) -> reqwest::Method { +/** Converts an elastic crate Method object to an http crate HttpMethod */ +pub fn build_http_method(method: Method) -> HttpMethod { match method { - Method::GET => reqwest::Method::GET, - Method::POST => reqwest::Method::POST, - Method::HEAD => reqwest::Method::HEAD, - Method::DELETE => reqwest::Method::DELETE, - Method::PUT => reqwest::Method::PUT, - Method::PATCH => reqwest::Method::PATCH, + Method::GET => HttpMethod::GET, + Method::POST => HttpMethod::POST, + Method::HEAD => HttpMethod::HEAD, + Method::DELETE => HttpMethod::DELETE, + Method::PUT => HttpMethod::PUT, + Method::PATCH => HttpMethod::PATCH, method => { - reqwest::Method::from_bytes(method.as_str().as_bytes()).expect("invalid HTTP method") + HttpMethod::from_bytes(method.as_str().as_bytes()).expect("invalid HTTP method") } } } diff --git a/src/elastic/src/http/sender/sniffed_nodes.rs b/src/elastic/src/http/sender/sniffed_nodes.rs index 02f92af05e..cc4cac2c42 100644 --- a/src/elastic/src/http/sender/sniffed_nodes.rs +++ b/src/elastic/src/http/sender/sniffed_nodes.rs @@ -23,10 +23,6 @@ This means our `SniffedNodes` structure looks completely different in synchronou It's effectively a rewrite. */ -use futures::{ - Future, - IntoFuture, -}; use std::{ sync::{ Arc, @@ -49,19 +45,14 @@ use crate::{ http::{ sender::{ static_nodes::StaticNodes, - AsyncSender, - NextParams, NodeAddress, PreRequestParams, RequestParams, SendableRequest, SendableRequestParams, - Sender, - SyncSender, }, DefaultBody, }, - private, }; /** @@ -76,8 +67,7 @@ If updating the nodes fails for some reason then the request itself will also fa [node info request]: https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-info.html */ #[derive(Clone)] -pub struct SniffedNodes { - sender: TSender, +pub struct SniffedNodes { refresh_params: RequestParams, inner: Arc>, } @@ -97,60 +87,6 @@ struct SniffedNodesInner { nodes: StaticNodes, } -impl SniffedNodes { - /** - Get the next async address or refresh. - - This method takes a generic function that will resolve to a new set of node addresses. - */ - fn async_next( - &self, - refresh: TRefresh, - ) -> Box + Send> - where - TRefresh: Fn( - SendableRequest, RequestParams, DefaultBody>, - ) -> TRefreshFuture, - TRefreshFuture: Future + Send + 'static, - { - if let Some(address) = self.next_or_start_refresh() { - return Box::new(address.into_future()); - } - - // Perform the refresh - let inner = self.inner.clone(); - let req = self.sendable_request(); - let refresh_params = self.refresh_params.clone(); - - let refresh_nodes = refresh(req) - .then(move |fresh_nodes| Self::finish_refresh(&inner, &refresh_params, fresh_nodes)); - - Box::new(refresh_nodes) - } - - /** - Get the next sync address or refresh. - - This method takes a generic function that will resolve to a new set of node addresses. - */ - fn sync_next(&self, refresh: TRefresh) -> Result - where - TRefresh: Fn( - SendableRequest, RequestParams, DefaultBody>, - ) -> Result, - { - if let Some(address) = self.next_or_start_refresh() { - return address; - } - - // Perform the refresh - let req = self.sendable_request(); - - let fresh_nodes = refresh(req); - Self::finish_refresh(&self.inner, &self.refresh_params, fresh_nodes) - } -} - impl SniffedNodesBuilder { /** Create a new `SniffedNodesBuilder` with the given base address. @@ -185,15 +121,14 @@ impl SniffedNodesBuilder { } /** - Build a cluster sniffer using the given sender and parameters. + Build a cluster sniffer using the given parameters. A `filter_path` url parameter will be added to the `refresh_parameters`. */ - pub(crate) fn build( + pub fn build( self, base_params: PreRequestParams, - sender: TSender, - ) -> SniffedNodes { + ) -> SniffedNodes { let nodes = StaticNodes::round_robin(vec![self.base_url.clone()], base_params.clone()); let wait = self.wait.unwrap_or_else(|| Duration::from_secs(90)); @@ -207,7 +142,6 @@ impl SniffedNodesBuilder { .url_param("filter_path", "nodes.*.http.publish_address"); SniffedNodes { - sender, refresh_params, inner: Arc::new(RwLock::new(SniffedNodesInner { last_update: None, @@ -234,30 +168,28 @@ Shared logic between sync and async methods. These methods definitely aren't intended to be made public. There are invariants that are shared between them that require they're called in specific ways. */ -impl SniffedNodes { +impl SniffedNodes { /** Return a node address if the set of nodes is still current. If this method returns `Some` then the set of nodes is current and an address is returned. If this method returns `None` then eventually call `finish_refresh`. */ - fn next_or_start_refresh(&self) -> Option> { + pub fn next_or_start_refresh(&self) -> Result { // Attempt to get an address using only a read lock first - let read_fresh = { + { let inner = self.inner.read().expect("lock poisoned"); if !inner.should_refresh() { // Return the next address without refreshing - let address = inner.nodes.next().map_err(error::request); + let address = inner.nodes.next().map_err(error::request)?; - Some(address) - } else { - None + return Ok(NextOrRefresh::Next(address)); } - }; + } // Attempt to refresh using a write lock otherwise - read_fresh.or_else(|| { + { let mut inner = self.inner.write().expect("lock poisoned"); if inner.refreshing { @@ -265,18 +197,24 @@ impl SniffedNodes { // This is unlikely but it's possible that a write lock // gets acquired after another thread kicks off a refresh. // In that case we don't want to do another one. - let address = inner.nodes.next().map_err(error::request); + let address = inner.nodes.next().map_err(error::request)?; - Some(address) + return Ok(NextOrRefresh::Next(address)); } else { inner.refreshing = true; - None + return Ok(NextOrRefresh::NeedsRefresh(Refresher { + inner: Arc::clone(&self.inner), + refresh_params: self.refresh_params.clone(), + })); } - }) + } } - fn sendable_request( + /** + Creates a `SendableRequest` for fetching node information. + */ + pub fn sendable_request( &self, ) -> SendableRequest, RequestParams, DefaultBody> { SendableRequest::new( @@ -284,29 +222,6 @@ impl SniffedNodes { SendableRequestParams::Value(self.refresh_params.clone()), ) } - - fn finish_refresh( - inner: &RwLock, - refresh_params: &RequestParams, - fresh_nodes: Result, - ) -> Result { - let mut inner = inner.write().expect("lock poisoned"); - - inner.refreshing = false; - - // TODO: We need to deal with the scheme better here - // The `NodeAddress` should one day be a properly typed url we can interrogate - let parsed_url = - Url::parse(refresh_params.get_base_url().as_ref()).map_err(error::request)?; - let scheme = parsed_url.scheme(); - - let fresh_nodes = fresh_nodes?; - let next = inner.update_nodes_and_next(fresh_nodes, scheme)?; - - inner.last_update = Some(Instant::now()); - - Ok(next) - } } impl SniffedNodesInner { @@ -335,40 +250,64 @@ impl SniffedNodesInner { } } -impl private::Sealed for SniffedNodes {} +/** Result of `SniffedNodes::next_or_start_refresh`. */ +pub enum NextOrRefresh { + /** Don't need to refresh, an address is available. */ + Next(RequestParams), + /** + Need to refresh. Sender should send a request and submit the + results to the `Refresher` in this object. + */ + NeedsRefresh(Refresher), +} -impl NextParams for SniffedNodes { - type Params = Box + Send>; +/** +Returned by `SniffedNodes::next_or_start_refresh` when a refresh is needed. - fn next(&self) -> Self::Params { - self.async_next(|req| { - self.sender - .send(req) - .and_then(|res| res.into_response::()) - }) - } +Senders should send a request to an existing node to get the new node list, then +pass the results to `update_nodes_and_next`, which consumes the object and updates +the node list. +*/ +pub struct Refresher { + inner: Arc>, + refresh_params: RequestParams, } +impl Refresher { + /** + Updates the node list of the `SniffedNodes` object. + + Senders should call this when the request for nodes comes in. + */ + pub fn update_nodes_and_next( + self, + fresh_nodes: Result, + ) -> Result { + let mut inner = self.inner.write().expect("lock poisoned"); + + inner.refreshing = false; + + // TODO: We need to deal with the scheme better here + // The `NodeAddress` should one day be a properly typed url we can interrogate + let parsed_url = + Url::parse(self.refresh_params.get_base_url().as_ref()).map_err(error::request)?; + let scheme = parsed_url.scheme(); + + let fresh_nodes = fresh_nodes?; + let next = inner.update_nodes_and_next(fresh_nodes, scheme)?; -impl NextParams for SniffedNodes { - type Params = Result; + inner.last_update = Some(Instant::now()); - fn next(&self) -> Self::Params { - self.sync_next(|req| { - self.sender - .send(req) - .and_then(|res| res.into_response::()) - }) + Ok(next) } } #[cfg(test)] mod tests { use super::*; - use futures::Future; use serde_json; - fn sender() -> SniffedNodes<()> { - SniffedNodesBuilder::new(initial_address()).build(PreRequestParams::default(), ()) + fn sender() -> SniffedNodes { + SniffedNodesBuilder::new(initial_address()).build(PreRequestParams::default()) } fn expected_nodes() -> NodesInfoResponse { @@ -402,7 +341,7 @@ mod tests { } fn assert_node_addresses_equal( - nodes: &SniffedNodes<()>, + nodes: &SniffedNodes, expected_addresses: Vec<&'static str>, ) { let inner = nodes.inner.read().expect("lock poisoned"); @@ -411,12 +350,12 @@ mod tests { assert_eq!(expected_addresses, actual); } - fn assert_refreshing_equal(nodes: &SniffedNodes<()>, refreshing: bool) { + fn assert_refreshing_equal(nodes: &SniffedNodes, refreshing: bool) { let inner = nodes.inner.read().expect("lock poisoned"); assert_eq!(refreshing, inner.refreshing); } - fn assert_should_refresh_equal(nodes: &SniffedNodes<()>, should_refresh: bool) { + fn assert_should_refresh_equal(nodes: &SniffedNodes, should_refresh: bool) { let inner = nodes.inner.read().expect("lock poisoned"); assert_eq!(should_refresh, inner.should_refresh()); } @@ -440,18 +379,22 @@ mod tests { } #[test] - fn async_refresh_success() { + fn refresh_success() { let nodes = sender(); let nodes_while_refreshing = nodes.clone(); - let res = nodes - .async_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - - Ok(expected_nodes()).into_future() - }) - .wait(); + let refresher = match nodes.next_or_start_refresh() { + Ok(NextOrRefresh::NeedsRefresh(r)) => r, + Ok(NextOrRefresh::Next(_)) => { + panic!("Expected to refresh here, got an address instead"); + }, + Err(err) => { + panic!("Expected to refresh here, got an error instead: {:?}", err); + }, + }; + assert_refreshing_equal(&nodes_while_refreshing, true); + let res = refresher.update_nodes_and_next(Ok(expected_nodes())); assert!(res.is_ok()); assert_node_addresses_equal(&nodes, expected_addresses()); @@ -460,38 +403,20 @@ mod tests { } #[test] - fn async_refresh_fail_on_empty() { + fn refresh_fail_on_empty() { let nodes = sender(); - let nodes_while_refreshing = nodes.clone(); - - let res = nodes - .async_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - - Ok(empty_nodes()).into_future() - }) - .wait(); - - assert!(res.is_err()); - - assert_node_addresses_equal(&nodes, vec![initial_address()]); - assert_refreshing_equal(&nodes, false); - assert_should_refresh_equal(&nodes, true); - } - - #[test] - fn async_refresh_fail_on_request() { - let nodes = sender(); - let nodes_while_refreshing = nodes.clone(); - let res = nodes - .async_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - - Err(error::test()).into_future() - }) - .wait(); + let refresher = match nodes.next_or_start_refresh() { + Ok(NextOrRefresh::NeedsRefresh(r)) => r, + Ok(NextOrRefresh::Next(_)) => { + panic!("Expected to refresh here, got an address instead"); + }, + Err(err) => { + panic!("Expected to refresh here, got an error instead: {:?}", err); + }, + }; + let res = refresher.update_nodes_and_next(Ok(empty_nodes())); assert!(res.is_err()); assert_node_addresses_equal(&nodes, vec![initial_address()]); @@ -500,34 +425,20 @@ mod tests { } #[test] - fn sync_refresh_success() { - let nodes = sender(); - let nodes_while_refreshing = nodes.clone(); - - let res = nodes.sync_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - - Ok(expected_nodes()) - }); - - assert!(res.is_ok()); - - assert_node_addresses_equal(&nodes, expected_addresses()); - assert_refreshing_equal(&nodes, false); - assert_should_refresh_equal(&nodes, false); - } - - #[test] - fn sync_refresh_fail_on_empty() { + fn refresh_fail_on_request() { let nodes = sender(); - let nodes_while_refreshing = nodes.clone(); - - let res = nodes.sync_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - Ok(empty_nodes()) - }); + let refresher = match nodes.next_or_start_refresh() { + Ok(NextOrRefresh::NeedsRefresh(r)) => r, + Ok(NextOrRefresh::Next(_)) => { + panic!("Expected to refresh here, got an address instead"); + }, + Err(err) => { + panic!("Expected to refresh here, got an error instead: {:?}", err); + }, + }; + let res = refresher.update_nodes_and_next(Err(error::test())); assert!(res.is_err()); assert_node_addresses_equal(&nodes, vec![initial_address()]); @@ -535,21 +446,4 @@ mod tests { assert_should_refresh_equal(&nodes, true); } - #[test] - fn sync_refresh_fail_on_request() { - let nodes = sender(); - let nodes_while_refreshing = nodes.clone(); - - let res = nodes.sync_next(move |_| { - assert_refreshing_equal(&nodes_while_refreshing, true); - - Err(error::test()) - }); - - assert!(res.is_err()); - - assert_node_addresses_equal(&nodes, vec![initial_address()]); - assert_refreshing_equal(&nodes, false); - assert_should_refresh_equal(&nodes, true); - } } diff --git a/src/elastic/src/http/sender/static_nodes.rs b/src/elastic/src/http/sender/static_nodes.rs index 30787ebf86..2c5bcf387a 100644 --- a/src/elastic/src/http/sender/static_nodes.rs +++ b/src/elastic/src/http/sender/static_nodes.rs @@ -8,7 +8,6 @@ use crate::{ Error, }, http::sender::{ - NextParams, NodeAddress, PreRequestParams, RequestParams, @@ -31,23 +30,12 @@ pub struct StaticNodes { params: PreRequestParams, } -impl NextParams for StaticNodes +impl private::Sealed for StaticNodes {} + +impl StaticNodes where TStrategy: Strategy + Clone, { - type Params = Result; - - fn next(&self) -> Self::Params { - self.strategy - .try_next(&self.nodes) - .map(|address| RequestParams::from_parts(address, self.params.clone())) - .map_err(error::request) - } -} - -impl private::Sealed for StaticNodes {} - -impl StaticNodes { pub(crate) fn set(&mut self, nodes: Vec) -> Result<(), Error> { if nodes.is_empty() { return Err(error::request(error::message( @@ -60,6 +48,16 @@ impl StaticNodes { Ok(()) } + /** + Gets the next node to use, based on the strategy provided at creation. + */ + pub fn next(&self) -> Result { + self.strategy + .try_next(&self.nodes) + .map(|address| RequestParams::from_parts(address, self.params.clone())) + .map_err(error::request) + } + #[cfg(test)] pub(crate) fn get(&self) -> &[NodeAddress] { &self.nodes @@ -138,7 +136,6 @@ impl Strategy for RoundRobin { #[cfg(test)] mod tests { use super::*; - use crate::http::sender::NextParams; fn round_robin(addresses: Vec<&'static str>) -> StaticNodes { StaticNodes::round_robin(addresses, PreRequestParams::default()) diff --git a/src/elastic/src/http/sender/synchronous.rs b/src/elastic/src/http/sender/synchronous.rs index 4df4db43e1..31ea92df97 100644 --- a/src/elastic/src/http/sender/synchronous.rs +++ b/src/elastic/src/http/sender/synchronous.rs @@ -8,6 +8,10 @@ use std::{ }; use crate::{ + client::{ + responses::nodes_info::NodesInfoResponse, + requests::RequestInner, + }, endpoints::Endpoint, error::{ self, @@ -19,21 +23,20 @@ use crate::{ SyncResponseBuilder, }, sender::{ - build_reqwest_method, + build_http_method, build_url, - NextParams, NodeAddresses, - NodeAddressesInner, RequestParams, SendableRequest, SendableRequestParams, Sender, + sniffed_nodes::NextOrRefresh, + TypedSender, }, SyncBody, SyncHttpRequest, Url, }, - private, }; pub(crate) type SyncPreSend = @@ -46,8 +49,6 @@ pub struct SyncSender { pub(crate) pre_send: Option>, } -impl private::Sealed for SyncSender {} - impl Sender for SyncSender { type Body = SyncBody; type Response = Result; @@ -129,18 +130,48 @@ impl Sender for SyncSender { sync_response(res) } -} - -impl NextParams for NodeAddresses { - type Params = Params; - fn next(&self) -> Self::Params { - match self.inner { - NodeAddressesInner::Static(ref nodes) => Params::new(nodes.next()), - NodeAddressesInner::Sniffed(ref sniffer) => Params::new(sniffer.next()), + fn next_params( + &self, + addresses: &NodeAddresses, + ) -> Self::Params { + match addresses { + NodeAddresses::Static(ref nodes) => Params::new(nodes.next()), + NodeAddresses::Sniffed(ref sniffer) => { + let refresher = match sniffer.next_or_start_refresh() { + Ok(NextOrRefresh::Next(address)) => { return Params::new(Ok(address)); }, + Ok(NextOrRefresh::NeedsRefresh(r)) => r, + Err(err) => { return Params::new(Err(err)); } + }; + + // Perform the refresh + let req = sniffer.sendable_request(); + let fresh_nodes = self + .send(req) + .and_then(|res| res.into_response::()); + Params::new(refresher.update_nodes_and_next(fresh_nodes)) + } } } } +impl TypedSender for SyncSender +where + TReqInner: RequestInner, +{ + type TypedResponse = Result; + fn typed_send( + &self, + request: Result, Error>, + ) -> Self::TypedResponse + where + TEndpoint: Into>, + TBody: Into + Send + 'static, + TParams: Into + Send + 'static, + { + let sendable_req = request?; + self.send(sendable_req).and_then(|resp| resp.into_response()) + } +} /** A set of parameters returned by calling `next` on a sync set of `NodeAddresses`. */ pub struct Params { @@ -184,7 +215,7 @@ fn build_reqwest(client: &SyncHttpClient, req: SyncHttpRequest) -> SyncHttpReque .. } = req; - let method = build_reqwest_method(method); + let method = build_http_method(method); let mut req = client.request(method, url); { diff --git a/src/elastic/src/lib.rs b/src/elastic/src/lib.rs index a3128f0d1a..5ce77379ee 100644 --- a/src/elastic/src/lib.rs +++ b/src/elastic/src/lib.rs @@ -257,8 +257,10 @@ for hit in response.hits() { #[macro_use] extern crate error_chain; +#[cfg(feature="async_sender")] #[macro_use] extern crate futures; +#[cfg(any(feature="async_sender", feature="sync_sender"))] #[macro_use] extern crate log; #[macro_use] @@ -303,6 +305,7 @@ pub mod endpoints { pub use super::genned::{ endpoints::*, http::Endpoint, + http::IntoEndpoint, }; } @@ -316,13 +319,12 @@ pub mod client; pub mod http; pub mod types; -pub use self::{ - client::{ - AsyncClient, - SyncClient, - }, - error::Error, -}; +#[cfg(feature="async_sender")] +pub use self::client::AsyncClient; +#[cfg(feature="sync_sender")] +pub use self::client::SyncClient; + +pub use self::error::Error; pub mod prelude { /*! A glob import for convenience. */ diff --git a/tools/generate_requests/src/gen/endpoints/into_endpoint.rs b/tools/generate_requests/src/gen/endpoints/into_endpoint.rs index 1441756864..0370563801 100644 --- a/tools/generate_requests/src/gen/endpoints/into_endpoint.rs +++ b/tools/generate_requests/src/gen/endpoints/into_endpoint.rs @@ -47,6 +47,12 @@ impl Builder { quote!( impl <'a, #generic_body> Into<#endpoint_ty<'a, #generic_body> > for #req_ty { fn into(self) -> #endpoint_ty<'a, #generic_body> { + self.into_endpoint() + } + } + impl<'a, #generic_body> IntoEndpoint<'a> for #req_ty { + type BodyType = #generic_body; + fn into_endpoint(self) -> #endpoint_ty<'a, Self::BodyType> { #endpoint_ty { url: self.url, method: #method, @@ -61,6 +67,12 @@ impl Builder { quote!( impl <'a> Into<#endpoint_ty<'a, #default_body> > for #req_ty { fn into(self) -> #endpoint_ty<'a, #default_body> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for #req_ty { + type BodyType = #default_body; + fn into_endpoint(self) -> #endpoint_ty<'a, Self::BodyType> { #endpoint_ty { url: self.url, method: #method, @@ -109,6 +121,12 @@ mod tests { let expected = quote!( impl<'a, B> Into > for Request<'a, B> { fn into(self) -> Endpoint<'a, B> { + self.into_endpoint() + } + } + impl<'a, B> IntoEndpoint<'a> for Request<'a, B> { + type BodyType = B; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, @@ -139,6 +157,12 @@ mod tests { let expected = quote!( impl<'a> Into > for Request<'a> { fn into(self) -> Endpoint<'a, DefaultBody> { + self.into_endpoint() + } + } + impl<'a> IntoEndpoint<'a> for Request<'a> { + type BodyType = DefaultBody; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType> { Endpoint { url: self.url, method: Method::GET, diff --git a/tools/generate_requests/src/gen/http/into_endpoint.rs b/tools/generate_requests/src/gen/http/into_endpoint.rs new file mode 100644 index 0000000000..f0aff9148e --- /dev/null +++ b/tools/generate_requests/src/gen/http/into_endpoint.rs @@ -0,0 +1,24 @@ +use crate::gen::helpers; +use quote; +use syn; + +pub fn ident() -> &'static str { + "IntoEndpoint" +} + +pub fn ty() -> syn::Ty { + helpers::ty(ident()) +} + +pub fn tokens() -> quote::Tokens { + quote!( + /// Trait for converting a request into its endpoint. + /// + /// Like `From`, but the client API doesn't need to know the exact + /// type to convert into. + pub trait IntoEndpoint<'a> { + type BodyType; + fn into_endpoint(self) -> Endpoint<'a, Self::BodyType>; + } + ) +} diff --git a/tools/generate_requests/src/gen/http/mod.rs b/tools/generate_requests/src/gen/http/mod.rs index 5f7c6bcc1a..7676d54f8f 100644 --- a/tools/generate_requests/src/gen/http/mod.rs +++ b/tools/generate_requests/src/gen/http/mod.rs @@ -1,4 +1,5 @@ pub mod body; pub mod endpoint; +pub mod into_endpoint; pub mod method; pub mod url; diff --git a/tools/generate_requests/src/main.rs b/tools/generate_requests/src/main.rs index 7b9c691a0f..750ebb19df 100644 --- a/tools/generate_requests/src/main.rs +++ b/tools/generate_requests/src/main.rs @@ -3,7 +3,6 @@ #[macro_use] extern crate quote; -#[allow(unused_imports)] #[macro_use] extern crate serde_derive; @@ -252,11 +251,13 @@ fn http_mod(tokens: &mut Tokens) { let http_req_item = gen::http::endpoint::tokens(); + let into_endpoint_tokens = gen::http::into_endpoint::tokens(); + tokens.append(header); tokens.append("\n\n"); - tokens.append_all(vec![url_tokens, http_req_item, body_tokens]); + tokens.append_all(vec![url_tokens, http_req_item, into_endpoint_tokens, body_tokens]); } fn params_mod(tokens: &mut Tokens, params_to_emit: BTreeMap) { diff --git a/tools/generate_requests/src/parse/mod.rs b/tools/generate_requests/src/parse/mod.rs index 99b8aaf79b..729d6f383d 100644 --- a/tools/generate_requests/src/parse/mod.rs +++ b/tools/generate_requests/src/parse/mod.rs @@ -70,6 +70,19 @@ pub enum Method { #[serde(rename = "DELETE")] Delete, } +impl Method { + /// Converts the enum to the method name as a string + pub fn to_name(self) -> &'static str { + match self { + Method::Head => "HEAD", + Method::Get => "GET", + Method::Post => "POST", + Method::Put => "PUT", + Method::Patch => "PATCH", + Method::Delete => "DELETE", + } + } +} #[derive(Debug, PartialEq, Deserialize, Clone)] pub struct Url {