WIP jayson integration

This commit is contained in:
Loïc Lecrenier 2022-06-21 15:41:28 +02:00
parent 4c1f034d9f
commit ff564f6d05
4 changed files with 47 additions and 27 deletions

View File

@ -1,7 +1,7 @@
use actix_web::{dev::Payload, web::Json, FromRequest, HttpRequest}; use actix_web::{dev::Payload, web::Json, FromRequest, HttpRequest};
use futures::ready; use futures::ready;
use jayson::{DeserializeError, DeserializeFromValue}; use jayson::{DeserializeError, DeserializeFromValue};
use meilisearch_types::error::{Code, ErrorCode, ResponseError}; use meilisearch_types::error::{ErrorCode, ResponseError};
use std::{ use std::{
fmt::Debug, fmt::Debug,
future::Future, future::Future,
@ -34,7 +34,7 @@ where
E: DeserializeError + ErrorCode + 'static, E: DeserializeError + ErrorCode + 'static,
T: DeserializeFromValue<E>, T: DeserializeFromValue<E>,
{ {
type Error = ResponseError; type Error = actix_web::Error;
type Future = ValidatedJsonExtractFut<T, E>; type Future = ValidatedJsonExtractFut<T, E>;
#[inline] #[inline]
@ -56,7 +56,7 @@ where
T: DeserializeFromValue<E>, T: DeserializeFromValue<E>,
E: DeserializeError + ErrorCode + 'static, E: DeserializeError + ErrorCode + 'static,
{ {
type Output = Result<ValidatedJson<T, E>, ResponseError>; type Output = Result<ValidatedJson<T, E>, actix_web::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut(); let this = self.get_mut();
@ -64,13 +64,10 @@ where
let res = ready!(Pin::new(&mut this.fut).poll(cx)); let res = ready!(Pin::new(&mut this.fut).poll(cx));
let res = match res { let res = match res {
Err(err) => Err(ResponseError::from_msg( Err(err) => Err(err),
format!("{err}"),
Code::MalformedPayload,
)),
Ok(data) => match jayson::deserialize::<_, _, E>(data.into_inner()) { Ok(data) => match jayson::deserialize::<_, _, E>(data.into_inner()) {
Ok(data) => Ok(ValidatedJson::new(data)), Ok(data) => Ok(ValidatedJson::new(data)),
Err(e) => Err(e.into()), Err(e) => Err(ResponseError::from(e).into()),
}, },
}; };

View File

@ -1,5 +1,9 @@
use log::debug; use log::debug;
use crate::analytics::Analytics;
use crate::extractors::authentication::{policies::*, GuardedData};
use crate::extractors::jayson::ValidatedJson;
use crate::task::SummarizedTaskView;
use actix_web::{web, HttpRequest, HttpResponse}; use actix_web::{web, HttpRequest, HttpResponse};
use meilisearch_lib::index::Settings; use meilisearch_lib::index::Settings;
use meilisearch_lib::index_controller::Update; use meilisearch_lib::index_controller::Update;
@ -7,11 +11,6 @@ use meilisearch_lib::MeiliSearch;
use meilisearch_types::error::{MeiliDeserError, ResponseError}; use meilisearch_types::error::{MeiliDeserError, ResponseError};
use serde_json::json; use serde_json::json;
use crate::analytics::Analytics;
use crate::extractors::authentication::{policies::*, GuardedData};
use crate::extractors::jayson::ValidatedJson;
use crate::task::SummarizedTaskView;
#[macro_export] #[macro_export]
macro_rules! make_setting_route { macro_rules! make_setting_route {
($route:literal, $update_verb:ident, $type:ty, $attr:ident, $camelcase_attr:literal, $analytics_var:ident, $analytics:expr) => { ($route:literal, $update_verb:ident, $type:ty, $attr:ident, $camelcase_attr:literal, $analytics_var:ident, $analytics:expr) => {
@ -55,7 +54,10 @@ macro_rules! make_setting_route {
pub async fn update( pub async fn update(
meilisearch: GuardedData<ActionPolicy<{ actions::SETTINGS_UPDATE }>, MeiliSearch>, meilisearch: GuardedData<ActionPolicy<{ actions::SETTINGS_UPDATE }>, MeiliSearch>,
index_uid: actix_web::web::Path<String>, index_uid: actix_web::web::Path<String>,
body: actix_web::web::Json<Option<$type>>, body: crate::extractors::jayson::ValidatedJson<
Option<$type>,
meilisearch_types::error::MeiliDeserError,
>,
req: HttpRequest, req: HttpRequest,
$analytics_var: web::Data<dyn Analytics>, $analytics_var: web::Data<dyn Analytics>,
) -> std::result::Result<HttpResponse, ResponseError> { ) -> std::result::Result<HttpResponse, ResponseError> {

View File

@ -36,7 +36,7 @@ pub mod test {
use super::error::Result; use super::error::Result;
use super::index::Index; use super::index::Index;
use super::Document; use super::Document;
use super::{Checked, IndexMeta, IndexStats, SearchQuery, SearchResult, Settings}; use super::{IndexMeta, IndexStats, SearchQuery, SearchResult, Settings};
use crate::update_file_store::UpdateFileStore; use crate::update_file_store::UpdateFileStore;
#[derive(Clone)] #[derive(Clone)]

View File

@ -67,6 +67,7 @@ pub struct TypoSettings {
#[cfg_attr(test, derive(proptest_derive::Arbitrary))] #[cfg_attr(test, derive(proptest_derive::Arbitrary))]
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, DeserializeFromValue)] #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, DeserializeFromValue)]
#[jayson(rename_all = camelCase, deny_unknown_fields)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct FacetingSettings { pub struct FacetingSettings {
@ -79,6 +80,7 @@ pub struct FacetingSettings {
#[derive( #[derive(
Debug, Clone, Default, Serialize, Deserialize, PartialEq, jayson::DeserializeFromValue, Debug, Clone, Default, Serialize, Deserialize, PartialEq, jayson::DeserializeFromValue,
)] )]
#[jayson(rename_all = camelCase, deny_unknown_fields)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PaginationSettings { pub struct PaginationSettings {
@ -92,10 +94,10 @@ pub struct PaginationSettings {
#[derive( #[derive(
Debug, Clone, Default, Serialize, Deserialize, PartialEq, jayson::DeserializeFromValue, Debug, Clone, Default, Serialize, Deserialize, PartialEq, jayson::DeserializeFromValue,
)] )]
#[jayson(rename_all = camelCase, deny_unknown_fields)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))] #[cfg_attr(test, derive(proptest_derive::Arbitrary))]
#[jayson(rename_all = camelCase, deny_unknown_fields)]
pub struct Settings { pub struct Settings {
#[serde( #[serde(
default, default,
@ -122,7 +124,7 @@ pub struct Settings {
#[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))]
pub sortable_attributes: Setting<BTreeSet<String>>, pub sortable_attributes: Setting<BTreeSet<String>>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")] #[serde(default, skip_serializing_if = "Setting::is_not_set")]
#[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[cfg_attr(test, proptest(strategy = "test::criteria_setting_strategy()"))]
#[jayson(needs_predicate)] #[jayson(needs_predicate)]
pub ranking_rules: Setting<Vec<Criterion>>, pub ranking_rules: Setting<Vec<Criterion>>,
#[serde(default, skip_serializing_if = "Setting::is_not_set")] #[serde(default, skip_serializing_if = "Setting::is_not_set")]
@ -162,9 +164,7 @@ impl Settings {
} }
} }
} }
pub fn map_searchable_or_displayed_attributes( fn map_searchable_or_displayed_attributes(setting: Setting<Vec<String>>) -> Setting<Vec<String>> {
setting: Setting<Vec<String>>,
) -> Setting<Vec<String>> {
match setting { match setting {
Setting::Set(fields) => { Setting::Set(fields) => {
if fields.iter().any(|f| f == "*") { if fields.iter().any(|f| f == "*") {
@ -422,10 +422,33 @@ pub fn apply_settings_to_builder(settings: &Settings, builder: &mut milli::updat
#[cfg(test)] #[cfg(test)]
pub(crate) mod test { pub(crate) mod test {
use super::*;
use milli::Criterion;
use proptest::prelude::*; use proptest::prelude::*;
use super::*; fn criteria_strategy() -> impl Strategy<Value = Vec<Criterion>> {
proptest::collection::vec(
prop_oneof![
Just(Criterion::Words),
Just(Criterion::Typo),
Just(Criterion::Proximity),
Just(Criterion::Attribute),
Just(Criterion::Sort),
Just(Criterion::Exactness),
any::<String>().prop_map(Criterion::Asc),
any::<String>().prop_map(Criterion::Desc),
],
0..100,
)
}
pub(super) fn criteria_setting_strategy() -> impl Strategy<Value = Setting<Vec<Criterion>>> {
prop_oneof![
Just(Setting::NotSet),
Just(Setting::Reset),
criteria_strategy().prop_map(Setting::Set),
]
}
pub(super) fn setting_strategy<T: Arbitrary + Clone>() -> impl Strategy<Value = Setting<T>> { pub(super) fn setting_strategy<T: Arbitrary + Clone>() -> impl Strategy<Value = Setting<T>> {
prop_oneof![ prop_oneof![
Just(Setting::NotSet), Just(Setting::NotSet),
@ -451,11 +474,10 @@ pub(crate) mod test {
pagination: Setting::NotSet, pagination: Setting::NotSet,
}; };
let checked = settings.clone().check(); assert_eq!(settings.displayed_attributes, settings.displayed_attributes);
assert_eq!(settings.displayed_attributes, checked.displayed_attributes);
assert_eq!( assert_eq!(
settings.searchable_attributes, settings.searchable_attributes,
checked.searchable_attributes settings.searchable_attributes
); );
// test wildcard // test wildcard
@ -474,8 +496,7 @@ pub(crate) mod test {
pagination: Setting::NotSet, pagination: Setting::NotSet,
}; };
let checked = settings.check(); assert_eq!(settings.displayed_attributes, Setting::Reset);
assert_eq!(checked.displayed_attributes, Setting::Reset); assert_eq!(settings.searchable_attributes, Setting::Reset);
assert_eq!(checked.searchable_attributes, Setting::Reset);
} }
} }