From 9ebbf7d038d74d1c5673559661db7c2e8af125ac Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Fri, 7 Aug 2020 02:03:11 +0300 Subject: [PATCH] feat: add count method --- src/channel.rs | 80 ++++++++++++++++++++++++++++++++++++++++- src/commands/count.rs | 40 +++++++++++++++++++++ src/commands/flush.rs | 4 +-- src/commands/mod.rs | 4 +++ src/commands/ping.rs | 6 +++- src/commands/pop.rs | 4 +-- src/commands/push.rs | 9 +++-- src/commands/query.rs | 4 +-- src/commands/quit.rs | 8 +++-- src/commands/suggest.rs | 4 +-- src/result.rs | 13 +++++-- 11 files changed, 156 insertions(+), 20 deletions(-) create mode 100644 src/commands/count.rs diff --git a/src/channel.rs b/src/channel.rs index 613f274..b199306 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -428,6 +428,84 @@ impl SonicChannel { bucket: &'a str => Some(bucket), object: &'a str => Some(object), ); + + #[doc=r#" + Bucket count in indexed search data of your collection. + + Note: This method requires enabling the `ingest` feature and start + connection in Ingest mode. + + ```rust,no_run + # use sonic_channel::*; + # fn main() -> result::Result<()> { + let ingest_channel = SonicChannel::connect_with_start( + ChannelMode::Ingest, + "localhost:1491", + "SecretPassword", + )?; + + let bucket_count = ingest_channel.bucket_count("search")?; + dbg!(bucket_count); + # Ok(()) + # } + ``` + "#] + use CountCommand for fn bucket_count<'a>( + collection: &'a str, + ); + + #[doc=r#" + Object count of bucket in indexed search data. + + Note: This method requires enabling the `ingest` feature and start + connection in Ingest mode. + + ```rust,no_run + # use sonic_channel::*; + # fn main() -> result::Result<()> { + let ingest_channel = SonicChannel::connect_with_start( + ChannelMode::Ingest, + "localhost:1491", + "SecretPassword", + )?; + + let object_count = ingest_channel.object_count("search", "default")?; + dbg!(object_count); + # Ok(()) + # } + ``` + "#] + use CountCommand for fn object_count<'a>( + collection: &'a str, + bucket: &'a str => Some(bucket), + ); + + #[doc=r#" + Object word count in indexed bucket search data. + + Note: This method requires enabling the `ingest` feature and start + connection in Ingest mode. + + ```rust,no_run + # use sonic_channel::*; + # fn main() -> result::Result<()> { + let ingest_channel = SonicChannel::connect_with_start( + ChannelMode::Ingest, + "localhost:1491", + "SecretPassword", + )?; + + let word_count = ingest_channel.word_count("search", "default", "recipe:296")?; + dbg!(word_count); + # Ok(()) + # } + ``` + "#] + use CountCommand for fn word_count<'a>( + collection: &'a str, + bucket: &'a str => Some(bucket), + object: &'a str => Some(object), + ); } #[cfg(feature = "search")] @@ -572,7 +650,7 @@ impl SonicChannel { "SecretPassword", )?; - let result = ingest_channel.suggest("search", "default", "Beef", 5)?; + let result = ingest_channel.suggest_with_limit("search", "default", "Beef", 5)?; dbg!(result); # Ok(()) # } diff --git a/src/commands/count.rs b/src/commands/count.rs new file mode 100644 index 0000000..e888e60 --- /dev/null +++ b/src/commands/count.rs @@ -0,0 +1,40 @@ +use super::StreamCommand; +use crate::result::*; + +#[doc(hidden)] +#[derive(Debug, Default)] +pub struct CountCommand<'a> { + pub collection: &'a str, + pub bucket: Option<&'a str>, + pub object: Option<&'a str>, +} + +impl StreamCommand for CountCommand<'_> { + type Response = usize; + + fn message(&self) -> String { + let mut message = format!("COUNT {}", self.collection); + if let Some(bucket) = self.bucket { + message.push_str(&format!(" {}", bucket)); + + if let Some(object) = self.object { + message.push_str(&format!(" {}", object)); + } + } + message.push_str("\r\n"); + message + } + + fn receive(&self, message: String) -> Result { + if message.starts_with("RESULT ") { + let count = message.split_whitespace().last().unwrap_or_default(); + count.parse().map_err(|_| { + Error::new(ErrorKind::QueryResponseError( + "Cannot parse count of count method response to usize", + )) + }) + } else { + Err(Error::new(ErrorKind::WrongSonicResponse)) + } + } +} diff --git a/src/commands/flush.rs b/src/commands/flush.rs index 8c981c0..c03efa7 100644 --- a/src/commands/flush.rs +++ b/src/commands/flush.rs @@ -33,9 +33,7 @@ impl StreamCommand for FlushCommand<'_> { )) }) } else { - Err(Error::new(ErrorKind::QueryResponseError( - "Sonic response are wrong. Please write issue to github.", - ))) + Err(Error::new(ErrorKind::WrongSonicResponse)) } } } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index f595631..0357493 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -3,6 +3,8 @@ mod start; mod ping; +#[cfg(feature = "ingest")] +mod count; #[cfg(feature = "ingest")] mod flush; #[cfg(feature = "ingest")] @@ -20,6 +22,8 @@ pub(crate) use start::StartCommand; pub(crate) use ping::PingCommand; +#[cfg(feature = "ingest")] +pub(crate) use count::CountCommand; #[cfg(feature = "ingest")] pub(crate) use flush::FlushCommand; #[cfg(feature = "ingest")] diff --git a/src/commands/ping.rs b/src/commands/ping.rs index 88ff755..ab84f8f 100644 --- a/src/commands/ping.rs +++ b/src/commands/ping.rs @@ -13,6 +13,10 @@ impl StreamCommand for PingCommand { fn receive(&self, message: String) -> Result { dbg!(&message); - Ok(message == "PONG\r\n") + if message == "PONG\r\n" { + Ok(true) + } else { + Err(Error::new(ErrorKind::WrongSonicResponse)) + } } } diff --git a/src/commands/pop.rs b/src/commands/pop.rs index dc5dff2..0cecad3 100644 --- a/src/commands/pop.rs +++ b/src/commands/pop.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::result::{Error, ErrorKind, Result}; +use crate::result::*; #[derive(Debug, Default)] pub struct PopCommand<'a> { @@ -31,7 +31,7 @@ impl StreamCommand for PopCommand<'_> { ))) } else { - Err(Error::new(ErrorKind::QueryResponseError("Cannot parse result"))) + Err(Error::new(ErrorKind::WrongSonicResponse)) } } } diff --git a/src/commands/push.rs b/src/commands/push.rs index 3cad05a..a6aa5bd 100644 --- a/src/commands/push.rs +++ b/src/commands/push.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::result::Result; +use crate::result::*; #[derive(Debug, Default)] pub struct PushCommand<'a> { @@ -27,6 +27,11 @@ impl StreamCommand for PushCommand<'_> { fn receive(&self, message: String) -> Result { dbg!(&message); - Ok(message == "OK\r\n") + + if message == "OK\r\n" { + Ok(true) + } else { + Err(Error::new(ErrorKind::WrongSonicResponse)) + } } } diff --git a/src/commands/query.rs b/src/commands/query.rs index 410b2b0..9b33ecc 100644 --- a/src/commands/query.rs +++ b/src/commands/query.rs @@ -44,9 +44,7 @@ impl StreamCommand for QueryCommand<'_> { dbg!(&message); match RE.captures(&message) { - None => Err(Error::new(ErrorKind::QueryResponseError( - "Sonic response are wrong. Please write issue to github.", - ))), + None => Err(Error::new(ErrorKind::WrongSonicResponse)), Some(caps) => { if &caps["pending_query_id"] != &caps["event_query_id"] { Err(Error::new(ErrorKind::QueryResponseError( diff --git a/src/commands/quit.rs b/src/commands/quit.rs index ae8cad4..77bb16b 100644 --- a/src/commands/quit.rs +++ b/src/commands/quit.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::result::Result; +use crate::result::*; #[derive(Debug, Default)] pub struct QuitCommand; @@ -13,6 +13,10 @@ impl StreamCommand for QuitCommand { fn receive(&self, message: String) -> Result { dbg!(&message); - Ok(message.starts_with("ENDED ")) + if message.starts_with("ENDED ") { + Ok(true) + } else { + Err(Error::new(ErrorKind::WrongSonicResponse)) + } } } diff --git a/src/commands/suggest.rs b/src/commands/suggest.rs index ea14dbc..8f0619b 100644 --- a/src/commands/suggest.rs +++ b/src/commands/suggest.rs @@ -40,9 +40,7 @@ impl StreamCommand for SuggestCommand<'_> { dbg!(&message); match RE.captures(&message) { - None => Err(Error::new(ErrorKind::QueryResponseError( - "Sonic response are wrong. Please write issue to github.", - ))), + None => Err(Error::new(ErrorKind::WrongSonicResponse)), Some(caps) => { if &caps["pending_suggest_id"] != &caps["event_suggest_id"] { Err(Error::new(ErrorKind::QueryResponseError( diff --git a/src/result.rs b/src/result.rs index e5064c4..af03bb8 100644 --- a/src/result.rs +++ b/src/result.rs @@ -4,7 +4,7 @@ use std::fmt; /// Sugar if you expect only sonic-channel error type in result pub type Result = std::result::Result; -/// Wrap for sonic channel error kind. This type has std::error::Error +/// Wrap for sonic channel error kind. This type has std::error::Error /// implementation and you can use boxed trait for catch other errors /// like this. #[derive(Debug)] @@ -16,10 +16,10 @@ impl StdError for Error {} impl Error { /// Creates new Error with sonic channel error kind - /// + /// /// ```rust /// use sonic_channel::result::*; - /// + /// /// let err = Error::new(ErrorKind::ConnectToServer); /// ``` pub fn new(kind: ErrorKind) -> Self { @@ -47,6 +47,10 @@ pub enum ErrorKind { /// Error in query response with additional message. QueryResponseError(&'static str), + + /// Response from sonic server are wrong! Actually it may happen if you use + /// unsupported sonic backend version. Please write issue to the github repo. + WrongSonicResponse, } impl fmt::Display for Error { @@ -60,6 +64,9 @@ impl fmt::Display for Error { ErrorKind::QueryResponseError(message) => { write!(f, "Error in query response: {}", message) } + ErrorKind::WrongSonicResponse => { + write!(f, "Sonic response are wrong. Please write issue to github.") + } } } }