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>;
|
|
|
|
|
2022-11-06 19:50:51 +01:00
|
|
|
#[allow(clippy::module_inception)]
|
2022-11-05 12:31:18 +01:00
|
|
|
pub mod search {
|
2022-11-06 19:50:51 +01:00
|
|
|
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,
|
2022-11-06 19:50:51 +01:00
|
|
|
pub bucket: String,
|
2022-11-05 12:31:18 +01:00
|
|
|
pub collection: String,
|
2022-11-06 19:50:51 +01:00
|
|
|
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 {
|
2022-11-06 19:50:51 +01:00
|
|
|
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;
|
|
|
|
|
2022-11-06 19:50:51 +01:00
|
|
|
#[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,
|
2022-11-06 19:50:51 +01:00
|
|
|
pub bucket: String,
|
2022-11-05 12:31:18 +01:00
|
|
|
pub collection: String,
|
2022-11-06 19:50:51 +01:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
pub mod delete_index {
|
|
|
|
use crate::search::Error;
|
|
|
|
|
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
|
|
pub struct Input {
|
|
|
|
pub key: String,
|
|
|
|
pub value: String,
|
|
|
|
pub bucket: String,
|
|
|
|
pub collection: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
key: key.into(),
|
|
|
|
value: value.into(),
|
|
|
|
bucket: bucket.into(),
|
|
|
|
collection: collection.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
|
|
|
|
pub struct Output {
|
|
|
|
pub found: Option<()>,
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-05 19:04:38 +01:00
|
|
|
pub mod rpc {
|
|
|
|
use config::SharedAppConfig;
|
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
use crate::search::{create_index, delete_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;
|
|
|
|
|
2022-11-06 19:50:51 +01:00
|
|
|
/// 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;
|
2022-11-07 16:28:51 +01:00
|
|
|
|
|
|
|
/// Delete search index.
|
|
|
|
async fn delete_index(input: delete_index::Input) -> delete_index::Output;
|
2022-11-05 19:04:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|