mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-29 08:14:26 +01:00
clippy + fmt
This commit is contained in:
parent
22fbff98d4
commit
6a1f73a304
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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 {
|
||||||
|
@ -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,7 +103,7 @@ 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?;
|
||||||
|
@ -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)))
|
||||||
|
@ -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())
|
||||||
|
@ -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
|
||||||
|
.db
|
||||||
|
.main_write_txn()
|
||||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
.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))
|
||||||
|
@ -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,9 +9,7 @@ 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,
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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,9 +175,13 @@ 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
|
||||||
|
.db
|
||||||
|
.main_read_txn()
|
||||||
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
.map_err(|err| ResponseError::Internal(err.to_string()))?;
|
||||||
|
|
||||||
let ranking_rules = index
|
let ranking_rules = index
|
||||||
@ -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,9 +318,13 @@ 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
|
||||||
|
.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 {
|
||||||
@ -264,10 +332,12 @@ pub async fn delete_distinct(
|
|||||||
..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)))
|
||||||
@ -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,11 +505,15 @@ pub async fn delete_displayed(
|
|||||||
..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)))
|
||||||
@ -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)))
|
||||||
|
@ -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);
|
||||||
|
@ -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)))
|
||||||
|
@ -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)))
|
||||||
|
@ -289,7 +289,6 @@ 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() {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user