refactor errors / isolate core/http errors

This commit is contained in:
mpostma 2020-05-22 12:03:57 +02:00
parent e2db197b3f
commit d69180ec67
29 changed files with 585 additions and 480 deletions

View file

@ -2,20 +2,14 @@ use std::collections::HashMap;
use std::ops::Deref;
use std::sync::Arc;
use chrono::{DateTime, Utc};
use heed::types::{SerdeBincode, Str};
use log::error;
use meilisearch_core::{Database, DatabaseOptions, Error as MError, MResult, MainT, UpdateT};
use meilisearch_core::{Database, DatabaseOptions, MResult, MainT, UpdateT};
use sha2::Digest;
use sysinfo::Pid;
use crate::index_update_callback;
use crate::option::Opt;
const LAST_UPDATE_KEY: &str = "last-update";
type SerdeDatetime = SerdeBincode<DateTime<Utc>>;
#[derive(Clone)]
pub struct Data {
inner: Arc<DataInner>,
@ -70,24 +64,6 @@ impl DataInner {
}
}
pub fn last_update(&self, reader: &heed::RoTxn<MainT>) -> MResult<Option<DateTime<Utc>>> {
match self
.db
.common_store()
.get::<_, Str, SerdeDatetime>(reader, LAST_UPDATE_KEY)?
{
Some(datetime) => Ok(Some(datetime)),
None => Ok(None),
}
}
pub fn set_last_update(&self, writer: &mut heed::RwTxn<MainT>) -> MResult<()> {
self.db
.common_store()
.put::<_, Str, SerdeDatetime>(writer, LAST_UPDATE_KEY, &Utc::now())
.map_err(Into::into)
}
pub fn compute_stats(&self, writer: &mut heed::RwTxn<MainT>, index_uid: &str) -> MResult<()> {
let index = match self.db.open_index(&index_uid) {
Some(index) => index,
@ -124,7 +100,6 @@ impl DataInner {
index
.main
.put_fields_distribution(writer, &distribution)
.map_err(MError::Zlmdb)
}
}
@ -170,3 +145,4 @@ impl Data {
data
}
}

View file

@ -1,4 +1,5 @@
use std::fmt;
use std::error;
use actix_http::ResponseBuilder;
use actix_web as aweb;
@ -6,6 +7,25 @@ use actix_web::http::StatusCode;
use serde_json::json;
use actix_web::error::JsonPayloadError;
use meilisearch_error::{ErrorCode, Code};
#[derive(Debug)]
pub struct ResponseError {
inner: Box<dyn ErrorCode>,
}
impl fmt::Display for ResponseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl From<Error> for ResponseError {
fn from(error: Error) -> ResponseError {
ResponseError { inner: Box::new(error) }
}
}
#[derive(Debug)]
pub enum Error {
BadParameter(String, String),
@ -26,10 +46,18 @@ pub enum Error {
SearchDocuments(String),
PayloadTooLarge,
UnsupportedMediaType,
FacetExpression(String),
FacetCount(String),
}
impl error::Error for Error {}
impl ErrorCode for Error {
fn error_code(&self) -> Code {
//TODO populate with right error codes
Code::Other
}
}
#[derive(Debug)]
pub enum FacetCountError {
AttributeNotSet(String),
SyntaxError(String),
@ -37,6 +65,14 @@ pub enum FacetCountError {
NoFacetSet,
}
impl error::Error for FacetCountError {}
impl ErrorCode for FacetCountError {
fn error_code(&self) -> Code {
unimplemented!()
}
}
impl FacetCountError {
pub fn unexpected_token(found: impl ToString, expected: &'static [&'static str]) -> FacetCountError {
let found = found.to_string();
@ -137,94 +173,42 @@ impl fmt::Display for Error {
Self::InvalidIndexUid => f.write_str("Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."),
Self::InvalidToken(err) => write!(f, "Invalid API key: {}", err),
Self::Maintenance => f.write_str("Server is in maintenance, please try again later"),
Self::FilterParsing(err) => write!(f, "parsing error: {}", err),
Self::MissingAuthorizationHeader => f.write_str("You must have an authorization token"),
Self::MissingHeader(header) => write!(f, "Header {} is missing", header),
Self::NotFound(err) => write!(f, "{} not found", err),
Self::OpenIndex(err) => write!(f, "Impossible to open index; {}", err),
Self::RetrieveDocument(id, err) => write!(f, "impossible to retrieve the document with id: {}; {}", id, err),
Self::SearchDocuments(err) => write!(f, "impossible to search documents; {}", err),
Self::FacetExpression(e) => write!(f, "error parsing facet filter expression: {}", e),
Self::PayloadTooLarge => f.write_str("Payload to large"),
Self::UnsupportedMediaType => f.write_str("Unsupported media type"),
Self::FacetCount(e) => write!(f, "error with facet count: {}", e),
}
}
}
impl aweb::error::ResponseError for Error {
impl aweb::error::ResponseError for ResponseError {
fn error_response(&self) -> aweb::HttpResponse {
let error_code = self.inner.error_code().internal();
ResponseBuilder::new(self.status_code()).json(json!({
"message": self.to_string(),
"errorCode": error_code,
"errorLink": format!("docs.meilisearch.come/error/{}", error_code),
}))
}
fn status_code(&self) -> StatusCode {
match *self {
Self::BadParameter(_, _)
| Self::BadRequest(_)
| Self::CreateIndex(_)
| Self::InvalidIndexUid
| Self::OpenIndex(_)
| Self::RetrieveDocument(_, _)
| Self::FacetExpression(_)
| Self::SearchDocuments(_)
| Self::FacetCount(_)
| Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
Self::DocumentNotFound(_)
| Self::IndexNotFound(_)
| Self::NotFound(_) => StatusCode::NOT_FOUND,
Self::InvalidToken(_)
| Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN,
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE,
Self::PayloadTooLarge => StatusCode::PAYLOAD_TOO_LARGE,
Self::UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
}
self.inner.error_code().http()
}
}
impl From<meilisearch_core::HeedError> for Error {
fn from(err: meilisearch_core::HeedError) -> Error {
Error::Internal(err.to_string())
impl From<meilisearch_core::Error> for ResponseError {
fn from(err: meilisearch_core::Error) -> ResponseError {
ResponseError { inner: Box::new(err) }
}
}
impl From<meilisearch_core::FstError> for Error {
fn from(err: meilisearch_core::FstError) -> Error {
Error::Internal(err.to_string())
}
}
impl From<meilisearch_core::FacetError> for Error {
fn from(error: meilisearch_core::FacetError) -> Error {
Error::FacetExpression(error.to_string())
}
}
impl From<meilisearch_core::Error> for Error {
fn from(err: meilisearch_core::Error) -> Error {
use meilisearch_core::pest_error::LineColLocation::*;
match err {
meilisearch_core::Error::FilterParseError(e) => {
let (line, column) = match e.line_col {
Span((line, _), (column, _)) => (line, column),
Pos((line, column)) => (line, column),
};
let message = format!("parsing error on line {} at column {}: {}", line, column, e.variant.message());
Error::FilterParsing(message)
},
meilisearch_core::Error::FacetError(e) => Error::FacetExpression(e.to_string()),
_ => Error::Internal(err.to_string()),
}
}
}
impl From<meilisearch_schema::Error> for Error {
fn from(err: meilisearch_schema::Error) -> Error {
Error::Internal(err.to_string())
impl From<meilisearch_schema::Error> for ResponseError {
fn from(err: meilisearch_schema::Error) -> ResponseError {
ResponseError { inner: Box::new(err) }
}
}
@ -234,9 +218,9 @@ impl From<actix_http::Error> for Error {
}
}
impl From<FacetCountError> for Error {
fn from(other: FacetCountError) -> Error {
Error::FacetCount(other.to_string())
impl From<FacetCountError> for ResponseError {
fn from(err: FacetCountError) -> ResponseError {
ResponseError { inner: Box::new(err) }
}
}
@ -251,6 +235,7 @@ impl From<JsonPayloadError> for Error {
}
}
pub fn json_error_handler(err: JsonPayloadError) -> Error {
err.into()
pub fn json_error_handler(err: JsonPayloadError) -> ResponseError {
let error = Error::from(err);
error.into()
}

View file

@ -7,7 +7,7 @@ use actix_service::{Service, Transform};
use actix_web::{dev::ServiceRequest, dev::ServiceResponse};
use futures::future::{err, ok, Future, Ready};
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::Data;
#[derive(Clone)]
@ -71,10 +71,10 @@ where
let auth_header = match req.headers().get("X-Meili-API-Key") {
Some(auth) => match auth.to_str() {
Ok(auth) => auth,
Err(_) => return Box::pin(err(Error::MissingAuthorizationHeader.into())),
Err(_) => return Box::pin(err(ResponseError::from(Error::MissingAuthorizationHeader).into())),
},
None => {
return Box::pin(err(Error::MissingAuthorizationHeader.into()));
return Box::pin(err(ResponseError::from(Error::MissingAuthorizationHeader).into()));
}
};
@ -95,7 +95,7 @@ where
Box::pin(svc.call(req))
} else {
Box::pin(err(
Error::InvalidToken(auth_header.to_string()).into()
ResponseError::from(Error::InvalidToken(auth_header.to_string())).into()
))
}
}

View file

@ -17,7 +17,7 @@ use serde_json::Value;
use siphasher::sip::SipHasher;
use slice_group_by::GroupBy;
use crate::error::Error;
use crate::error::{Error, ResponseError};
pub trait IndexSearchExt {
fn new_search(&self, query: String) -> SearchBuilder;
@ -107,7 +107,7 @@ impl<'a> SearchBuilder<'a> {
self
}
pub fn search(self, reader: &heed::RoTxn<MainT>) -> Result<SearchResult, Error> {
pub fn search(self, reader: &heed::RoTxn<MainT>) -> Result<SearchResult, ResponseError> {
let schema = self
.index
.main
@ -260,7 +260,7 @@ impl<'a> SearchBuilder<'a> {
reader: &heed::RoTxn<MainT>,
ranked_map: &'a RankedMap,
schema: &Schema,
) -> Result<Option<Criteria<'a>>, Error> {
) -> Result<Option<Criteria<'a>>, ResponseError> {
let ranking_rules = self.index.main.ranking_rules(reader)?;
if let Some(ranking_rules) = ranking_rules {

View file

@ -7,14 +7,17 @@ pub mod models;
pub mod option;
pub mod routes;
pub use self::data::Data;
use self::error::json_error_handler;
use actix_http::Error;
use actix_service::ServiceFactory;
use actix_web::{dev, web, App};
use chrono::Utc;
use log::error;
use meilisearch_core::ProcessedUpdateResult;
pub use self::data::Data;
use self::error::{json_error_handler, ResponseError};
pub fn create_app(
data: &Data,
) -> App<
@ -55,28 +58,23 @@ pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpda
if let Some(index) = data.db.open_index(&index_uid) {
let db = &data.db;
let mut writer = match db.main_write_txn() {
Ok(writer) => writer,
Err(e) => {
error!("Impossible to get write_txn; {}", e);
return;
let res = db.main_write::<_, _, ResponseError>(|mut writer| {
if let Err(e) = data.compute_stats(&mut writer, &index_uid) {
error!("Impossible to compute stats; {}", e)
}
};
if let Err(e) = data.compute_stats(&mut writer, &index_uid) {
error!("Impossible to compute stats; {}", e)
}
if let Err(e) = data.db.set_last_update(&mut writer, &Utc::now()) {
error!("Impossible to update last_update; {}", e)
}
if let Err(e) = data.set_last_update(&mut writer) {
error!("Impossible to update last_update; {}", e)
}
if let Err(e) = index.main.put_updated_at(&mut writer) {
error!("Impossible to update updated_at; {}", e)
}
if let Err(e) = writer.commit() {
error!("Impossible to get write_txn; {}", e);
if let Err(e) = index.main.put_updated_at(&mut writer) {
error!("Impossible to update updated_at; {}", e)
}
Ok(())
});
match res {
Ok(_) => (),
Err(e) => error!("{}", e),
}
}
}

View file

@ -7,7 +7,7 @@ use meilisearch_core::update;
use serde::Deserialize;
use serde_json::Value;
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data;
@ -37,7 +37,7 @@ pub fn services(cfg: &mut web::ServiceConfig) {
async fn get_document(
data: web::Data<Data>,
path: web::Path<DocumentParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -46,13 +46,9 @@ async fn get_document(
let reader = data.db.main_read_txn()?;
let internal_id = index.main
.external_to_internal_docid(&reader, &path.document_id)?
.ok_or(ResponseError::document_not_found(&path.document_id))?;
let response: Document = index
.document(&reader, None, document_id)?
.ok_or(Error::document_not_found(&path.document_id))?;
Ok(HttpResponse::Ok().json(response))
Ok(HttpResponse::Ok().json(document))
}
#[delete(
@ -62,7 +58,7 @@ async fn get_document(
async fn delete_document(
data: web::Data<Data>,
path: web::Path<DocumentParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -70,14 +66,10 @@ async fn delete_document(
let document_id = meilisearch_core::serde::compute_document_id(&path.document_id);
let mut update_writer = data.db.update_write_txn()?;
let mut documents_deletion = index.documents_deletion();
documents_deletion.delete_document_by_external_docid(path.document_id.clone());
let update_id = documents_deletion.finalize(&mut update_writer)?;
update_writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|writer| Ok(documents_deletion.finalize(writer)?))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -95,7 +87,7 @@ async fn get_all_documents(
data: web::Data<Data>,
path: web::Path<IndexParam>,
params: web::Query<BrowseQuery>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -105,7 +97,6 @@ async fn get_all_documents(
let limit = params.limit.unwrap_or(20);
let reader = data.db.main_read_txn()?;
let documents_ids: Result<BTreeSet<_>, _> = index
.documents_fields_counts
.documents_ids(&reader)?
@ -113,23 +104,21 @@ async fn get_all_documents(
.take(limit)
.collect();
let documents_ids = documents_ids?;
let attributes: Option<HashSet<&str>> = params
.attributes_to_retrieve
.as_ref()
.map(|a| a.split(',').collect());
let mut response = Vec::new();
for document_id in documents_ids {
let mut documents = Vec::new();
for document_id in documents_ids? {
if let Ok(Some(document)) =
index.document::<Document>(&reader, attributes.as_ref(), document_id)
{
response.push(document);
documents.push(document);
}
}
Ok(HttpResponse::Ok().json(response))
Ok(HttpResponse::Ok().json(documents))
}
fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
@ -153,7 +142,7 @@ async fn update_multiple_documents(
params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>>,
is_partial: bool,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -175,13 +164,14 @@ async fn update_multiple_documents(
.ok_or(Error::bad_request("Could not infer a primary key"))?,
};
let mut writer = data.db.main_write_txn()?;
schema
.set_primary_key(&id)
.map_err(Error::bad_request)?;
index.main.put_schema(&mut writer, &schema)?;
writer.commit()?;
data.db.main_write::<_, _, ResponseError>(|mut writer| {
index.main.put_schema(&mut writer, &schema)?;
Ok(())
})?;
}
let mut document_addition = if is_partial {
@ -194,9 +184,12 @@ async fn update_multiple_documents(
document_addition.update_document(document);
}
let mut update_writer = data.db.update_write_txn()?;
let update_id = document_addition.finalize(&mut update_writer)?;
update_writer.commit()?;
let update_id = data
.db
.update_write::<_, _, ResponseError>(move |writer| {
let update_id = document_addition.finalize(writer)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -207,7 +200,7 @@ async fn add_documents(
path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
update_multiple_documents(data, path, params, body, false).await
}
@ -217,7 +210,7 @@ async fn update_documents(
path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
update_multiple_documents(data, path, params, body, true).await
}
@ -229,13 +222,12 @@ async fn delete_documents(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Vec<Value>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let mut documents_deletion = index.documents_deletion();
@ -244,9 +236,7 @@ async fn delete_documents(
documents_deletion.delete_document_by_external_docid(document_id);
}
let update_id = documents_deletion.finalize(&mut writer)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|writer| Ok(documents_deletion.finalize(writer)?))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -255,17 +245,13 @@ async fn delete_documents(
async fn clear_all_documents(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let update_id = index.clear_all(&mut writer)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|writer| Ok(index.clear_all(writer)?))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}

View file

@ -1,46 +1,37 @@
use actix_web::{web, HttpResponse};
use actix_web_macros::{get, put};
use heed::types::{Str, Unit};
use serde::Deserialize;
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::Data;
const UNHEALTHY_KEY: &str = "_is_unhealthy";
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(get_health).service(change_healthyness);
}
#[get("/health", wrap = "Authentication::Private")]
async fn get_health(data: web::Data<Data>) -> Result<HttpResponse, Error> {
async fn get_health(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let reader = data.db.main_read_txn()?;
let common_store = data.db.common_store();
if let Ok(Some(_)) = common_store.get::<_, Str, Unit>(&reader, UNHEALTHY_KEY) {
return Err(Error::Maintenance);
if let Ok(Some(_)) = data.db.get_health(&reader) {
return Err(Error::Maintenance.into());
}
Ok(HttpResponse::Ok().finish())
}
async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, Error> {
let mut writer = data.db.main_write_txn()?;
let common_store = data.db.common_store();
common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)?;
writer.commit()?;
async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
data.db.main_write::<_, _, ResponseError>(|writer| {
data.db.set_healthy(writer)?;
Ok(())
})?;
Ok(HttpResponse::Ok().finish())
}
async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, Error> {
let mut writer = data.db.main_write_txn()?;
let common_store = data.db.common_store();
common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())?;
writer.commit()?;
async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
data.db.main_write::<_, _, ResponseError>(|writer| {
data.db.set_unhealthy(writer)?;
Ok(())
})?;
Ok(HttpResponse::Ok().finish())
}
@ -52,8 +43,8 @@ struct HealthBody {
#[put("/health", wrap = "Authentication::Private")]
async fn change_healthyness(
data: web::Data<Data>,
body: web::Json<HealthBody>,
) -> Result<HttpResponse, Error> {
body: web::Json<HealtBody>,
) -> Result<HttpResponse, ResponseError> {
if body.health {
set_healthy(data).await
} else {

View file

@ -5,7 +5,7 @@ use log::error;
use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize};
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::IndexParam;
use crate::Data;
@ -40,10 +40,9 @@ struct IndexResponse {
}
#[get("/indexes", wrap = "Authentication::Private")]
async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, Error> {
async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let reader = data.db.main_read_txn()?;
let mut response = Vec::new();
let mut indexes = Vec::new();
for index_uid in data.db.indexes_uids() {
let index = data.db.open_index(&index_uid);
@ -51,19 +50,19 @@ async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, Error> {
match index {
Some(index) => {
let name = index.main.name(&reader)?.ok_or(Error::internal(
"Impossible to get the name of an index",
"Impossible to get the name of an index",
))?;
let created_at = index
.main
.created_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the create date of an index",
"Impossible to get the create date of an index",
))?;
let updated_at = index
.main
.updated_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the last update date of an index",
"Impossible to get the last update date of an index",
))?;
let primary_key = match index.main.schema(&reader) {
@ -81,7 +80,7 @@ async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, Error> {
updated_at,
primary_key,
};
response.push(index_response);
indexes.push(index_response);
}
None => error!(
"Index {} is referenced in the indexes list but cannot be found",
@ -90,35 +89,34 @@ async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, Error> {
}
}
Ok(HttpResponse::Ok().json(response))
Ok(HttpResponse::Ok().json(indexes))
}
#[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
async fn get_index(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let reader = data.db.main_read_txn()?;
let name = index.main.name(&reader)?.ok_or(Error::internal(
"Impossible to get the name of an index",
"Impossible to get the name of an index",
))?;
let created_at = index
.main
.created_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the create date of an index",
"Impossible to get the create date of an index",
))?;
let updated_at = index
.main
.updated_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the last update date of an index",
"Impossible to get the last update date of an index",
))?;
let primary_key = match index.main.schema(&reader) {
@ -128,14 +126,15 @@ async fn get_index(
},
_ => None,
};
Ok(HttpResponse::Ok().json(IndexResponse {
let index_response = IndexResponse {
name,
uid: path.index_uid.clone(),
created_at,
updated_at,
primary_key,
}))
};
Ok(HttpResponse::Ok().json(index_response))
}
#[derive(Debug, Deserialize)]
@ -150,11 +149,11 @@ struct IndexCreateRequest {
async fn create_index(
data: web::Data<Data>,
body: web::Json<IndexCreateRequest>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
if let (None, None) = (body.name.clone(), body.uid.clone()) {
return Err(Error::bad_request(
"Index creation must have an uid",
));
).into());
}
let uid = match &body.uid {
@ -165,7 +164,7 @@ async fn create_index(
{
uid.to_owned()
} else {
return Err(Error::InvalidIndexUid);
return Err(Error::InvalidIndexUid.into());
}
}
None => loop {
@ -181,39 +180,39 @@ async fn create_index(
.create_index(&uid)
.map_err(Error::create_index)?;
let mut writer = data.db.main_write_txn()?;
let index_response = data.db.main_write::<_, _, ResponseError>(|mut writer| {
let name = body.name.as_ref().unwrap_or(&uid);
created_index.main.put_name(&mut writer, name)?;
let name = body.name.as_ref().unwrap_or(&uid);
created_index.main.put_name(&mut writer, name)?;
let created_at = created_index
.main
.created_at(&writer)?
.ok_or(Error::internal("Impossible to read created at"))?;
let created_at = created_index
.main
.created_at(&writer)?
.ok_or(Error::internal("Impossible to read created at"))?;
let updated_at = created_index
.main
.updated_at(&writer)?
.ok_or(Error::internal("Impossible to read updated at"))?;
let updated_at = created_index
.main
.updated_at(&writer)?
.ok_or(Error::internal("Impossible to read updated at"))?;
if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = created_index.main.schema(&writer)? {
schema
.set_primary_key(&id)
.map_err(Error::bad_request)?;
created_index.main.put_schema(&mut writer, &schema)?;
if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = created_index.main.schema(&writer)? {
schema
.set_primary_key(&id)
.map_err(Error::bad_request)?;
created_index.main.put_schema(&mut writer, &schema)?;
}
}
}
let index_response = IndexResponse {
name: name.to_string(),
uid,
created_at,
updated_at,
primary_key: body.primary_key.clone(),
};
Ok(index_response)
})?;
writer.commit()?;
Ok(HttpResponse::Created().json(IndexResponse {
name: name.to_string(),
uid,
created_at,
updated_at,
primary_key: body.primary_key.clone(),
}))
Ok(HttpResponse::Created().json(index_response))
}
#[derive(Debug, Deserialize)]
@ -238,53 +237,51 @@ async fn update_index(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<IndexCreateRequest>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.main_write_txn()?;
data.db.main_write::<_, _, ResponseError>(|mut writer| {
if let Some(name) = &body.name {
index.main.put_name(&mut writer, name)?;
}
if let Some(name) = &body.name {
index.main.put_name(&mut writer, name)?;
}
if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = index.main.schema(&writer)? {
match schema.primary_key() {
Some(_) => {
return Err(Error::bad_request(
"The primary key cannot be updated",
));
}
None => {
schema.set_primary_key(&id)?;
index.main.put_schema(&mut writer, &schema)?;
if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = index.main.schema(&writer)? {
match schema.primary_key() {
Some(_) => {
return Err(Error::bad_request(
"The primary key cannot be updated",
).into());
}
None => {
schema.set_primary_key(&id)?;
index.main.put_schema(&mut writer, &schema)?;
}
}
}
}
}
index.main.put_updated_at(&mut writer)?;
writer.commit()?;
index.main.put_updated_at(&mut writer)?;
Ok(())
})?;
let reader = data.db.main_read_txn()?;
let name = index.main.name(&reader)?.ok_or(Error::internal(
"Impossible to get the name of an index",
"Impossible to get the name of an index",
))?;
let created_at = index
.main
.created_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the create date of an index",
"Impossible to get the create date of an index",
))?;
let updated_at = index
.main
.updated_at(&reader)?
.ok_or(Error::internal(
"Impossible to get the last update date of an index",
"Impossible to get the last update date of an index",
))?;
let primary_key = match index.main.schema(&reader) {
@ -295,20 +292,22 @@ async fn update_index(
_ => None,
};
Ok(HttpResponse::Ok().json(IndexResponse {
let index_response = IndexResponse {
name,
uid: path.index_uid.clone(),
created_at,
updated_at,
primary_key,
}))
};
Ok(HttpResponse::Ok().json(index_response))
}
#[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
async fn delete_index(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
data.db.delete_index(&path.index_uid)?;
Ok(HttpResponse::NoContent().finish())
@ -327,7 +326,7 @@ struct UpdateParam {
async fn get_update_status(
data: web::Data<Data>,
path: web::Path<UpdateParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -342,7 +341,7 @@ async fn get_update_status(
None => Err(Error::NotFound(format!(
"Update {} not found",
path.update_id
))),
)).into()),
}
}
@ -350,7 +349,7 @@ async fn get_update_status(
async fn get_all_updates_status(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)

View file

@ -7,7 +7,7 @@ use actix_web_macros::get;
use serde::Deserialize;
use serde_json::Value;
use crate::error::{Error, FacetCountError};
use crate::error::{Error, FacetCountError, ResponseError};
use crate::helpers::meilisearch::IndexSearchExt;
use crate::helpers::Authentication;
use crate::routes::IndexParam;
@ -41,14 +41,13 @@ async fn search_with_url_query(
data: web::Data<Data>,
path: web::Path<IndexParam>,
params: web::Query<SearchQuery>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let reader = data.db.main_read_txn()?;
let schema = index
.main
.schema(&reader)?
@ -88,9 +87,9 @@ async fn search_with_url_query(
}
if let Some(ref facet_filters) = params.facet_filters {
match index.main.attributes_for_faceting(&reader)? {
Some(ref attrs) => { search_builder.add_facet_filters(FacetFilter::from_str(facet_filters, &schema, attrs)?); },
None => return Err(Error::FacetExpression("can't filter on facets, as no facet is set".to_string()))
let attrs = index.main.attributes_for_faceting(&reader)?;
if let Some(attrs) = attrs {
search_builder.add_facet_filters(FacetFilter::from_str(facet_filters, &schema, &attrs)?);
}
}
@ -100,7 +99,7 @@ async fn search_with_url_query(
let field_ids = prepare_facet_list(&facets, &schema, attrs)?;
search_builder.add_facets(field_ids);
},
None => return Err(FacetCountError::NoFacetSet.into())
None => todo!() /* return Err(FacetCountError::NoFacetSet.into()) */
}
}
@ -160,8 +159,9 @@ async fn search_with_url_query(
search_builder.get_matches();
}
}
let search_result = search_builder.search(&reader)?;
Ok(HttpResponse::Ok().json(search_builder.search(&reader)?))
Ok(HttpResponse::Ok().json(search_result))
}
/// Parses the incoming string into an array of attributes for which to return a count. It returns

View file

@ -3,7 +3,7 @@ use actix_web_macros::{delete, get, post};
use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES};
use std::collections::{BTreeMap, BTreeSet, HashSet};
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data;
@ -33,19 +33,20 @@ async fn update_all(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Settings>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let settings = body
.into_inner()
.into_update()
.map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let settings = body
.into_inner()
.into_update()
.map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -54,7 +55,7 @@ async fn update_all(
async fn get_all(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -62,19 +63,21 @@ async fn get_all(
let reader = data.db.main_read_txn()?;
let stop_words_fst = index.main.stop_words_fst(&reader)?;
let stop_words = stop_words_fst.stream().into_strs()?;
let stop_words: BTreeSet<String> = stop_words.into_iter().collect();
let stop_words: BTreeSet<String> = index
.main
.stop_words_list(&reader)?
.into_iter()
.collect();
let synonyms_fst = index.main.synonyms_fst(&reader)?;
let synonyms_list = synonyms_fst.stream().into_strs()?;
let synonyms_list = index.main.synonyms_list(&reader)?;
let mut synonyms = BTreeMap::new();
let index_synonyms = &index.synonyms;
for synonym in synonyms_list {
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
let list = alternative_list.stream().into_strs()?;
synonyms.insert(synonym, list);
if let Some(list) = alternative_list {
synonyms.insert(synonym, list);
}
}
let ranking_rules = index
@ -134,12 +137,11 @@ async fn get_all(
async fn delete_all(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let settings = SettingsUpdate {
ranking_rules: UpdateState::Clear,
@ -153,8 +155,10 @@ async fn delete_all(
attributes_for_faceting: UpdateState::Clear,
};
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|writer| {
let update_id = index.settings_update(writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -166,7 +170,7 @@ async fn delete_all(
async fn get_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -192,7 +196,7 @@ async fn update_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -203,10 +207,12 @@ async fn update_rules(
..Settings::default()
};
let mut writer = data.db.update_write_txn()?;
let settings = settings.into_update().map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -218,21 +224,21 @@ async fn update_rules(
async fn delete_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let settings = SettingsUpdate {
ranking_rules: UpdateState::Clear,
..SettingsUpdate::default()
};
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -244,7 +250,7 @@ async fn delete_rules(
async fn get_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -263,7 +269,7 @@ async fn update_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<String>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -274,10 +280,12 @@ async fn update_distinct(
..Settings::default()
};
let mut writer = data.db.update_write_txn()?;
let settings = settings.into_update().map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -289,21 +297,21 @@ async fn update_distinct(
async fn delete_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let mut writer = data.db.update_write_txn()?;
let settings = SettingsUpdate {
distinct_attribute: UpdateState::Clear,
..SettingsUpdate::default()
};
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -315,7 +323,7 @@ async fn delete_distinct(
async fn get_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -336,7 +344,7 @@ async fn update_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -347,10 +355,12 @@ async fn update_searchable(
..Settings::default()
};
let mut writer = data.db.update_write_txn()?;
let settings = settings.into_update().map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -362,7 +372,7 @@ async fn update_searchable(
async fn delete_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -373,9 +383,10 @@ async fn delete_searchable(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -387,7 +398,7 @@ async fn delete_searchable(
async fn get_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -410,7 +421,7 @@ async fn update_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<HashSet<String>>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -421,10 +432,12 @@ async fn update_displayed(
..Settings::default()
};
let mut writer = data.db.update_write_txn()?;
let settings = settings.into_update().map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -436,7 +449,7 @@ async fn update_displayed(
async fn delete_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -447,9 +460,10 @@ async fn delete_displayed(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -461,7 +475,7 @@ async fn delete_displayed(
async fn get_accept_new_fields(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -483,7 +497,7 @@ async fn update_accept_new_fields(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<bool>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -494,10 +508,12 @@ async fn update_accept_new_fields(
..Settings::default()
};
let mut writer = data.db.update_write_txn()?;
let settings = settings.into_update().map_err(Error::bad_request)?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}

View file

@ -10,7 +10,7 @@ use serde::Serialize;
use sysinfo::{NetworkExt, ProcessExt, ProcessorExt, System, SystemExt};
use walkdir::WalkDir;
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::IndexParam;
use crate::Data;
@ -35,7 +35,7 @@ struct IndexStatsResponse {
async fn index_stats(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -71,7 +71,7 @@ struct StatsResult {
}
#[get("/stats", wrap = "Authentication::Private")]
async fn get_stats(data: web::Data<Data>) -> Result<HttpResponse, Error> {
async fn get_stats(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let mut index_list = HashMap::new();
let reader = data.db.main_read_txn()?;
@ -111,7 +111,7 @@ async fn get_stats(data: web::Data<Data>) -> Result<HttpResponse, Error> {
.filter(|metadata| metadata.is_file())
.fold(0, |acc, m| acc + m.len());
let last_update = data.last_update(&reader)?;
let last_update = data.db.last_update(&reader)?;
Ok(HttpResponse::Ok().json(StatsResult {
database_size,

View file

@ -3,7 +3,7 @@ use actix_web_macros::{delete, get, post};
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use std::collections::BTreeSet;
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data;
@ -19,14 +19,13 @@ pub fn services(cfg: &mut web::ServiceConfig) {
async fn get(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
.ok_or(Error::index_not_found(&path.index_uid))?;
let reader = data.db.main_read_txn()?;
let stop_words_fst = index.main.stop_words_fst(&reader)?;
let stop_words = stop_words_fst.stream().into_strs()?;
let stop_words = index.main.stop_words_list(&reader)?;
Ok(HttpResponse::Ok().json(stop_words))
}
@ -39,7 +38,7 @@ async fn update(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<BTreeSet<String>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -50,9 +49,10 @@ async fn update(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -64,7 +64,7 @@ async fn update(
async fn delete(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -75,9 +75,10 @@ async fn delete(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}

View file

@ -5,7 +5,7 @@ use actix_web_macros::{delete, get, post};
use indexmap::IndexMap;
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data;
@ -21,7 +21,7 @@ pub fn services(cfg: &mut web::ServiceConfig) {
async fn get(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -29,15 +29,15 @@ async fn get(
let reader = data.db.main_read_txn()?;
let synonyms_fst = index.main.synonyms_fst(&reader)?;
let synonyms_list = synonyms_fst.stream().into_strs()?;
let synonyms_list = index.main.synonyms_list(&reader)?;
let mut synonyms = IndexMap::new();
let index_synonyms = &index.synonyms;
for synonym in synonyms_list {
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
let list = alternative_list.stream().into_strs()?;
synonyms.insert(synonym, list);
if let Some(list) = alternative_list {
synonyms.insert(synonym, list);
}
}
Ok(HttpResponse::Ok().json(synonyms))
@ -51,7 +51,7 @@ async fn update(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<BTreeMap<String, Vec<String>>>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -62,9 +62,10 @@ async fn update(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
@ -76,7 +77,7 @@ async fn update(
async fn delete(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, Error> {
) -> Result<HttpResponse, ResponseError> {
let index = data
.db
.open_index(&path.index_uid)
@ -87,10 +88,10 @@ async fn delete(
..SettingsUpdate::default()
};
let mut writer = data.db.update_write_txn()?;
let update_id = index.settings_update(&mut writer, settings)?;
writer.commit()?;
let update_id = data.db.update_write::<_, _, ResponseError>(|mut writer| {
let update_id = index.settings_update(&mut writer, settings)?;
Ok(update_id)
})?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}