mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-12-23 21:20:24 +01:00
simplify error handling by impl errors traits on ResponseError
This commit is contained in:
parent
4bd7e46ba6
commit
e74d2c1872
@ -7,39 +7,109 @@ use serde_json::json;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ResponseError {
|
||||
Internal(String),
|
||||
BadRequest(String),
|
||||
MissingAuthorizationHeader,
|
||||
InvalidToken(String),
|
||||
NotFound(String),
|
||||
IndexNotFound(String),
|
||||
DocumentNotFound(String),
|
||||
MissingHeader(String),
|
||||
FilterParsing(String),
|
||||
BadParameter(String, String),
|
||||
OpenIndex(String),
|
||||
BadRequest(String),
|
||||
CreateIndex(String),
|
||||
DocumentNotFound(String),
|
||||
IndexNotFound(String),
|
||||
Internal(String),
|
||||
InvalidIndexUid,
|
||||
InvalidToken(String),
|
||||
Maintenance,
|
||||
MissingAuthorizationHeader,
|
||||
MissingFilterValue,
|
||||
MissingHeader(String),
|
||||
NotFound(String),
|
||||
OpenIndex(String),
|
||||
FilterParsing(String),
|
||||
RetrieveDocument(u64, String),
|
||||
SearchDocuments(String),
|
||||
UnknownFilteredAttribute,
|
||||
}
|
||||
|
||||
impl ResponseError {
|
||||
pub fn internal(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::Internal(err.to_string())
|
||||
}
|
||||
|
||||
pub fn bad_request(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::BadRequest(err.to_string())
|
||||
}
|
||||
|
||||
pub fn missing_authorization_header() -> ResponseError {
|
||||
ResponseError::MissingAuthorizationHeader
|
||||
}
|
||||
|
||||
pub fn invalid_token(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::InvalidToken(err.to_string())
|
||||
}
|
||||
|
||||
pub fn not_found(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::NotFound(err.to_string())
|
||||
}
|
||||
|
||||
pub fn index_not_found(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::IndexNotFound(err.to_string())
|
||||
}
|
||||
|
||||
pub fn document_not_found(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::DocumentNotFound(err.to_string())
|
||||
}
|
||||
|
||||
pub fn missing_header(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::MissingHeader(err.to_string())
|
||||
}
|
||||
|
||||
pub fn bad_parameter(param: impl fmt::Display, err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::BadParameter(param.to_string(), err.to_string())
|
||||
}
|
||||
|
||||
pub fn open_index(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::OpenIndex(err.to_string())
|
||||
}
|
||||
|
||||
pub fn create_index(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::CreateIndex(err.to_string())
|
||||
}
|
||||
|
||||
pub fn invalid_index_uid() -> ResponseError {
|
||||
ResponseError::InvalidIndexUid
|
||||
}
|
||||
|
||||
pub fn maintenance() -> ResponseError {
|
||||
ResponseError::Maintenance
|
||||
}
|
||||
|
||||
pub fn retrieve_document(doc_id: u64, err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::RetrieveDocument(doc_id, err.to_string())
|
||||
}
|
||||
|
||||
pub fn search_documents(err: impl fmt::Display) -> ResponseError {
|
||||
ResponseError::SearchDocuments(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ResponseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Internal(err) => write!(f, "{}", err),
|
||||
Self::BadRequest(err) => write!(f, "{}", err),
|
||||
Self::MissingAuthorizationHeader => write!(f, "You must have an authorization token"),
|
||||
Self::InvalidToken(err) => write!(f, "Invalid API key: {}", err),
|
||||
Self::NotFound(err) => write!(f, "{} not found", err),
|
||||
Self::IndexNotFound(index_uid) => write!(f, "Index {} not found", index_uid),
|
||||
Self::DocumentNotFound(document_id) => write!(f, "Document with id {} not found", document_id),
|
||||
Self::MissingHeader(header) => write!(f, "Header {} is missing", header),
|
||||
Self::BadParameter(param, err) => write!(f, "Url parameter {} error: {}", param, err),
|
||||
Self::OpenIndex(err) => write!(f, "Impossible to open index; {}", err),
|
||||
Self::BadRequest(err) => write!(f, "{}", err),
|
||||
Self::CreateIndex(err) => write!(f, "Impossible to create index; {}", err),
|
||||
Self::InvalidIndexUid => write!(f, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."),
|
||||
Self::Maintenance => write!(f, "Server is in maintenance, please try again later"),
|
||||
Self::DocumentNotFound(document_id) => write!(f, "Document with id {} not found", document_id),
|
||||
Self::IndexNotFound(index_uid) => write!(f, "Index {} not found", index_uid),
|
||||
Self::Internal(err) => write!(f, "{}", err),
|
||||
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::MissingFilterValue => f.write_str("a filter doesn't have a value to compare it with"),
|
||||
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::UnknownFilteredAttribute => f.write_str("a filter is specifying an unknown schema attribute"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,20 +123,66 @@ impl aweb::error::ResponseError for ResponseError {
|
||||
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
|
||||
Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN,
|
||||
Self::InvalidToken(_) => StatusCode::UNAUTHORIZED,
|
||||
Self::NotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::IndexNotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::DocumentNotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
|
||||
Self::BadParameter(_, _) => StatusCode::BAD_REQUEST,
|
||||
Self::OpenIndex(_) => StatusCode::BAD_REQUEST,
|
||||
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
|
||||
Self::CreateIndex(_) => StatusCode::BAD_REQUEST,
|
||||
Self::DocumentNotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::IndexNotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::InvalidIndexUid => StatusCode::BAD_REQUEST,
|
||||
Self::InvalidToken(_) => StatusCode::UNAUTHORIZED,
|
||||
Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE,
|
||||
Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
|
||||
Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN,
|
||||
Self::MissingFilterValue => StatusCode::BAD_REQUEST,
|
||||
Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
|
||||
Self::NotFound(_) => StatusCode::NOT_FOUND,
|
||||
Self::OpenIndex(_) => StatusCode::BAD_REQUEST,
|
||||
Self::RetrieveDocument(_, _) => StatusCode::BAD_REQUEST,
|
||||
Self::SearchDocuments(_) => StatusCode::BAD_REQUEST,
|
||||
Self::UnknownFilteredAttribute => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<meilisearch_core::HeedError> for ResponseError {
|
||||
fn from(err: meilisearch_core::HeedError) -> ResponseError {
|
||||
ResponseError::Internal(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<meilisearch_core::FstError> for ResponseError {
|
||||
fn from(err: meilisearch_core::FstError) -> ResponseError {
|
||||
ResponseError::Internal(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<meilisearch_core::Error> for ResponseError {
|
||||
fn from(err: meilisearch_core::Error) -> ResponseError {
|
||||
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());
|
||||
|
||||
ResponseError::FilterParsing(message)
|
||||
},
|
||||
_ => ResponseError::Internal(err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<meilisearch_schema::Error> for ResponseError {
|
||||
fn from(err: meilisearch_schema::Error) -> ResponseError {
|
||||
ResponseError::Internal(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<actix_http::Error> for ResponseError {
|
||||
fn from(err: actix_http::Error) -> ResponseError {
|
||||
ResponseError::Internal(err.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::convert::From;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
@ -19,74 +16,7 @@ use serde_json::Value;
|
||||
use siphasher::sip::SipHasher;
|
||||
use slice_group_by::GroupBy;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
SearchDocuments(String),
|
||||
RetrieveDocument(u64, String),
|
||||
DocumentNotFound(u64),
|
||||
CropFieldWrongType(String),
|
||||
FilterParsing(String),
|
||||
AttributeNotFoundOnDocument(String),
|
||||
AttributeNotFoundOnSchema(String),
|
||||
MissingFilterValue,
|
||||
UnknownFilteredAttribute,
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Error::*;
|
||||
|
||||
match self {
|
||||
SearchDocuments(err) => write!(f, "impossible to search documents; {}", err),
|
||||
RetrieveDocument(id, err) => write!(
|
||||
f,
|
||||
"impossible to retrieve the document with id: {}; {}",
|
||||
id, err
|
||||
),
|
||||
DocumentNotFound(id) => write!(f, "document {} not found", id),
|
||||
CropFieldWrongType(field) => {
|
||||
write!(f, "the field {} cannot be cropped it's not a string", field)
|
||||
}
|
||||
AttributeNotFoundOnDocument(field) => {
|
||||
write!(f, "field {} is not found on document", field)
|
||||
}
|
||||
AttributeNotFoundOnSchema(field) => write!(f, "field {} is not found on schema", field),
|
||||
MissingFilterValue => f.write_str("a filter doesn't have a value to compare it with"),
|
||||
UnknownFilteredAttribute => {
|
||||
f.write_str("a filter is specifying an unknown schema attribute")
|
||||
}
|
||||
Internal(err) => write!(f, "internal error; {}", err),
|
||||
FilterParsing(err) => write!(f, "filter parsing error: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<meilisearch_core::Error> for Error {
|
||||
fn from(error: meilisearch_core::Error) -> Self {
|
||||
use meilisearch_core::pest_error::LineColLocation::*;
|
||||
match error {
|
||||
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)
|
||||
},
|
||||
_ => Error::Internal(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<heed::Error> for Error {
|
||||
fn from(error: heed::Error) -> Self {
|
||||
Error::Internal(error.to_string())
|
||||
}
|
||||
}
|
||||
use crate::error::ResponseError;
|
||||
|
||||
pub trait IndexSearchExt {
|
||||
fn new_search(&self, query: String) -> SearchBuilder;
|
||||
@ -169,17 +99,14 @@ impl<'a> SearchBuilder<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn search(&self, reader: &heed::RoTxn<MainT>) -> Result<SearchResult, Error> {
|
||||
let schema = self.index.main.schema(reader);
|
||||
let schema = schema.map_err(|e| Error::Internal(e.to_string()))?;
|
||||
let schema = match schema {
|
||||
Some(schema) => schema,
|
||||
None => return Err(Error::Internal(String::from("missing schema"))),
|
||||
};
|
||||
pub fn search(&self, reader: &heed::RoTxn<MainT>) -> Result<SearchResult, ResponseError> {
|
||||
let schema = self
|
||||
.index
|
||||
.main
|
||||
.schema(reader)?
|
||||
.ok_or(ResponseError::internal("missing schema"))?;
|
||||
|
||||
let ranked_map = self.index.main.ranked_map(reader);
|
||||
let ranked_map = ranked_map.map_err(|e| Error::Internal(e.to_string()))?;
|
||||
let ranked_map = ranked_map.unwrap_or_default();
|
||||
let ranked_map = self.index.main.ranked_map(reader)?.unwrap_or_default();
|
||||
|
||||
// Change criteria
|
||||
let mut query_builder = match self.get_criteria(reader, &ranked_map, &schema)? {
|
||||
@ -221,9 +148,8 @@ impl<'a> SearchBuilder<'a> {
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let result =
|
||||
query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit));
|
||||
let (docs, nb_hits) = result.map_err(|e| Error::SearchDocuments(e.to_string()))?;
|
||||
let result = query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit));
|
||||
let (docs, nb_hits) = result.map_err(ResponseError::search_documents)?;
|
||||
let time_ms = start.elapsed().as_millis() as usize;
|
||||
|
||||
let mut all_attributes: HashSet<&str> = HashSet::new();
|
||||
@ -255,11 +181,19 @@ impl<'a> SearchBuilder<'a> {
|
||||
|
||||
let mut hits = Vec::with_capacity(self.limit);
|
||||
for doc in docs {
|
||||
// retrieve the content of document in kv store
|
||||
let attributes: Option<HashSet<&str>> = self
|
||||
.attributes_to_retrieve
|
||||
.as_ref()
|
||||
.map(|a| a.iter().map(|a| a.as_str()).collect());
|
||||
|
||||
let mut document: IndexMap<String, Value> = self
|
||||
.index
|
||||
.document(reader, Some(&all_attributes), doc.id)
|
||||
.map_err(|e| Error::RetrieveDocument(doc.id.0, e.to_string()))?
|
||||
.ok_or(Error::DocumentNotFound(doc.id.0))?;
|
||||
.document(reader, attributes.as_ref(), doc.id)
|
||||
.map_err(|e| ResponseError::retrieve_document(doc.id.0, e))?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to retrieve a document id returned by the engine",
|
||||
))?;
|
||||
|
||||
let mut formatted = document.iter()
|
||||
.filter(|(key, _)| all_formatted.contains(key.as_str()))
|
||||
@ -320,7 +254,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 {
|
||||
|
@ -1,7 +1,5 @@
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
|
||||
use actix_web as aweb;
|
||||
use actix_web::{delete, get, post, put, web, HttpResponse};
|
||||
use indexmap::IndexMap;
|
||||
use serde::Deserialize;
|
||||
@ -23,22 +21,18 @@ pub struct DocumentParam {
|
||||
pub async fn get_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone());
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let document_id = meilisearch_core::serde::compute_document_id(&path.document_id);
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let response = index
|
||||
.document::<Document>(&reader, None, document_id)
|
||||
.map_err(|_| ResponseError::DocumentNotFound(path.document_id.clone()))?
|
||||
.ok_or(ResponseError::DocumentNotFound(path.document_id.clone()))?;
|
||||
.document::<Document>(&reader, None, document_id)?
|
||||
.ok_or(ResponseError::document_not_found(&path.document_id))?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
@ -47,28 +41,21 @@ pub async fn get_document(
|
||||
pub async fn delete_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone());
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let document_id = meilisearch_core::serde::compute_document_id(&path.document_id);
|
||||
|
||||
let mut update_writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut update_writer = data.db.update_write_txn()?;
|
||||
|
||||
let mut documents_deletion = index.documents_deletion();
|
||||
documents_deletion.delete_document_by_id(document_id);
|
||||
|
||||
let update_id = documents_deletion
|
||||
.finalize(&mut update_writer)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = documents_deletion.finalize(&mut update_writer)?;
|
||||
|
||||
update_writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
update_writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -86,32 +73,29 @@ pub async fn get_all_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<BrowseQuery>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let offset = params.offset.unwrap_or(0);
|
||||
let limit = params.limit.unwrap_or(20);
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let documents_ids: Result<BTreeSet<_>, _> = index
|
||||
.documents_fields_counts
|
||||
.documents_ids(&reader)
|
||||
.map_err(|_| ResponseError::Internal(path.index_uid.clone()))?
|
||||
.documents_ids(&reader)?
|
||||
.skip(offset)
|
||||
.take(limit)
|
||||
.collect();
|
||||
|
||||
let documents_ids = documents_ids.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let documents_ids = documents_ids?;
|
||||
|
||||
let attributes: Option<HashSet<&str>> = params
|
||||
.attributes_to_retrieve.as_ref()
|
||||
.attributes_to_retrieve
|
||||
.as_ref()
|
||||
.map(|a| a.split(',').collect());
|
||||
|
||||
let mut response = Vec::<Document>::new();
|
||||
@ -145,48 +129,33 @@ async fn update_multiple_documents(
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Json<Vec<Document>>,
|
||||
is_partial: bool,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let mut schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to retrieve the schema".to_string(),
|
||||
))?;
|
||||
.schema(&reader)?
|
||||
.ok_or(ResponseError::internal("Impossible to retrieve the schema"))?;
|
||||
|
||||
if schema.primary_key().is_none() {
|
||||
let id = match params.primary_key.clone() {
|
||||
Some(id) => id,
|
||||
None => body.first().and_then(|docs| find_primary_key(docs)).ok_or(
|
||||
ResponseError::BadRequest("Could not infer a primary key".to_string()),
|
||||
)?,
|
||||
let id = match ¶ms.primary_key {
|
||||
Some(id) => id.to_string(),
|
||||
None => body
|
||||
.first()
|
||||
.and_then(find_primary_key)
|
||||
.ok_or(ResponseError::bad_request("Could not infer a primary key"))?,
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.main_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.main_write_txn()?;
|
||||
|
||||
schema
|
||||
.set_primary_key(&id)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
index
|
||||
.main
|
||||
.put_schema(&mut writer, &schema)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
schema.set_primary_key(&id)?;
|
||||
index.main.put_schema(&mut writer, &schema)?;
|
||||
writer.commit()?;
|
||||
}
|
||||
|
||||
let mut document_addition = if is_partial {
|
||||
@ -199,16 +168,9 @@ async fn update_multiple_documents(
|
||||
document_addition.update_document(document);
|
||||
}
|
||||
|
||||
let mut update_writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = document_addition
|
||||
.finalize(&mut update_writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
update_writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut update_writer = data.db.update_write_txn()?;
|
||||
let update_id = document_addition.finalize(&mut update_writer)?;
|
||||
update_writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -219,7 +181,7 @@ pub async fn add_documents(
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Json<Vec<Document>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
update_multiple_documents(data, path, params, body, false).await
|
||||
}
|
||||
|
||||
@ -229,7 +191,7 @@ pub async fn update_documents(
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Json<Vec<Document>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
update_multiple_documents(data, path, params, body, true).await
|
||||
}
|
||||
|
||||
@ -238,16 +200,13 @@ pub async fn delete_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Vec<Value>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
|
||||
let mut documents_deletion = index.documents_deletion();
|
||||
|
||||
@ -258,13 +217,9 @@ pub async fn delete_documents(
|
||||
}
|
||||
}
|
||||
|
||||
let update_id = documents_deletion
|
||||
.finalize(&mut writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
let update_id = documents_deletion.finalize(&mut writer)?;
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -273,24 +228,17 @@ pub async fn delete_documents(
|
||||
pub async fn clear_all_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
|
||||
let update_id = index
|
||||
.clear_all(&mut writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
let update_id = index.clear_all(&mut writer)?;
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::error::ResponseError;
|
||||
use crate::Data;
|
||||
use actix_web as aweb;
|
||||
use actix_web::{get, put, web, HttpResponse};
|
||||
use heed::types::{Str, Unit};
|
||||
use serde::Deserialize;
|
||||
@ -8,49 +7,32 @@ use serde::Deserialize;
|
||||
const UNHEALTHY_KEY: &str = "_is_unhealthy";
|
||||
|
||||
#[get("/health")]
|
||||
pub async fn get_health(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
pub 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(ResponseError::Maintenance.into());
|
||||
return Err(ResponseError::Maintenance);
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
|
||||
pub async fn set_healthy(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
let mut writer = data
|
||||
.db
|
||||
.main_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
pub async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
let mut writer = data.db.main_write_txn()?;
|
||||
let common_store = data.db.common_store();
|
||||
common_store
|
||||
.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
|
||||
pub async fn set_unhealthy(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
let mut writer = data
|
||||
.db
|
||||
.main_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
pub async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
let mut writer = data.db.main_write_txn()?;
|
||||
let common_store = data.db.common_store();
|
||||
common_store
|
||||
.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
@ -64,7 +46,7 @@ pub struct HealtBody {
|
||||
pub async fn change_healthyness(
|
||||
data: web::Data<Data>,
|
||||
body: web::Json<HealtBody>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
if body.health {
|
||||
set_healthy(data).await
|
||||
} else {
|
||||
|
@ -1,4 +1,3 @@
|
||||
use actix_web as aweb;
|
||||
use actix_web::{delete, get, post, put, web, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
@ -29,11 +28,8 @@ pub struct IndexResponse {
|
||||
}
|
||||
|
||||
#[get("/indexes")]
|
||||
pub async fn list_indexes(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
pub async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let mut response = Vec::new();
|
||||
|
||||
@ -42,26 +38,20 @@ pub async fn list_indexes(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
|
||||
match index {
|
||||
Some(index) => {
|
||||
let name = index
|
||||
.main
|
||||
.name(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the name of an index".to_string(),
|
||||
))?;
|
||||
let name = index.main.name(&reader)?.ok_or(ResponseError::internal(
|
||||
"Impossible to get the name of an index",
|
||||
))?;
|
||||
let created_at = index
|
||||
.main
|
||||
.created_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the create date of an index".to_string(),
|
||||
.created_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the create date of an index",
|
||||
))?;
|
||||
let updated_at = index
|
||||
.main
|
||||
.updated_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the last update date of an index".to_string(),
|
||||
.updated_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the last update date of an index",
|
||||
))?;
|
||||
|
||||
let primary_key = match index.main.schema(&reader) {
|
||||
@ -95,37 +85,28 @@ pub async fn list_indexes(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
|
||||
pub async fn get_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let name = index
|
||||
.main
|
||||
.name(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the name of an index".to_string(),
|
||||
))?;
|
||||
let name = index.main.name(&reader)?.ok_or(ResponseError::internal(
|
||||
"Impossible to get the name of an index",
|
||||
))?;
|
||||
let created_at = index
|
||||
.main
|
||||
.created_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the create date of an index".to_string(),
|
||||
.created_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the create date of an index",
|
||||
))?;
|
||||
let updated_at = index
|
||||
.main
|
||||
.updated_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the last update date of an index".to_string(),
|
||||
.updated_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the last update date of an index",
|
||||
))?;
|
||||
|
||||
let primary_key = match index.main.schema(&reader) {
|
||||
@ -157,11 +138,11 @@ pub struct IndexCreateRequest {
|
||||
pub async fn create_index(
|
||||
data: web::Data<Data>,
|
||||
body: web::Json<IndexCreateRequest>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
if let (None, None) = (body.name.clone(), body.uid.clone()) {
|
||||
return Err(
|
||||
ResponseError::BadRequest("Index creation must have an uid".to_string()).into(),
|
||||
);
|
||||
return Err(ResponseError::bad_request(
|
||||
"Index creation must have an uid",
|
||||
));
|
||||
}
|
||||
|
||||
let uid = match body.uid.clone() {
|
||||
@ -172,7 +153,7 @@ pub async fn create_index(
|
||||
{
|
||||
uid
|
||||
} else {
|
||||
return Err(ResponseError::InvalidIndexUid.into());
|
||||
return Err(ResponseError::InvalidIndexUid);
|
||||
}
|
||||
}
|
||||
None => loop {
|
||||
@ -186,50 +167,33 @@ pub async fn create_index(
|
||||
let created_index = data
|
||||
.db
|
||||
.create_index(&uid)
|
||||
.map_err(|e| ResponseError::CreateIndex(e.to_string()))?;
|
||||
.map_err(ResponseError::create_index)?;
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.main_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.main_write_txn()?;
|
||||
|
||||
let name = body.name.clone().unwrap_or(uid.clone());
|
||||
created_index
|
||||
.main
|
||||
.put_name(&mut writer, &name)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
created_index.main.put_name(&mut writer, &name)?;
|
||||
|
||||
let created_at = created_index
|
||||
.main
|
||||
.created_at(&writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal("".to_string()))?;
|
||||
.created_at(&writer)?
|
||||
.ok_or(ResponseError::internal("Impossible to read created at"))?;
|
||||
|
||||
let updated_at = created_index
|
||||
.main
|
||||
.updated_at(&writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal("".to_string()))?;
|
||||
.updated_at(&writer)?
|
||||
.ok_or(ResponseError::internal("Impossible to read updated at"))?;
|
||||
|
||||
if let Some(id) = body.primary_key.clone() {
|
||||
if let Some(mut schema) = created_index
|
||||
.main
|
||||
.schema(&writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
{
|
||||
if let Some(mut schema) = created_index.main.schema(&writer)? {
|
||||
schema
|
||||
.set_primary_key(&id)
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
created_index
|
||||
.main
|
||||
.put_schema(&mut writer, &schema)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
.map_err(ResponseError::bad_request)?;
|
||||
created_index.main.put_schema(&mut writer, &schema)?;
|
||||
}
|
||||
}
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Created().json(IndexResponse {
|
||||
name,
|
||||
@ -262,83 +226,53 @@ pub async fn update_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<IndexCreateRequest>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.main_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.main_write_txn()?;
|
||||
|
||||
if let Some(name) = body.name.clone() {
|
||||
index
|
||||
.main
|
||||
.put_name(&mut writer, &name)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
index.main.put_name(&mut writer, &name)?;
|
||||
}
|
||||
|
||||
if let Some(id) = body.primary_key.clone() {
|
||||
if let Some(mut schema) = index
|
||||
.main
|
||||
.schema(&writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
{
|
||||
if let Some(mut schema) = index.main.schema(&writer)? {
|
||||
match schema.primary_key() {
|
||||
Some(_) => {
|
||||
return Err(ResponseError::BadRequest(
|
||||
"The primary key cannot be updated".to_string(),
|
||||
)
|
||||
.into());
|
||||
return Err(ResponseError::bad_request(
|
||||
"The primary key cannot be updated",
|
||||
));
|
||||
}
|
||||
None => {
|
||||
schema
|
||||
.set_primary_key(&id)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
index
|
||||
.main
|
||||
.put_schema(&mut writer, &schema)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
schema.set_primary_key(&id)?;
|
||||
index.main.put_schema(&mut writer, &schema)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index
|
||||
.main
|
||||
.put_updated_at(&mut writer)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
index.main.put_updated_at(&mut writer)?;
|
||||
writer.commit()?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let name = index
|
||||
.main
|
||||
.name(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the name of an index".to_string(),
|
||||
))?;
|
||||
let name = index.main.name(&reader)?.ok_or(ResponseError::internal(
|
||||
"Impossible to get the name of an index",
|
||||
))?;
|
||||
let created_at = index
|
||||
.main
|
||||
.created_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the create date of an index".to_string(),
|
||||
.created_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the create date of an index",
|
||||
))?;
|
||||
let updated_at = index
|
||||
.main
|
||||
.updated_at(&reader)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to get the last update date of an index".to_string(),
|
||||
.updated_at(&reader)?
|
||||
.ok_or(ResponseError::internal(
|
||||
"Impossible to get the last update date of an index",
|
||||
))?;
|
||||
|
||||
let primary_key = match index.main.schema(&reader) {
|
||||
@ -362,12 +296,10 @@ pub async fn update_index(
|
||||
pub async fn delete_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
data.db
|
||||
.delete_index(&path.index_uid)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
data.db.delete_index(&path.index_uid)?;
|
||||
|
||||
HttpResponse::NoContent().await
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize)]
|
||||
@ -380,24 +312,22 @@ pub struct UpdateParam {
|
||||
pub async fn get_update_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<UpdateParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.update_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.update_read_txn()?;
|
||||
|
||||
let status = index
|
||||
.update_status(&reader, path.update_id)
|
||||
.map_err(|e| ResponseError::Internal(e.to_string()))?;
|
||||
let status = index.update_status(&reader, path.update_id)?;
|
||||
|
||||
match status {
|
||||
Some(status) => Ok(HttpResponse::Ok().json(status)),
|
||||
None => Err(ResponseError::NotFound(format!("Update {} not found", path.update_id)).into()),
|
||||
None => Err(ResponseError::NotFound(format!(
|
||||
"Update {} not found",
|
||||
path.update_id
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,20 +335,15 @@ pub async fn get_update_status(
|
||||
pub async fn get_all_updates_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.update_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.update_read_txn()?;
|
||||
|
||||
let response = index
|
||||
.all_updates_status(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let response = index.all_updates_status(&reader)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
|
@ -2,13 +2,11 @@ use std::collections::{HashSet, HashMap};
|
||||
use std::time::Duration;
|
||||
|
||||
use log::warn;
|
||||
use meilisearch_core::Index;
|
||||
use actix_web as aweb;
|
||||
use actix_web::{get, web};
|
||||
use serde::{Deserialize};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::meilisearch::{Error, IndexSearchExt, SearchResult};
|
||||
use crate::helpers::meilisearch::{IndexSearchExt, SearchResult};
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
@ -32,24 +30,18 @@ pub async fn search_with_url_query(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<SearchQuery>,
|
||||
) -> aweb::Result<web::Json<SearchResult>> {
|
||||
) -> Result<web::Json<SearchResult>, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.ok_or(ResponseError::Internal(
|
||||
"Impossible to retrieve the schema".to_string(),
|
||||
))?;
|
||||
.schema(&reader)?
|
||||
.ok_or(ResponseError::internal("Impossible to retrieve the schema"))?;
|
||||
|
||||
let mut search_builder = index.new_search(params.q.clone());
|
||||
|
||||
@ -145,11 +137,5 @@ pub async fn search_with_url_query(
|
||||
}
|
||||
}
|
||||
|
||||
let response = match search_builder.search(&reader) {
|
||||
Ok(response) => response,
|
||||
Err(Error::Internal(message)) => return Err(ResponseError::Internal(message).into()),
|
||||
Err(others) => return Err(ResponseError::BadRequest(others.to_string()).into()),
|
||||
};
|
||||
|
||||
Ok(web::Json(response))
|
||||
Ok(web::Json(search_builder.search(&reader)?))
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use actix_web as aweb;
|
||||
use actix_web::{delete, get, post, web, HttpResponse};
|
||||
use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
@ -12,26 +11,19 @@ pub async fn update_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Settings>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = body
|
||||
.into_inner()
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -40,71 +32,42 @@ pub async fn update_all(
|
||||
pub async fn get_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let stop_words_fst = index
|
||||
.main
|
||||
.stop_words_fst(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let stop_words = stop_words_fst
|
||||
.unwrap_or_default()
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let stop_words_fst = index.main.stop_words_fst(&reader)?;
|
||||
let stop_words = stop_words_fst.unwrap_or_default().stream().into_strs()?;
|
||||
let stop_words: BTreeSet<String> = stop_words.into_iter().collect();
|
||||
|
||||
let synonyms_fst = index
|
||||
.main
|
||||
.synonyms_fst(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.unwrap_or_default();
|
||||
let synonyms_list = synonyms_fst
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let synonyms_fst = index.main.synonyms_fst(&reader)?.unwrap_or_default();
|
||||
let synonyms_list = synonyms_fst.stream().into_strs()?;
|
||||
|
||||
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())
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
|
||||
if let Some(list) = alternative_list {
|
||||
let list = list
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let list = list.stream().into_strs()?;
|
||||
synonyms.insert(synonym, list);
|
||||
}
|
||||
}
|
||||
|
||||
let ranking_rules = index
|
||||
.main
|
||||
.ranking_rules(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.ranking_rules(&reader)?
|
||||
.unwrap_or(DEFAULT_RANKING_RULES.to_vec())
|
||||
.into_iter()
|
||||
.map(|r| r.to_string())
|
||||
.collect();
|
||||
|
||||
let distinct_attribute = index
|
||||
.main
|
||||
.distinct_attribute(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let distinct_attribute = index.main.distinct_attribute(&reader)?;
|
||||
|
||||
let schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
|
||||
let searchable_attributes = schema.clone().map(|s| {
|
||||
s.indexed_name()
|
||||
@ -139,15 +102,12 @@ pub async fn get_all(
|
||||
pub async fn delete_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
ranking_rules: UpdateState::Clear,
|
||||
@ -160,12 +120,8 @@ pub async fn delete_all(
|
||||
accept_new_fields: UpdateState::Clear,
|
||||
};
|
||||
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -174,20 +130,16 @@ pub async fn delete_all(
|
||||
pub async fn get_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let ranking_rules = index
|
||||
.main
|
||||
.ranking_rules(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.ranking_rules(&reader)?
|
||||
.unwrap_or(DEFAULT_RANKING_RULES.to_vec())
|
||||
.into_iter()
|
||||
.map(|r| r.to_string())
|
||||
@ -201,30 +153,21 @@ pub async fn update_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<Vec<String>>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = Settings {
|
||||
ranking_rules: Some(body.into_inner()),
|
||||
..Settings::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let settings = settings
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = settings.into_update().map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -233,28 +176,21 @@ pub async fn update_rules(
|
||||
pub async fn delete_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::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)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -263,19 +199,13 @@ pub async fn delete_rules(
|
||||
pub async fn get_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let distinct_attribute = index
|
||||
.main
|
||||
.distinct_attribute(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
let distinct_attribute = index.main.distinct_attribute(&reader)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(distinct_attribute))
|
||||
}
|
||||
@ -285,30 +215,21 @@ pub async fn update_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<String>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = Settings {
|
||||
distinct_attribute: Some(body.into_inner()),
|
||||
..Settings::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let settings = settings
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = settings.into_update().map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -317,28 +238,21 @@ pub async fn update_distinct(
|
||||
pub async fn delete_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::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)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -347,19 +261,13 @@ pub async fn delete_distinct(
|
||||
pub async fn get_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
let searchable_attributes: Option<Vec<String>> =
|
||||
schema.map(|s| s.indexed_name().iter().map(|i| (*i).to_string()).collect());
|
||||
|
||||
@ -371,30 +279,21 @@ pub async fn update_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<Vec<String>>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = Settings {
|
||||
searchable_attributes: Some(body.into_inner()),
|
||||
..Settings::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let settings = settings
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = settings.into_update().map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -403,27 +302,20 @@ pub async fn update_searchable(
|
||||
pub async fn delete_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
searchable_attributes: UpdateState::Clear,
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -432,20 +324,14 @@ pub async fn delete_searchable(
|
||||
pub async fn get_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
|
||||
let displayed_attributes: Option<HashSet<String>> = schema.map(|s| {
|
||||
s.displayed_name()
|
||||
@ -462,30 +348,21 @@ pub async fn update_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<HashSet<String>>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = Settings {
|
||||
displayed_attributes: Some(body.into_inner()),
|
||||
..Settings::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let settings = settings
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = settings.into_update().map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -494,27 +371,20 @@ pub async fn update_displayed(
|
||||
pub async fn delete_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
displayed_attributes: UpdateState::Clear,
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -523,20 +393,14 @@ pub async fn delete_displayed(
|
||||
pub async fn get_accept_new_fields(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let schema = index
|
||||
.main
|
||||
.schema(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
|
||||
let accept_new_fields = schema.map(|s| s.accept_new_fields());
|
||||
|
||||
@ -548,30 +412,21 @@ pub async fn update_accept_new_fields(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<bool>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = Settings {
|
||||
accept_new_fields: Some(body.into_inner()),
|
||||
..Settings::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let settings = settings
|
||||
.into_update()
|
||||
.map_err(|e| ResponseError::BadRequest(e.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let settings = settings.into_update().map_err(ResponseError::bad_request)?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix_web as aweb;
|
||||
use actix_web::{get, web};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
@ -25,36 +24,22 @@ pub struct IndexStatsResponse {
|
||||
pub async fn index_stats(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<web::Json<IndexStatsResponse>> {
|
||||
) -> Result<web::Json<IndexStatsResponse>, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(path.index_uid.clone())
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let number_of_documents = index
|
||||
.main
|
||||
.number_of_documents(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let number_of_documents = index.main.number_of_documents(&reader)?;
|
||||
|
||||
let fields_frequency = index
|
||||
.main
|
||||
.fields_frequency(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.unwrap_or_default();
|
||||
let fields_frequency = index.main.fields_frequency(&reader)?.unwrap_or_default();
|
||||
|
||||
let update_reader = data
|
||||
.db
|
||||
.update_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_reader = data.db.update_read_txn()?;
|
||||
|
||||
let is_indexing = data
|
||||
.is_indexing(&update_reader, &path.index_uid)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.is_indexing(&update_reader, &path.index_uid)?
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(web::Json(IndexStatsResponse {
|
||||
@ -73,37 +58,23 @@ pub struct StatsResult {
|
||||
}
|
||||
|
||||
#[get("/stats")]
|
||||
pub async fn get_stats(data: web::Data<Data>) -> aweb::Result<web::Json<StatsResult>> {
|
||||
pub async fn get_stats(data: web::Data<Data>) -> Result<web::Json<StatsResult>, ResponseError> {
|
||||
let mut index_list = HashMap::new();
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_reader = data
|
||||
.db
|
||||
.update_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
let update_reader = data.db.update_read_txn()?;
|
||||
|
||||
let indexes_set = data.db.indexes_uids();
|
||||
for index_uid in indexes_set {
|
||||
let index = data.db.open_index(&index_uid);
|
||||
match index {
|
||||
Some(index) => {
|
||||
let number_of_documents = index
|
||||
.main
|
||||
.number_of_documents(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let number_of_documents = index.main.number_of_documents(&reader)?;
|
||||
|
||||
let fields_frequency = index
|
||||
.main
|
||||
.fields_frequency(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.unwrap_or_default();
|
||||
let fields_frequency = index.main.fields_frequency(&reader)?.unwrap_or_default();
|
||||
|
||||
let is_indexing = data
|
||||
.is_indexing(&update_reader, &index_uid)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.is_indexing(&update_reader, &index_uid)?
|
||||
.unwrap_or_default();
|
||||
|
||||
let response = IndexStatsResponse {
|
||||
@ -120,16 +91,14 @@ pub async fn get_stats(data: web::Data<Data>) -> aweb::Result<web::Json<StatsRes
|
||||
}
|
||||
}
|
||||
|
||||
let database_size = WalkDir::new(data.db_path.clone())
|
||||
let database_size = WalkDir::new(&data.db_path)
|
||||
.into_iter()
|
||||
.filter_map(|entry| entry.ok())
|
||||
.filter_map(|entry| entry.metadata().ok())
|
||||
.filter(|metadata| metadata.is_file())
|
||||
.fold(0, |acc, m| acc + m.len());
|
||||
|
||||
let last_update = data
|
||||
.last_update(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let last_update = data.last_update(&reader)?;
|
||||
|
||||
Ok(web::Json(StatsResult {
|
||||
database_size,
|
||||
|
@ -1,32 +1,23 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use actix_web as aweb;
|
||||
use actix_web::{delete, get, post, web, HttpResponse};
|
||||
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::Data;
|
||||
|
||||
#[get("/indexes/{index_uid}/settings/stop-words")]
|
||||
pub async fn get(data: web::Data<Data>, path: web::Path<IndexParam>) -> aweb::Result<HttpResponse> {
|
||||
pub async fn get(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let stop_words_fst = index
|
||||
.main
|
||||
.stop_words_fst(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let stop_words = stop_words_fst
|
||||
.unwrap_or_default()
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
.ok_or(ResponseError::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.unwrap_or_default().stream().into_strs()?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(stop_words))
|
||||
}
|
||||
@ -36,27 +27,20 @@ pub async fn update(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<BTreeSet<String>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
stop_words: UpdateState::Update(body.into_inner()),
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -65,27 +49,20 @@ pub async fn update(
|
||||
pub async fn delete(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
stop_words: UpdateState::Clear,
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use actix_web as aweb;
|
||||
use actix_web::{delete, get, post, web, HttpResponse};
|
||||
use indexmap::IndexMap;
|
||||
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
|
||||
@ -10,41 +9,27 @@ use crate::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::Data;
|
||||
|
||||
#[get("/indexes/{index_uid}/settings/synonyms")]
|
||||
pub async fn get(data: web::Data<Data>, path: web::Path<IndexParam>) -> aweb::Result<HttpResponse> {
|
||||
pub async fn get(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let reader = data
|
||||
.db
|
||||
.main_read_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let reader = data.db.main_read_txn()?;
|
||||
|
||||
let synonyms_fst = index
|
||||
.main
|
||||
.synonyms_fst(&reader)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?
|
||||
.unwrap_or_default();
|
||||
let synonyms_list = synonyms_fst
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let synonyms_fst = index.main.synonyms_fst(&reader)?.unwrap_or_default();
|
||||
let synonyms_list = synonyms_fst.stream().into_strs()?;
|
||||
|
||||
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())
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
|
||||
|
||||
if let Some(list) = alternative_list {
|
||||
let list = list
|
||||
.stream()
|
||||
.into_strs()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let list = list.stream().into_strs()?;
|
||||
synonyms.insert(synonym, list);
|
||||
}
|
||||
}
|
||||
@ -57,27 +42,20 @@ pub async fn update(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<BTreeMap<String, Vec<String>>>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
synonyms: UpdateState::Update(body.into_inner()),
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
@ -86,28 +64,21 @@ pub async fn update(
|
||||
pub async fn delete(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> aweb::Result<HttpResponse> {
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.open_index(&path.index_uid)
|
||||
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
|
||||
.ok_or(ResponseError::index_not_found(&path.index_uid))?;
|
||||
|
||||
let settings = SettingsUpdate {
|
||||
synonyms: UpdateState::Clear,
|
||||
..SettingsUpdate::default()
|
||||
};
|
||||
|
||||
let mut writer = data
|
||||
.db
|
||||
.update_write_txn()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let update_id = index
|
||||
.settings_update(&mut writer, settings)
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
let mut writer = data.db.update_write_txn()?;
|
||||
let update_id = index.settings_update(&mut writer, settings)?;
|
||||
|
||||
writer
|
||||
.commit()
|
||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||
writer.commit()?;
|
||||
|
||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user