clippy + fmt

This commit is contained in:
Quentin de Quelen 2020-04-10 19:05:05 +02:00 committed by qdequele
parent 22fbff98d4
commit 6a1f73a304
No known key found for this signature in database
GPG Key ID: B3F0A000EBF11745
17 changed files with 633 additions and 339 deletions

View File

@ -135,7 +135,7 @@ impl Data {
let db = Arc::new(Database::open_or_create(opt.db_path).unwrap()); let db = Arc::new(Database::open_or_create(opt.db_path).unwrap());
let mut api_keys = ApiKeys { let mut api_keys = ApiKeys {
master: opt.master_key.clone(), master: opt.master_key,
private: None, private: None,
public: None, public: None,
}; };

View File

@ -1,8 +1,9 @@
use std::fmt; use std::fmt;
use serde_json::json;
use actix_web as aweb;
use actix_http::ResponseBuilder; use actix_http::ResponseBuilder;
use actix_web as aweb;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use serde_json::json;
#[derive(Debug)] #[derive(Debug)]
pub enum ResponseError { pub enum ResponseError {

View File

@ -1,14 +1,14 @@
use std::{env, thread}; use std::{env, thread};
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use log::info; use log::info;
use main_error::MainError; use main_error::MainError;
use structopt::StructOpt;
use actix_web::middleware::Logger;
use actix_web::{web, HttpServer, App};
use meilisearch_http::data::Data; use meilisearch_http::data::Data;
use meilisearch_http::option::Opt; use meilisearch_http::option::Opt;
use meilisearch_http::routes; use meilisearch_http::routes;
use meilisearch_http::routes::index_update_callback; use meilisearch_http::routes::index_update_callback;
use structopt::StructOpt;
mod analytics; mod analytics;
@ -30,7 +30,7 @@ async fn main() -> Result<(), MainError> {
.into(), .into(),
); );
} }
}, }
"development" => { "development" => {
env_logger::from_env(env_logger::Env::default().default_filter_or("info")).init(); env_logger::from_env(env_logger::Env::default().default_filter_or("info")).init();
} }
@ -50,7 +50,7 @@ async fn main() -> Result<(), MainError> {
print_launch_resume(&opt, &data); print_launch_resume(&opt, &data);
HttpServer::new(move || HttpServer::new(move || {
App::new() App::new()
.wrap(Logger::default()) .wrap(Logger::default())
.app_data(web::Data::new(data.clone())) .app_data(web::Data::new(data.clone()))
@ -103,10 +103,10 @@ async fn main() -> Result<(), MainError> {
.service(routes::stats::get_sys_info_pretty) .service(routes::stats::get_sys_info_pretty)
.service(routes::health::get_health) .service(routes::health::get_health)
.service(routes::health::change_healthyness) .service(routes::health::change_healthyness)
) })
.bind(opt.http_addr)? .bind(opt.http_addr)?
.run() .run()
.await?; .await?;
Ok(()) Ok(())
} }

View File

@ -1,20 +1,21 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use actix_web as aweb;
use actix_web::{delete, get, post, put, web, HttpResponse};
use indexmap::IndexMap; use indexmap::IndexMap;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use actix_web::{web, get, post, put, delete, HttpResponse};
use actix_web as aweb;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
use crate::routes::{IndexUpdateResponse, IndexParam};
type Document = IndexMap<String, Value>; type Document = IndexMap<String, Value>;
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct DocumentParam { pub struct DocumentParam {
index_uid: String, index_uid: String,
document_id: String document_id: String,
} }
#[get("/indexes/{index_uid}/documents/{document_id}")] #[get("/indexes/{index_uid}/documents/{document_id}")]
@ -22,14 +23,19 @@ pub async fn get_document(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<DocumentParam>, path: web::Path<DocumentParam>,
) -> aweb::Result<web::Json<Document>> { ) -> aweb::Result<web::Json<Document>> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone()); let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone());
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let response = index.document::<Document, String>(&reader, None, document_id) let response = index
.document::<Document, String>(&reader, None, document_id)
.map_err(|_| ResponseError::DocumentNotFound(path.document_id.clone()))? .map_err(|_| ResponseError::DocumentNotFound(path.document_id.clone()))?
.ok_or(ResponseError::DocumentNotFound(path.document_id.clone()))?; .ok_or(ResponseError::DocumentNotFound(path.document_id.clone()))?;
@ -41,26 +47,31 @@ pub async fn delete_document(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<DocumentParam>, path: web::Path<DocumentParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone()); let document_id = meilisearch_core::serde::compute_document_id(path.document_id.clone());
let mut update_writer = data.db.update_write_txn() let mut update_writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut documents_deletion = index.documents_deletion(); let mut documents_deletion = index.documents_deletion();
documents_deletion.delete_document_by_id(document_id); documents_deletion.delete_document_by_id(document_id);
let update_id = documents_deletion.finalize(&mut update_writer) let update_id = documents_deletion
.finalize(&mut update_writer)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
update_writer.commit() update_writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct BrowseQuery { pub struct BrowseQuery {
@ -75,14 +86,17 @@ pub async fn get_all_documents(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<BrowseQuery>, params: web::Query<BrowseQuery>,
) -> aweb::Result<web::Json<Vec<Document>>> { ) -> aweb::Result<web::Json<Vec<Document>>> {
let index = data
let index = data.db.open_index(&path.index_uid) .db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let offset = params.offset.unwrap_or(0); let offset = params.offset.unwrap_or(0);
let limit = params.limit.unwrap_or(20); let limit = params.limit.unwrap_or(20);
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let documents_ids: Result<BTreeSet<_>, _> = index let documents_ids: Result<BTreeSet<_>, _> = index
@ -93,10 +107,11 @@ pub async fn get_all_documents(
.take(limit) .take(limit)
.collect(); .collect();
let documents_ids = documents_ids let documents_ids = documents_ids.map_err(|err| ResponseError::Internal(err.to_string()))?;
.map_err(|err| ResponseError::Internal(err.to_string()))?;
let attributes = params.attributes_to_retrieve.clone() let attributes = params
.attributes_to_retrieve
.clone()
.map(|a| a.split(',').map(|a| a.to_string()).collect()); .map(|a| a.split(',').map(|a| a.to_string()).collect());
let mut response_body = Vec::<Document>::new(); let mut response_body = Vec::<Document>::new();
@ -129,39 +144,48 @@ async fn update_multiple_documents(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>, params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>>, body: web::Json<Vec<Document>>,
is_partial: bool is_partial: bool,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut schema = index let mut schema = index
.main .main
.schema(&reader) .schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.ok_or(ResponseError::Internal("Impossible to retrieve the schema".to_string()))?; .ok_or(ResponseError::Internal(
"Impossible to retrieve the schema".to_string(),
))?;
if schema.primary_key().is_none() { if schema.primary_key().is_none() {
let id = match params.primary_key.clone() { let id = match params.primary_key.clone() {
Some(id) => id, Some(id) => id,
None => { None => body.first().and_then(|docs| find_primary_key(docs)).ok_or(
body.first() ResponseError::BadRequest("Impossible to infer the primary key".to_string()),
.and_then(|docs| find_primary_key(docs)) )?,
.ok_or(ResponseError::BadRequest("Impossible to infer the primary key".to_string()))?
}
}; };
let mut writer = data.db.main_write_txn() let mut writer = data
.db
.main_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
schema.set_primary_key(&id) schema
.set_primary_key(&id)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
index.main.put_schema(&mut writer, &schema) index
.main
.put_schema(&mut writer, &schema)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
} }
@ -175,11 +199,15 @@ async fn update_multiple_documents(
document_addition.update_document(document); document_addition.update_document(document);
} }
let mut update_writer = data.db.update_write_txn() let mut update_writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = document_addition.finalize(&mut update_writer) let update_id = document_addition
.finalize(&mut update_writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
update_writer.commit() update_writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -190,7 +218,7 @@ pub async fn add_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>, params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>> body: web::Json<Vec<Document>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
update_multiple_documents(data, path, params, body, false).await update_multiple_documents(data, path, params, body, false).await
} }
@ -200,7 +228,7 @@ pub async fn update_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>, params: web::Query<UpdateDocumentsQuery>,
body: web::Json<Vec<Document>> body: web::Json<Vec<Document>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
update_multiple_documents(data, path, params, body, true).await update_multiple_documents(data, path, params, body, true).await
} }
@ -209,13 +237,16 @@ pub async fn update_documents(
pub async fn delete_documents( pub async fn delete_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Vec<Value>> body: web::Json<Vec<Value>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut documents_deletion = index.documents_deletion(); let mut documents_deletion = index.documents_deletion();
@ -227,10 +258,12 @@ pub async fn delete_documents(
} }
} }
let update_id = documents_deletion.finalize(&mut writer) let update_id = documents_deletion
.finalize(&mut writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -241,17 +274,22 @@ pub async fn clear_all_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.clear_all(&mut writer) let update_id = index
.clear_all(&mut writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))

View File

@ -1,17 +1,17 @@
use crate::error::ResponseError; use crate::error::ResponseError;
use actix_web::{web, get, put, HttpResponse};
use actix_web as aweb;
use crate::Data; use crate::Data;
use actix_web as aweb;
use actix_web::{get, put, web, HttpResponse};
use heed::types::{Str, Unit}; use heed::types::{Str, Unit};
use serde::Deserialize; use serde::Deserialize;
const UNHEALTHY_KEY: &str = "_is_unhealthy"; const UNHEALTHY_KEY: &str = "_is_unhealthy";
#[get("/health")] #[get("/health")]
pub async fn get_health( pub async fn get_health(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
data: web::Data<Data>, let reader = data
) -> aweb::Result<HttpResponse> { .db
let reader = data.db.main_read_txn() .main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
@ -23,29 +23,33 @@ pub async fn get_health(
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
pub async fn set_healthy( pub async fn set_healthy(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
data: web::Data<Data>, let mut writer = data
) -> aweb::Result<HttpResponse> { .db
let mut writer = data.db.main_write_txn() .main_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY) common_store
.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
pub async fn set_unhealthy( pub async fn set_unhealthy(data: web::Data<Data>) -> aweb::Result<HttpResponse> {
data: web::Data<Data>, let mut writer = data
) -> aweb::Result<HttpResponse> { .db
let mut writer = data.db.main_write_txn() .main_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &()) common_store
.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())

View File

@ -1,14 +1,14 @@
use actix_web as aweb;
use actix_web::{delete, get, post, web, HttpResponse};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use log::error; use log::error;
use meilisearch_core::UpdateStatus;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use actix_web::{web, get, post, delete, HttpResponse};
use actix_web as aweb;
use meilisearch_core::UpdateStatus;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::Data;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data;
fn generate_uid() -> String { fn generate_uid() -> String {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@ -30,11 +30,10 @@ pub struct IndexResponse {
} }
#[get("/indexes")] #[get("/indexes")]
pub async fn list_indexes( pub async fn list_indexes(data: web::Data<Data>) -> aweb::Result<web::Json<Vec<IndexResponse>>> {
data: web::Data<Data>, let reader = data
) -> aweb::Result<web::Json<Vec<IndexResponse>>> { .db
.main_read_txn()
let reader = data.db.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut response_body = Vec::new(); let mut response_body = Vec::new();
@ -44,15 +43,27 @@ pub async fn list_indexes(
match index { match index {
Some(index) => { Some(index) => {
let name = index.main.name(&reader) let name = index
.main
.name(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the name of an index".to_string()))?; .ok_or(ResponseError::Internal(
let created_at = index.main.created_at(&reader) "Impossible to get the name of an index".to_string(),
))?;
let created_at = index
.main
.created_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the create date of an index".to_string()))?; .ok_or(ResponseError::Internal(
let updated_at = index.main.updated_at(&reader) "Impossible to get the create date of an index".to_string(),
))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the last update date of an index".to_string()))?; .ok_or(ResponseError::Internal(
"Impossible to get the last update date of an index".to_string(),
))?;
let primary_key = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => match schema.primary_key() { Ok(Some(schema)) => match schema.primary_key() {
@ -86,22 +97,37 @@ pub async fn get_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<web::Json<IndexResponse>> { ) -> aweb::Result<web::Json<IndexResponse>> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let name = index.main.name(&reader) let name = index
.main
.name(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the name of an index".to_string()))?; .ok_or(ResponseError::Internal(
let created_at = index.main.created_at(&reader) "Impossible to get the name of an index".to_string(),
))?;
let created_at = index
.main
.created_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the create date of an index".to_string()))?; .ok_or(ResponseError::Internal(
let updated_at = index.main.updated_at(&reader) "Impossible to get the create date of an index".to_string(),
))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the last update date of an index".to_string()))?; .ok_or(ResponseError::Internal(
"Impossible to get the last update date of an index".to_string(),
))?;
let primary_key = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => match schema.primary_key() { Ok(Some(schema)) => match schema.primary_key() {
@ -131,11 +157,12 @@ pub struct IndexCreateRequest {
#[post("/indexes")] #[post("/indexes")]
pub async fn create_index( pub async fn create_index(
data: web::Data<Data>, data: web::Data<Data>,
body: web::Json<IndexCreateRequest> body: web::Json<IndexCreateRequest>,
) -> aweb::Result<web::Json<IndexResponse>> { ) -> aweb::Result<web::Json<IndexResponse>> {
if let (None, None) = (body.name.clone(), body.uid.clone()) { 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::BadRequest("Index creation must have an uid".to_string()).into(),
);
} }
let uid = match body.uid.clone() { let uid = match body.uid.clone() {
@ -157,14 +184,20 @@ pub async fn create_index(
}, },
}; };
let created_index = data.db.create_index(&uid) let created_index = data
.db
.create_index(&uid)
.map_err(|e| ResponseError::CreateIndex(e.to_string()))?; .map_err(|e| ResponseError::CreateIndex(e.to_string()))?;
let mut writer = data.db.main_write_txn() let mut writer = data
.db
.main_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let name = body.name.clone().unwrap_or(uid.clone()); let name = body.name.clone().unwrap_or(uid.clone());
created_index.main.put_name(&mut writer, &name) created_index
.main
.put_name(&mut writer, &name)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
let created_at = created_index let created_at = created_index
@ -180,16 +213,23 @@ pub async fn create_index(
.ok_or(ResponseError::Internal("".to_string()))?; .ok_or(ResponseError::Internal("".to_string()))?;
if let Some(id) = body.primary_key.clone() { if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = created_index.main.schema(&mut writer) if let Some(mut schema) = created_index
.map_err(|e| ResponseError::Internal(e.to_string()))? { .main
schema.set_primary_key(&id) .schema(&writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?
{
schema
.set_primary_key(&id)
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
created_index.main.put_schema(&mut writer, &schema) created_index
.main
.put_schema(&mut writer, &schema)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
} }
} }
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(web::Json(IndexResponse { Ok(web::Json(IndexResponse {
@ -222,55 +262,85 @@ pub struct UpdateIndexResponse {
pub async fn update_index( pub async fn update_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<IndexCreateRequest> body: web::Json<IndexCreateRequest>,
) -> aweb::Result<web::Json<IndexResponse>> { ) -> aweb::Result<web::Json<IndexResponse>> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.main_write_txn() let mut writer = data
.map_err(|err| ResponseError::Internal(err.to_string()))?; .db
.main_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?;
if let Some(name) = body.name.clone() { if let Some(name) = body.name.clone() {
index.main.put_name(&mut writer, &name) index
.main
.put_name(&mut writer, &name)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
} }
if let Some(id) = body.primary_key.clone() { if let Some(id) = body.primary_key.clone() {
if let Some(mut schema) = index.main.schema(&mut writer) if let Some(mut schema) = index
.map_err(|e| ResponseError::Internal(e.to_string()))? { .main
.schema(&writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?
{
match schema.primary_key() { match schema.primary_key() {
Some(_) => { Some(_) => {
return Err(ResponseError::BadRequest("The primary key cannot be updated".to_string()).into()); return Err(ResponseError::BadRequest(
"The primary key cannot be updated".to_string(),
)
.into());
} }
None => { None => {
schema schema
.set_primary_key(&id) .set_primary_key(&id)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
index.main.put_schema(&mut writer, &schema) index
.main
.put_schema(&mut writer, &schema)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
} }
} }
} }
} }
index.main.put_updated_at(&mut writer) index
.main
.put_updated_at(&mut writer)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let name = index.main.name(&reader) let name = index
.main
.name(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the name of an index".to_string()))?; .ok_or(ResponseError::Internal(
let created_at = index.main.created_at(&reader) "Impossible to get the name of an index".to_string(),
))?;
let created_at = index
.main
.created_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the create date of an index".to_string()))?; .ok_or(ResponseError::Internal(
let updated_at = index.main.updated_at(&reader) "Impossible to get the create date of an index".to_string(),
))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(|e| ResponseError::Internal(e.to_string()))? .map_err(|e| ResponseError::Internal(e.to_string()))?
.ok_or(ResponseError::Internal("Impossible to get the last update date of an index".to_string()))?; .ok_or(ResponseError::Internal(
"Impossible to get the last update date of an index".to_string(),
))?;
let primary_key = match index.main.schema(&reader) { let primary_key = match index.main.schema(&reader) {
Ok(Some(schema)) => match schema.primary_key() { Ok(Some(schema)) => match schema.primary_key() {
@ -294,8 +364,8 @@ pub async fn delete_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
data.db
data.db.delete_index(&path.index_uid) .delete_index(&path.index_uid)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
HttpResponse::NoContent().await HttpResponse::NoContent().await
@ -304,7 +374,7 @@ pub async fn delete_index(
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct UpdateParam { pub struct UpdateParam {
index_uid: String, index_uid: String,
update_id: u64 update_id: u64,
} }
#[get("/indexes/{index_uid}/updates/{update_id}")] #[get("/indexes/{index_uid}/updates/{update_id}")]
@ -312,19 +382,23 @@ pub async fn get_update_status(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<UpdateParam>, path: web::Path<UpdateParam>,
) -> aweb::Result<web::Json<UpdateStatus>> { ) -> aweb::Result<web::Json<UpdateStatus>> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.update_read_txn() let reader = data
.db
.update_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let status = index.update_status(&reader, path.update_id) let status = index
.update_status(&reader, path.update_id)
.map_err(|e| ResponseError::Internal(e.to_string()))?; .map_err(|e| ResponseError::Internal(e.to_string()))?;
match status { match status {
Some(status) => Ok(web::Json(status)), Some(status) => Ok(web::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)).into()),
} }
} }
@ -333,14 +407,18 @@ pub async fn get_all_updates_status(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<web::Json<Vec<UpdateStatus>>> { ) -> aweb::Result<web::Json<Vec<UpdateStatus>>> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.update_read_txn() let reader = data
.db
.update_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let response = index.all_updates_status(&reader) let response = index
.all_updates_status(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(web::Json(response)) Ok(web::Json(response))

View File

@ -1,8 +1,7 @@
use crate::Data; use crate::Data;
use actix_web::{web, get}; use actix_web::{get, web};
use serde::Serialize; use serde::Serialize;
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
pub struct KeysResponse { pub struct KeysResponse {
private: Option<String>, private: Option<String>,
@ -10,11 +9,9 @@ pub struct KeysResponse {
} }
#[get("/keys")] #[get("/keys")]
pub async fn list( pub async fn list(data: web::Data<Data>) -> web::Json<KeysResponse> {
data: web::Data<Data>,
) -> web::Json<KeysResponse> {
let api_keys = data.api_keys.clone(); let api_keys = data.api_keys.clone();
web::Json(KeysResponse{ web::Json(KeysResponse {
private: api_keys.private, private: api_keys.private,
public: api_keys.public, public: api_keys.public,
}) })

View File

@ -1,7 +1,7 @@
use actix_web::{get, HttpResponse}; use actix_web::{get, HttpResponse};
use serde::{Serialize, Deserialize};
use log::error; use log::error;
use meilisearch_core::ProcessedUpdateResult; use meilisearch_core::ProcessedUpdateResult;
use serde::{Deserialize, Serialize};
use crate::Data; use crate::Data;
@ -10,14 +10,14 @@ pub mod health;
pub mod index; pub mod index;
pub mod key; pub mod key;
pub mod search; pub mod search;
pub mod stats;
pub mod setting; pub mod setting;
pub mod stats;
pub mod stop_words; pub mod stop_words;
pub mod synonym; pub mod synonym;
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct IndexParam { pub struct IndexParam {
index_uid: String index_uid: String,
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
@ -28,9 +28,7 @@ pub struct IndexUpdateResponse {
impl IndexUpdateResponse { impl IndexUpdateResponse {
pub fn with_id(update_id: u64) -> Self { pub fn with_id(update_id: u64) -> Self {
Self { Self { update_id }
update_id,
}
} }
} }
@ -48,7 +46,6 @@ pub async fn load_css() -> HttpResponse {
.body(include_str!("../../public/bulma.min.css").to_string()) .body(include_str!("../../public/bulma.min.css").to_string())
} }
pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) { pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) {
if status.error.is_some() { if status.error.is_some() {
return; return;
@ -82,7 +79,6 @@ pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpda
} }
} }
// pub fn load_routes(app: &mut tide::Server<Data>) { // pub fn load_routes(app: &mut tide::Server<Data>) {
// app.at("/").get(|_| async { // app.at("/").get(|_| async {
// tide::Response::new(200) // tide::Response::new(200)

View File

@ -4,15 +4,15 @@ use std::time::Duration;
use log::warn; use log::warn;
use meilisearch_core::Index; use meilisearch_core::Index;
use actix_web as aweb;
use actix_web::{get, post, web};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use actix_web::{web, get, post};
use actix_web as aweb;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::meilisearch::{Error, IndexSearchExt, SearchHit, SearchResult}; use crate::helpers::meilisearch::{Error, IndexSearchExt, SearchHit, SearchResult};
use crate::Data;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
@ -35,18 +35,23 @@ pub async fn search_with_url_query(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<SearchQuery>, params: web::Query<SearchQuery>,
) -> aweb::Result<web::Json<SearchResult>> { ) -> aweb::Result<web::Json<SearchResult>> {
let index = data
let index = data.db.open_index(path.index_uid.clone()) .db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let schema = index let schema = index
.main .main
.schema(&reader) .schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.ok_or(ResponseError::Internal("Impossible to retrieve the schema".to_string()))?; .ok_or(ResponseError::Internal(
"Impossible to retrieve the schema".to_string(),
))?;
let mut search_builder = index.new_search(params.q.clone()); let mut search_builder = index.new_search(params.q.clone());
@ -182,7 +187,6 @@ pub async fn search_multi_index(
data: web::Data<Data>, data: web::Data<Data>,
body: web::Json<SearchMultiBody>, body: web::Json<SearchMultiBody>,
) -> aweb::Result<web::Json<SearchMultiBodyResponse>> { ) -> aweb::Result<web::Json<SearchMultiBodyResponse>> {
let mut index_list = body.clone().indexes; let mut index_list = body.clone().indexes;
for index in index_list.clone() { for index in index_list.clone() {
@ -203,7 +207,6 @@ pub async fn search_multi_index(
} }
} }
let par_body = body.clone(); let par_body = body.clone();
let responses_per_index: Vec<(String, SearchResult)> = index_list let responses_per_index: Vec<(String, SearchResult)> = index_list
.into_par_iter() .into_par_iter()

View File

@ -1,42 +1,58 @@
use actix_web as aweb;
use actix_web::{delete, get, post, web, HttpResponse};
use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES}; use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES};
use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashSet};
use actix_web::{web, get, post, delete, HttpResponse};
use actix_web as aweb;
use crate::error::{ResponseError}; use crate::error::ResponseError;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
use crate::routes::{IndexUpdateResponse, IndexParam};
#[post("/indexes/{index_uid}/settings")] #[post("/indexes/{index_uid}/settings")]
pub async fn update_all( pub async fn update_all(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let stop_words_fst = index.main.stop_words_fst(&reader) let stop_words_fst = index
.main
.stop_words_fst(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let stop_words = stop_words_fst.unwrap_or_default().stream().into_strs() let stop_words = stop_words_fst
.unwrap_or_default()
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let stop_words: BTreeSet<String> = stop_words.into_iter().collect(); let stop_words: BTreeSet<String> = stop_words.into_iter().collect();
let synonyms_fst = index.main.synonyms_fst(&reader) let synonyms_fst = index
.main
.synonyms_fst(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.unwrap_or_default(); .unwrap_or_default();
let synonyms_list = synonyms_fst.stream().into_strs() let synonyms_list = synonyms_fst
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut synonyms = BTreeMap::new(); let mut synonyms = BTreeMap::new();
let index_synonyms = &index.synonyms; let index_synonyms = &index.synonyms;
for synonym in synonyms_list { for synonym in synonyms_list {
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes()) let alternative_list = index_synonyms
.synonyms(&reader, synonym.as_bytes())
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
if let Some(list) = alternative_list { if let Some(list) = alternative_list {
let list = list.stream().into_strs() let list = list
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
synonyms.insert(synonym, list); synonyms.insert(synonym, list);
} }
@ -51,10 +67,14 @@ pub async fn update_all(
.map(|r| r.to_string()) .map(|r| r.to_string())
.collect(); .collect();
let distinct_attribute = index.main.distinct_attribute(&reader) let distinct_attribute = index
.main
.distinct_attribute(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let schema = index.main.schema(&reader) let schema = index
.main
.schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let searchable_attributes = schema.clone().map(|s| { let searchable_attributes = schema.clone().map(|s| {
@ -92,16 +112,24 @@ pub async fn get_all(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Settings>, body: web::Json<Settings>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = body.into_inner().into_update() let settings = body
.into_inner()
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -112,9 +140,13 @@ pub async fn delete_all(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -128,9 +160,11 @@ pub async fn delete_all(
accept_new_fields: UpdateState::Clear, accept_new_fields: UpdateState::Clear,
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -141,10 +175,14 @@ pub async fn get_rules(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.map_err(|err| ResponseError::Internal(err.to_string()))?; .db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?;
let ranking_rules = index let ranking_rules = index
.main .main
@ -164,7 +202,9 @@ pub async fn update_rules(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>, body: web::Json<Option<Vec<String>>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = Settings { let settings = Settings {
@ -172,13 +212,18 @@ pub async fn update_rules(
..Settings::default() ..Settings::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = settings.into_update() let settings = settings
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -189,9 +234,13 @@ pub async fn delete_rules(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -199,10 +248,12 @@ pub async fn delete_rules(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -213,11 +264,17 @@ pub async fn get_distinct(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let distinct_attribute = index.main.distinct_attribute(&reader) let distinct_attribute = index
.main
.distinct_attribute(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Ok().json(distinct_attribute)) Ok(HttpResponse::Ok().json(distinct_attribute))
@ -229,7 +286,9 @@ pub async fn update_distinct(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<String>>, body: web::Json<Option<String>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = Settings { let settings = Settings {
@ -237,13 +296,18 @@ pub async fn update_distinct(
..Settings::default() ..Settings::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = settings.into_update() let settings = settings
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -254,21 +318,27 @@ pub async fn delete_distinct(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let mut writer = data.db.update_write_txn() let mut writer = data
.map_err(|err| ResponseError::Internal(err.to_string()))?; .db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
distinct_attribute: UpdateState::Clear, distinct_attribute: UpdateState::Clear,
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.map_err(|err| ResponseError::Internal(err.to_string()))?; .settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.map_err(|err| ResponseError::Internal(err.to_string()))?; .commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
@ -278,11 +348,17 @@ pub async fn get_searchable(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let schema = index.main.schema(&reader) let schema = index
.main
.schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let searchable_attributes: Option<Vec<String>> = let searchable_attributes: Option<Vec<String>> =
schema.map(|s| s.indexed_name().iter().map(|i| (*i).to_string()).collect()); schema.map(|s| s.indexed_name().iter().map(|i| (*i).to_string()).collect());
@ -296,7 +372,9 @@ pub async fn update_searchable(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>, body: web::Json<Option<Vec<String>>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = Settings { let settings = Settings {
@ -304,13 +382,18 @@ pub async fn update_searchable(
..Settings::default() ..Settings::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = settings.into_update() let settings = settings
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -321,7 +404,9 @@ pub async fn delete_searchable(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -329,11 +414,15 @@ pub async fn delete_searchable(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -344,12 +433,18 @@ pub async fn get_displayed(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let schema = index.main.schema(&reader) let schema = index
.main
.schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let displayed_attributes: Option<HashSet<String>> = schema.map(|s| { let displayed_attributes: Option<HashSet<String>> = schema.map(|s| {
@ -368,7 +463,9 @@ pub async fn update_displayed(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<HashSet<String>>>, body: web::Json<Option<HashSet<String>>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = Settings { let settings = Settings {
@ -376,13 +473,18 @@ pub async fn update_displayed(
..Settings::default() ..Settings::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = settings.into_update() let settings = settings
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -393,7 +495,9 @@ pub async fn delete_displayed(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -401,12 +505,16 @@ pub async fn delete_displayed(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.map_err(|err| ResponseError::Internal(err.to_string()))?; .db
let update_id = index.settings_update(&mut writer, settings) .update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() let update_id = index
.map_err(|err| ResponseError::Internal(err.to_string()))?; .settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?;
writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
@ -416,12 +524,18 @@ pub async fn get_accept_new_fields(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let schema = index.main.schema(&reader) let schema = index
.main
.schema(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let accept_new_fields = schema.map(|s| s.accept_new_fields()); let accept_new_fields = schema.map(|s| s.accept_new_fields());
@ -435,7 +549,9 @@ pub async fn update_accept_new_fields(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<bool>>, body: web::Json<Option<bool>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = Settings { let settings = Settings {
@ -443,13 +559,18 @@ pub async fn update_accept_new_fields(
..Settings::default() ..Settings::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let settings = settings.into_update() let settings = settings
.into_update()
.map_err(|e| ResponseError::BadRequest(e.to_string()))?; .map_err(|e| ResponseError::BadRequest(e.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))

View File

@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use actix_web as aweb; use actix_web as aweb;
use actix_web::{web, get}; use actix_web::{get, web};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use log::error; use log::error;
use pretty_bytes::converter::convert; use pretty_bytes::converter::convert;
@ -9,9 +9,9 @@ use serde::Serialize;
use sysinfo::{NetworkExt, ProcessExt, ProcessorExt, System, SystemExt}; use sysinfo::{NetworkExt, ProcessExt, ProcessorExt, System, SystemExt};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::Data;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data;
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -26,20 +26,30 @@ pub async fn index_stats(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<web::Json<IndexStatsResponse>> { ) -> aweb::Result<web::Json<IndexStatsResponse>> {
let index = data.db.open_index(path.index_uid.clone()) let index = data
.db
.open_index(path.index_uid.clone())
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let number_of_documents = index.main.number_of_documents(&reader) let number_of_documents = index
.main
.number_of_documents(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let fields_frequency = index.main.fields_frequency(&reader) let fields_frequency = index
.main
.fields_frequency(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.unwrap_or_default(); .unwrap_or_default();
let update_reader = data.db.update_read_txn() let update_reader = data
.db
.update_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let is_indexing = data let is_indexing = data
@ -63,15 +73,16 @@ pub struct StatsResult {
} }
#[get("/stats")] #[get("/stats")]
pub async fn get_stats( pub async fn get_stats(data: web::Data<Data>) -> aweb::Result<web::Json<StatsResult>> {
data: web::Data<Data>,
) -> aweb::Result<web::Json<StatsResult>> {
let mut index_list = HashMap::new(); let mut index_list = HashMap::new();
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_reader = data.db.update_read_txn() let update_reader = data
.db
.update_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let indexes_set = data.db.indexes_uids(); let indexes_set = data.db.indexes_uids();
@ -79,10 +90,14 @@ pub async fn get_stats(
let index = data.db.open_index(&index_uid); let index = data.db.open_index(&index_uid);
match index { match index {
Some(index) => { Some(index) => {
let number_of_documents = index.main.number_of_documents(&reader) let number_of_documents = index
.main
.number_of_documents(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let fields_frequency = index.main.fields_frequency(&reader) let fields_frequency = index
.main
.fields_frequency(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.unwrap_or_default(); .unwrap_or_default();
@ -112,7 +127,8 @@ pub async fn get_stats(
.filter(|metadata| metadata.is_file()) .filter(|metadata| metadata.is_file())
.fold(0, |acc, m| acc + m.len()); .fold(0, |acc, m| acc + m.len());
let last_update = data.last_update(&reader) let last_update = data
.last_update(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(web::Json(StatsResult { Ok(web::Json(StatsResult {
@ -200,9 +216,7 @@ impl SysInfo {
} }
#[get("/sys-info")] #[get("/sys-info")]
pub async fn get_sys_info( pub async fn get_sys_info(data: web::Data<Data>) -> web::Json<SysInfo> {
data: web::Data<Data>,
) -> web::Json<SysInfo> {
let mut sys = System::new(); let mut sys = System::new();
let mut info = SysInfo::new(); let mut info = SysInfo::new();
@ -216,11 +230,13 @@ pub async fn get_sys_info(
info.global.used_memory = sys.get_used_memory(); info.global.used_memory = sys.get_used_memory();
info.global.total_swap = sys.get_total_swap(); info.global.total_swap = sys.get_total_swap();
info.global.used_swap = sys.get_used_swap(); info.global.used_swap = sys.get_used_swap();
info.global.input_data = sys.get_networks() info.global.input_data = sys
.get_networks()
.into_iter() .into_iter()
.map(|(_, n)| n.get_received()) .map(|(_, n)| n.get_received())
.sum::<u64>(); .sum::<u64>();
info.global.output_data = sys.get_networks() info.global.output_data = sys
.get_networks()
.into_iter() .into_iter()
.map(|(_, n)| n.get_transmitted()) .map(|(_, n)| n.get_transmitted())
.sum::<u64>(); .sum::<u64>();
@ -294,11 +310,8 @@ impl SysInfoPretty {
} }
} }
#[get("/sys-info/pretty")] #[get("/sys-info/pretty")]
pub async fn get_sys_info_pretty( pub async fn get_sys_info_pretty(data: web::Data<Data>) -> web::Json<SysInfoPretty> {
data: web::Data<Data>,
) -> web::Json<SysInfoPretty> {
let mut sys = System::new(); let mut sys = System::new();
let mut info = SysInfoPretty::new(); let mut info = SysInfoPretty::new();
@ -316,8 +329,18 @@ pub async fn get_sys_info_pretty(
info.global.used_memory = convert(sys.get_used_memory() as f64 * 1024.0); info.global.used_memory = convert(sys.get_used_memory() as f64 * 1024.0);
info.global.total_swap = convert(sys.get_total_swap() as f64 * 1024.0); info.global.total_swap = convert(sys.get_total_swap() as f64 * 1024.0);
info.global.used_swap = convert(sys.get_used_swap() as f64 * 1024.0); info.global.used_swap = convert(sys.get_used_swap() as f64 * 1024.0);
info.global.input_data = convert(sys.get_networks().into_iter().map(|(_, n)| n.get_received()).sum::<u64>() as f64); info.global.input_data = convert(
info.global.output_data = convert(sys.get_networks().into_iter().map(|(_, n)| n.get_transmitted()).sum::<u64>() as f64); sys.get_networks()
.into_iter()
.map(|(_, n)| n.get_received())
.sum::<u64>() as f64,
);
info.global.output_data = convert(
sys.get_networks()
.into_iter()
.map(|(_, n)| n.get_transmitted())
.sum::<u64>() as f64,
);
if let Some(process) = sys.get_process(data.server_pid) { if let Some(process) = sys.get_process(data.server_pid) {
info.process.memory = convert(process.memory() as f64 * 1024.0); info.process.memory = convert(process.memory() as f64 * 1024.0);

View File

@ -1,25 +1,31 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use actix_web::{web, get, post, delete, HttpResponse};
use actix_web as aweb; use actix_web as aweb;
use actix_web::{delete, get, post, web, HttpResponse};
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use crate::error::{ResponseError}; use crate::error::ResponseError;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
use crate::routes::{IndexUpdateResponse, IndexParam};
#[get("/indexes/{index_uid}/settings/stop-words")] #[get("/indexes/{index_uid}/settings/stop-words")]
pub async fn get( pub async fn get(data: web::Data<Data>, path: web::Path<IndexParam>) -> aweb::Result<HttpResponse> {
data: web::Data<Data>, let index = data
path: web::Path<IndexParam>, .db
) -> aweb::Result<HttpResponse> { .open_index(&path.index_uid)
let index = data.db.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let stop_words_fst = index.main.stop_words_fst(&reader) let stop_words_fst = index
.main
.stop_words_fst(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let stop_words = stop_words_fst.unwrap_or_default().stream().into_strs() let stop_words = stop_words_fst
.unwrap_or_default()
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Ok().json(stop_words)) Ok(HttpResponse::Ok().json(stop_words))
@ -31,7 +37,9 @@ pub async fn update(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<BTreeSet<String>>, body: web::Json<BTreeSet<String>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -39,11 +47,15 @@ pub async fn update(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -54,7 +66,9 @@ pub async fn delete(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -62,11 +76,15 @@ pub async fn delete(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))

View File

@ -1,29 +1,34 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use actix_web as aweb;
use actix_web::{delete, get, post, web, HttpResponse};
use indexmap::IndexMap; use indexmap::IndexMap;
use meilisearch_core::settings::{SettingsUpdate, UpdateState}; use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use actix_web::{web, get, post, delete, HttpResponse};
use actix_web as aweb;
use crate::error::{ResponseError}; use crate::error::ResponseError;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
use crate::routes::{IndexUpdateResponse, IndexParam};
#[get("/indexes/{index_uid}/settings/synonyms")] #[get("/indexes/{index_uid}/settings/synonyms")]
pub async fn get( pub async fn get(data: web::Data<Data>, path: web::Path<IndexParam>) -> aweb::Result<HttpResponse> {
data: web::Data<Data>, let index = data
path: web::Path<IndexParam>, .db
) -> aweb::Result<HttpResponse> { .open_index(&path.index_uid)
let index = data.db.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let reader = data.db.main_read_txn() let reader = data
.db
.main_read_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let synonyms_fst = index.main.synonyms_fst(&reader) let synonyms_fst = index
.main
.synonyms_fst(&reader)
.map_err(|err| ResponseError::Internal(err.to_string()))? .map_err(|err| ResponseError::Internal(err.to_string()))?
.unwrap_or_default(); .unwrap_or_default();
let synonyms_list = synonyms_fst.stream().into_strs() let synonyms_list = synonyms_fst
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let mut synonyms = IndexMap::new(); let mut synonyms = IndexMap::new();
@ -31,11 +36,14 @@ pub async fn get(
let index_synonyms = &index.synonyms; let index_synonyms = &index.synonyms;
for synonym in synonyms_list { for synonym in synonyms_list {
let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes()) let alternative_list = index_synonyms
.synonyms(&reader, synonym.as_bytes())
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
if let Some(list) = alternative_list { if let Some(list) = alternative_list {
let list = list.stream().into_strs() let list = list
.stream()
.into_strs()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
synonyms.insert(synonym, list); synonyms.insert(synonym, list);
} }
@ -50,7 +58,9 @@ pub async fn update(
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<BTreeMap<String, Vec<String>>>, body: web::Json<BTreeMap<String, Vec<String>>>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -58,11 +68,15 @@ pub async fn update(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
@ -73,7 +87,9 @@ pub async fn delete(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> aweb::Result<HttpResponse> { ) -> aweb::Result<HttpResponse> {
let index = data.db.open_index(&path.index_uid) let index = data
.db
.open_index(&path.index_uid)
.ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?; .ok_or(ResponseError::IndexNotFound(path.index_uid.clone()))?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
@ -81,12 +97,16 @@ pub async fn delete(
..SettingsUpdate::default() ..SettingsUpdate::default()
}; };
let mut writer = data.db.update_write_txn() let mut writer = data
.db
.update_write_txn()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
let update_id = index.settings_update(&mut writer, settings) let update_id = index
.settings_update(&mut writer, settings)
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
writer.commit() writer
.commit()
.map_err(|err| ResponseError::Internal(err.to_string()))?; .map_err(|err| ResponseError::Internal(err.to_string()))?;
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))

View File

@ -660,7 +660,7 @@ fn check_add_documents_without_primary_key() {
} }
#[test] #[test]
fn check_first_update_should_bring_up_processed_status_after_first_docs_addition(){ fn check_first_update_should_bring_up_processed_status_after_first_docs_addition() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
let body = json!({ let body = json!({

View File

@ -289,10 +289,9 @@ fn index_new_fields_false_then_true() {
assert_json_eq!(response, expected); assert_json_eq!(response, expected);
} }
// Fix issue https://github.com/meilisearch/MeiliSearch/issues/518 // Fix issue https://github.com/meilisearch/MeiliSearch/issues/518
#[test] #[test]
fn accept_new_fields_does_not_take_into_account_the_primary_key () { fn accept_new_fields_does_not_take_into_account_the_primary_key() {
let mut server = common::Server::with_uid("movies"); let mut server = common::Server::with_uid("movies");
// 1 - Create an index with no primary-key // 1 - Create an index with no primary-key

View File

@ -148,10 +148,7 @@ fn write_custom_ranking_and_index_documents() {
// 1 - Add ranking rules with one custom ranking on a string // 1 - Add ranking rules with one custom ranking on a string
let body = json!([ let body = json!(["asc(title)", "typo"]);
"asc(title)",
"typo"
]);
server.update_ranking_rules(body); server.update_ranking_rules(body);
@ -184,5 +181,4 @@ fn write_custom_ranking_and_index_documents() {
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
assert_json_eq!(response, expected, ordered: false); assert_json_eq!(response, expected, ordered: false);
} }