bazzar/crates/channels/src/search.rs

243 lines
6.1 KiB
Rust
Raw Normal View History

2022-11-05 19:04:38 +01:00
#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
2022-11-05 12:31:18 +01:00
pub enum Error {
#[error("Can't create index")]
CantCreate,
#[error("Failed to find records in bucket")]
QueryFailed,
}
pub type Result<T> = std::result::Result<T, Error>;
#[allow(clippy::module_inception)]
2022-11-05 12:31:18 +01:00
pub mod search {
use crate::search::create_index::Lang;
2022-11-05 12:31:18 +01:00
use crate::search::Error;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Input {
pub query: String,
pub bucket: String,
2022-11-05 12:31:18 +01:00
pub collection: String,
pub lang: Lang,
}
impl Input {
pub fn new<Q: Into<String>, B: Into<String>, C: Into<String>>(
query: Q,
collection: C,
bucket: B,
lang: whatlang::Lang,
) -> Self {
Self {
query: query.into(),
bucket: bucket.into(),
collection: collection.into(),
lang: Lang(lang),
}
}
}
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct Output {
pub found: Option<Vec<String>>,
pub error: Option<Error>,
}
impl Output {
pub fn found(found: Vec<String>) -> Self {
Self {
found: Some(found),
..Default::default()
}
}
pub fn error(error: Error) -> Self {
Self {
error: Some(error),
..Default::default()
}
}
}
}
pub mod suggest {
use crate::search::Error;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Input {
pub query: String,
pub bucket: String,
pub collection: String,
}
impl Input {
pub fn new<Q: Into<String>, B: Into<String>, C: Into<String>>(
query: Q,
collection: C,
bucket: B,
) -> Self {
Self {
query: query.into(),
bucket: bucket.into(),
collection: collection.into(),
}
}
2022-11-05 12:31:18 +01:00
}
2022-11-05 19:04:38 +01:00
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
2022-11-05 12:31:18 +01:00
pub struct Output {
pub found: Option<Vec<String>>,
2022-11-05 19:04:38 +01:00
pub error: Option<Error>,
}
impl Output {
pub fn found(found: Vec<String>) -> Self {
Self {
found: Some(found),
..Default::default()
}
}
pub fn error(error: Error) -> Self {
Self {
error: Some(error),
..Default::default()
}
}
2022-11-05 12:31:18 +01:00
}
}
pub mod create_index {
use std::fmt::Formatter;
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
2022-11-05 12:31:18 +01:00
use crate::search::Error;
#[derive(Debug)]
pub struct Lang(pub whatlang::Lang);
impl Serialize for Lang {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.0.code())
}
}
impl<'de> Deserialize<'de> for Lang {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct SV;
impl Visitor<'_> for SV {
type Value = whatlang::Lang;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("must be valid whatlang::Lang")
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match v.parse() {
Ok(l) => Ok(l),
Err(e) => Err(E::custom(format!("{}", e))),
}
}
}
Ok(Self(deserializer.deserialize_string(SV)?))
}
}
2022-11-05 12:31:18 +01:00
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Input {
pub key: String,
pub value: String,
pub bucket: String,
2022-11-05 12:31:18 +01:00
pub collection: String,
pub lang: Lang,
}
impl Input {
pub fn new<K: Into<String>, V: Into<String>, B: Into<String>, C: Into<String>>(
key: K,
value: V,
collection: C,
bucket: B,
lang: whatlang::Lang,
) -> Self {
Self {
key: key.into(),
value: value.into(),
bucket: bucket.into(),
collection: collection.into(),
lang: Lang(lang),
}
}
2022-11-05 12:31:18 +01:00
}
2022-11-05 19:04:38 +01:00
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
2022-11-05 12:31:18 +01:00
pub struct Output {
pub found: Option<()>,
2022-11-05 19:04:38 +01:00
pub error: Option<Error>,
}
impl Output {
pub fn ok() -> Self {
Self {
found: Some(()),
..Default::default()
}
}
pub fn error(error: Error) -> Self {
Self {
error: Some(error),
..Default::default()
}
}
}
}
pub mod rpc {
use config::SharedAppConfig;
use crate::search::{create_index, search, suggest};
2022-11-05 19:04:38 +01:00
#[tarpc::service]
pub trait Search {
/// Search all matching indices.
async fn search(input: search::Input) -> search::Output;
/// Suggest all matching indices.
async fn suggest(input: suggest::Input) -> suggest::Output;
2022-11-05 19:04:38 +01:00
/// Create new search index.
async fn create_index(input: create_index::Input) -> create_index::Output;
}
pub async fn create_client(config: SharedAppConfig) -> SearchClient {
use tarpc::client;
use tarpc::tokio_serde::formats::Bincode;
let l = config.lock();
let transport =
tarpc::serde_transport::tcp::connect(l.search().rpc_addr(), Bincode::default);
let client = SearchClient::new(
client::Config::default(),
transport.await.expect("Failed to connect to search server"),
)
.spawn();
client
2022-11-05 12:31:18 +01:00
}
}