simplify error handling

This commit is contained in:
qdequele 2020-01-16 16:58:57 +01:00
parent f83e874e35
commit b71bbcffaa
No known key found for this signature in database
GPG Key ID: B3F0A000EBF11745
13 changed files with 158 additions and 280 deletions

1
Cargo.lock generated
View File

@ -1016,6 +1016,7 @@ dependencies = [
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fst 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"heed 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "heed 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"http-service 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-service 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -14,10 +14,12 @@ name = "meilisearch"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
async-std = { version = "1.0.1", features = ["unstable", "attributes"] }
bincode = "1.2.0" bincode = "1.2.0"
chrono = { version = "0.4.9", features = ["serde"] } chrono = { version = "0.4.9", features = ["serde"] }
crossbeam-channel = "0.4.0" crossbeam-channel = "0.4.0"
env_logger = "0.7.1" env_logger = "0.7.1"
fst = { version = "0.3.5", default-features = false }
heed = "0.6.1" heed = "0.6.1"
http = "0.1.19" http = "0.1.19"
indexmap = { version = "1.3.0", features = ["serde-1"] } indexmap = { version = "1.3.0", features = ["serde-1"] }
@ -34,11 +36,10 @@ serde_qs = "0.5.1"
siphasher = "0.3.1" siphasher = "0.3.1"
structopt = "0.3.3" structopt = "0.3.3"
sysinfo = "0.9.5" sysinfo = "0.9.5"
tide = "0.5.1"
ureq = { version = "0.11.2", features = ["tls"], default-features = false } ureq = { version = "0.11.2", features = ["tls"], default-features = false }
walkdir = "2.2.9" walkdir = "2.2.9"
whoami = "0.6" whoami = "0.6"
tide = "0.5.1"
async-std = { version = "1.0.1", features = ["unstable", "attributes"] }
[dev-dependencies] [dev-dependencies]

View File

@ -6,6 +6,8 @@ use serde::{Deserialize, Serialize};
use tide::IntoResponse; use tide::IntoResponse;
use tide::Response; use tide::Response;
use crate::helpers::meilisearch::Error as SearchError;
pub type SResult<T> = Result<T, ResponseError>; pub type SResult<T> = Result<T, ResponseError>;
pub enum ResponseError { pub enum ResponseError {
@ -122,3 +124,42 @@ fn error(message: String, status: StatusCode) -> Response {
let message = ErrorMessage { message }; let message = ErrorMessage { message };
tide::Response::new(status.as_u16()).body_json(&message).unwrap() tide::Response::new(status.as_u16()).body_json(&message).unwrap()
} }
impl From<meilisearch_core::Error> for ResponseError {
fn from(err: meilisearch_core::Error) -> ResponseError {
ResponseError::internal(err)
}
}
impl From<heed::Error> for ResponseError {
fn from(err: heed::Error) -> ResponseError {
ResponseError::internal(err)
}
}
impl From<fst::Error> for ResponseError {
fn from(err: fst::Error) -> ResponseError {
ResponseError::internal(err)
}
}
impl From<SearchError> for ResponseError {
fn from(err: SearchError) -> ResponseError {
ResponseError::internal(err)
}
}
pub trait IntoInternalError<T> {
fn into_internal_error(self) -> SResult<T>;
}
/// Must be used only
impl <T> IntoInternalError<T> for Option<T> {
fn into_internal_error(self) -> SResult<T> {
match self {
Some(value) => Ok(value),
None => Err(ResponseError::internal("Heed "))
}
}
}

View File

@ -30,14 +30,13 @@ impl RequestExt for Request<Data> {
let request_index: Option<String> = None; //self.param::<String>("index").ok(); let request_index: Option<String> = None; //self.param::<String>("index").ok();
let db = &self.state().db; let db = &self.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let token_key = format!("{}{}", TOKEN_PREFIX_KEY, user_api_key); let token_key = format!("{}{}", TOKEN_PREFIX_KEY, user_api_key);
let token_config = db let token_config = db
.common_store() .common_store()
.get::<_, Str, SerdeBincode<Token>>(&reader, &token_key) .get::<_, Str, SerdeBincode<Token>>(&reader, &token_key)?
.map_err(ResponseError::internal)?
.ok_or(ResponseError::invalid_token(format!( .ok_or(ResponseError::invalid_token(format!(
"Api key does not exist: {}", "Api key does not exist: {}",
user_api_key user_api_key

View File

@ -21,11 +21,10 @@ pub async fn get_document(ctx: Request<Data>) -> SResult<Response> {
let document_id = meilisearch_core::serde::compute_document_id(identifier.clone()); let document_id = meilisearch_core::serde::compute_document_id(identifier.clone());
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let response = index let response = index
.document::<IndexMap<String, Value>>(&reader, None, document_id) .document::<IndexMap<String, Value>>(&reader, None, document_id)?
.map_err(ResponseError::internal)?
.ok_or(ResponseError::document_not_found(&identifier))?; .ok_or(ResponseError::document_not_found(&identifier))?;
if response.is_empty() { if response.is_empty() {
@ -47,17 +46,13 @@ pub async fn delete_document(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let identifier = ctx.identifier()?; let identifier = ctx.identifier()?;
let document_id = meilisearch_core::serde::compute_document_id(identifier.clone()); let document_id = meilisearch_core::serde::compute_document_id(identifier.clone());
let db = &ctx.state().db; let db = &ctx.state().db;
let mut update_writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut update_writer = db.update_write_txn()?;
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 let update_id = documents_deletion.finalize(&mut update_writer)?;
.finalize(&mut update_writer)
.map_err(ResponseError::internal)?;
update_writer.commit().map_err(ResponseError::internal)?; update_writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())
@ -81,13 +76,11 @@ pub async fn get_all_documents(ctx: Request<Data>) -> SResult<Response> {
let limit = query.limit.unwrap_or(20); let limit = query.limit.unwrap_or(20);
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let documents_ids: Result<BTreeSet<_>, _> = let documents_ids: Result<BTreeSet<_>, _> = index.documents_fields_counts
match index.documents_fields_counts.documents_ids(&reader) { .documents_ids(&reader)?
Ok(documents_ids) => documents_ids.skip(offset).take(limit).collect(), .skip(offset).take(limit).collect();
Err(e) => return Err(ResponseError::internal(e)),
};
let documents_ids = match documents_ids { let documents_ids = match documents_ids {
Ok(documents_ids) => documents_ids, Ok(documents_ids) => documents_ids,
@ -139,13 +132,9 @@ async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) ->
let query: UpdateDocumentsQuery = ctx.query().unwrap_or_default(); let query: UpdateDocumentsQuery = ctx.query().unwrap_or_default();
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let mut update_writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut update_writer = db.update_write_txn()?;
let current_schema = index.main.schema(&reader)?;
let current_schema = index
.main
.schema(&reader)
.map_err(ResponseError::internal)?;
if current_schema.is_none() { if current_schema.is_none() {
let id = match query.identifier { let id = match query.identifier {
Some(id) => id, Some(id) => id,
@ -160,9 +149,7 @@ async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) ->
attribute_identifier: Some(id), attribute_identifier: Some(id),
..Settings::default() ..Settings::default()
}; };
index index.settings_update(&mut update_writer, settings.into())?;
.settings_update(&mut update_writer, settings.into())
.map_err(ResponseError::internal)?;
} }
let mut document_addition = if is_partial { let mut document_addition = if is_partial {
@ -175,11 +162,8 @@ async fn update_multiple_documents(mut ctx: Request<Data>, is_partial: bool) ->
document_addition.update_document(document); document_addition.update_document(document);
} }
let update_id = document_addition let update_id = document_addition.finalize(&mut update_writer)?;
.finalize(&mut update_writer) update_writer.commit()?;
.map_err(ResponseError::internal)?;
update_writer.commit().map_err(ResponseError::internal)?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())
@ -200,7 +184,7 @@ pub async fn delete_multiple_documents(mut ctx: Request<Data>) -> SResult<Respon
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let mut documents_deletion = index.documents_deletion(); let mut documents_deletion = index.documents_deletion();
@ -211,11 +195,9 @@ pub async fn delete_multiple_documents(mut ctx: Request<Data>) -> SResult<Respon
} }
} }
let update_id = documents_deletion let update_id = documents_deletion.finalize(&mut writer)?;
.finalize(&mut writer)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())
@ -227,12 +209,10 @@ pub async fn clear_all_documents(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let update_id = index let update_id = index.clear_all(&mut writer)?;
.clear_all(&mut writer) writer.commit()?;
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())

View File

@ -11,7 +11,7 @@ const UNHEALTHY_KEY: &str = "_is_unhealthy";
pub async fn get_health(ctx: Request<Data>) -> SResult<Response> { pub async fn get_health(ctx: Request<Data>) -> SResult<Response> {
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let common_store = ctx.state().db.common_store(); let common_store = ctx.state().db.common_store();
@ -24,38 +24,22 @@ pub async fn get_health(ctx: Request<Data>) -> SResult<Response> {
pub async fn set_healthy(ctx: Request<Data>) -> SResult<Response> { pub async fn set_healthy(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
let common_store = ctx.state().db.common_store(); let common_store = ctx.state().db.common_store();
match common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY) { common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)?;
Ok(_) => (), writer.commit()?;
Err(e) => return Err(ResponseError::internal(e)),
}
if let Err(e) = writer.commit() {
return Err(ResponseError::internal(e));
}
Ok(tide::Response::new(200)) Ok(tide::Response::new(200))
} }
pub async fn set_unhealthy(ctx: Request<Data>) -> SResult<Response> { pub async fn set_unhealthy(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
let common_store = ctx.state().db.common_store(); let common_store = ctx.state().db.common_store();
common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())?;
if let Err(e) = common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &()) { writer.commit()?;
return Err(ResponseError::internal(e));
}
if let Err(e) = writer.commit() {
return Err(ResponseError::internal(e));
}
Ok(tide::Response::new(200)) Ok(tide::Response::new(200))
} }

View File

@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use serde_json::json; use serde_json::json;
use tide::{Request, Response}; use tide::{Request, Response};
use crate::error::{ResponseError, SResult}; use crate::error::{ResponseError, SResult, IntoInternalError};
use crate::helpers::tide::RequestExt; use crate::helpers::tide::RequestExt;
use crate::models::token::ACL::*; use crate::models::token::ACL::*;
use crate::Data; use crate::Data;
@ -26,7 +26,7 @@ pub async fn list_indexes(ctx: Request<Data>) -> SResult<Response> {
let indexes_uids = ctx.state().db.indexes_uids(); let indexes_uids = ctx.state().db.indexes_uids();
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let mut response_body = Vec::new(); let mut response_body = Vec::new();
@ -35,21 +35,9 @@ pub async fn list_indexes(ctx: Request<Data>) -> SResult<Response> {
match index { match index {
Some(index) => { Some(index) => {
let name = index let name = index.main.name(&reader)?.into_internal_error()?;
.main let created_at = index.main.created_at(&reader)?.into_internal_error()?;
.name(&reader) let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'name' not found"))?;
let created_at = index
.main
.created_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'created_at' date not found"))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'updated_at' date not found"))?;
let index_response = IndexResponse { let index_response = IndexResponse {
name, name,
@ -84,24 +72,12 @@ pub async fn get_index(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let uid = ctx.url_param("index")?; let uid = ctx.url_param("index")?;
let name = index let name = index.main.name(&reader)?.into_internal_error()?;
.main let created_at = index.main.created_at(&reader)?.into_internal_error()?;
.name(&reader) let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'name' not found"))?;
let created_at = index
.main
.created_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'created_at' date not found"))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'updated_at' date not found"))?;
let response_body = IndexResponse { let response_body = IndexResponse {
name, name,
@ -158,24 +134,13 @@ pub async fn create_index(mut ctx: Request<Data>) -> SResult<Response> {
Err(e) => return Err(ResponseError::create_index(e)), Err(e) => return Err(ResponseError::create_index(e)),
}; };
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
let name = body.name.unwrap_or(uid.clone()); let name = body.name.unwrap_or(uid.clone());
created_index.main.put_name(&mut writer, &name)?;
let created_at = created_index.main.created_at(&writer)?.into_internal_error()?;
let updated_at = created_index.main.updated_at(&writer)?.into_internal_error()?;
created_index.main writer.commit()?;
.put_name(&mut writer, &name)
.map_err(ResponseError::internal)?;
let created_at = created_index.main
.created_at(&writer)
.map_err(ResponseError::internal)?
.unwrap_or(Utc::now());
let updated_at = created_index.main
.updated_at(&writer)
.map_err(ResponseError::internal)?
.unwrap_or(Utc::now());
writer.commit().map_err(ResponseError::internal)?;
let response_body = IndexCreateResponse { let response_body = IndexCreateResponse {
name: name, name: name,
@ -214,31 +179,17 @@ pub async fn update_index(mut ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
index index.main.put_name(&mut writer, &body.name)?;
.main
.put_name(&mut writer, &body.name)
.map_err(ResponseError::internal)?;
index index.main.put_updated_at(&mut writer)?;
.main
.put_updated_at(&mut writer)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let created_at = index let created_at = index.main.created_at(&reader)?.into_internal_error()?;
.main let updated_at = index.main.updated_at(&reader)?.into_internal_error()?;
.created_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'created_at' date not found"))?;
let updated_at = index
.main
.updated_at(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'updated_at' date not found"))?;
let response_body = UpdateIndexResponse { let response_body = UpdateIndexResponse {
name: body.name, name: body.name,
@ -254,16 +205,14 @@ pub async fn get_update_status(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(IndexesRead)?; ctx.is_allowed(IndexesRead)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.update_read_txn().map_err(ResponseError::internal)?; let reader = db.update_read_txn()?;
let update_id = ctx let update_id = ctx
.param::<u64>("update_id") .param::<u64>("update_id")
.map_err(|e| ResponseError::bad_parameter("update_id", e))?; .map_err(|e| ResponseError::bad_parameter("update_id", e))?;
let index = ctx.index()?; let index = ctx.index()?;
let status = index let status = index.update_status(&reader, update_id)?;
.update_status(&reader, update_id)
.map_err(ResponseError::internal)?;
let response = match status { let response = match status {
Some(status) => tide::Response::new(200).body_json(&status).unwrap(), Some(status) => tide::Response::new(200).body_json(&status).unwrap(),
@ -275,15 +224,10 @@ pub async fn get_update_status(ctx: Request<Data>) -> SResult<Response> {
pub async fn get_all_updates_status(ctx: Request<Data>) -> SResult<Response> { pub async fn get_all_updates_status(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(IndexesRead)?; ctx.is_allowed(IndexesRead)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.update_read_txn().map_err(ResponseError::internal)?; let reader = db.update_read_txn()?;
let index = ctx.index()?; let index = ctx.index()?;
let response = index let response = index.all_updates_status(&reader)?;
.all_updates_status(&reader)
.map_err(ResponseError::internal)?;
Ok(tide::Response::new(200).body_json(&response).unwrap()) Ok(tide::Response::new(200).body_json(&response).unwrap())
} }
@ -291,7 +235,7 @@ pub async fn delete_index(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(IndexesWrite)?; ctx.is_allowed(IndexesWrite)?;
let _ = ctx.index()?; let _ = ctx.index()?;
let index_uid = ctx.url_param("index")?; let index_uid = ctx.url_param("index")?;
ctx.state().db.delete_index(&index_uid).map_err(ResponseError::internal)?; ctx.state().db.delete_index(&index_uid)?;
Ok(tide::Response::new(204)) Ok(tide::Response::new(204))
} }

View File

@ -24,18 +24,17 @@ pub async fn list(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let common_store = db.common_store(); let common_store = db.common_store();
let mut response: Vec<Token> = Vec::new(); let mut response: Vec<Token> = Vec::new();
let iter = common_store let iter = common_store
.prefix_iter::<_, Str, SerdeBincode<Token>>(&reader, TOKEN_PREFIX_KEY) .prefix_iter::<_, Str, SerdeBincode<Token>>(&reader, TOKEN_PREFIX_KEY)?;
.map_err(ResponseError::internal)?;
for result in iter { for result in iter {
let (_, token) = result.map_err(ResponseError::internal)?; let (_, token) = result?;
response.push(token); response.push(token);
} }
@ -47,14 +46,13 @@ pub async fn get(ctx: Request<Data>) -> SResult<Response> {
let request_key = ctx.url_param("key")?; let request_key = ctx.url_param("key")?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key); let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key);
let token_config = db let token_config = db
.common_store() .common_store()
.get::<_, Str, SerdeBincode<Token>>(&reader, &token_key) .get::<_, Str, SerdeBincode<Token>>(&reader, &token_key)?
.map_err(ResponseError::internal)?
.ok_or(ResponseError::not_found(format!( .ok_or(ResponseError::not_found(format!(
"token key: {}", "token key: {}",
token_key token_key
@ -93,14 +91,11 @@ pub async fn create(mut ctx: Request<Data>) -> SResult<Response> {
}; };
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
db.common_store() db.common_store().put::<_, Str, SerdeBincode<Token>>(&mut writer, &token_key, &token_definition)?;
.put::<_, Str, SerdeBincode<Token>>(&mut writer, &token_key, &token_definition)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?;
writer.commit()?;
Ok(tide::Response::new(201).body_json(&token_definition).unwrap()) Ok(tide::Response::new(201).body_json(&token_definition).unwrap())
} }
@ -121,15 +116,14 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
let data: UpdatedRequest = ctx.body_json().await.map_err(ResponseError::bad_request)?; let data: UpdatedRequest = ctx.body_json().await.map_err(ResponseError::bad_request)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
let common_store = db.common_store(); let common_store = db.common_store();
let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key); let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key);
let mut token_config = common_store let mut token_config = common_store
.get::<_, Str, SerdeBincode<Token>>(&writer, &token_key) .get::<_, Str, SerdeBincode<Token>>(&writer, &token_key)?
.map_err(ResponseError::internal)?
.ok_or(ResponseError::not_found(format!( .ok_or(ResponseError::not_found(format!(
"token key: {}", "token key: {}",
token_key token_key
@ -139,30 +133,22 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
if let Some(description) = data.description { if let Some(description) = data.description {
token_config.description = description; token_config.description = description;
} }
if let Some(acl) = data.acl { if let Some(acl) = data.acl {
token_config.acl = acl; token_config.acl = acl;
} }
if let Some(indexes) = data.indexes { if let Some(indexes) = data.indexes {
token_config.indexes = indexes; token_config.indexes = indexes;
} }
if let Some(expires_at) = data.expires_at { if let Some(expires_at) = data.expires_at {
token_config.expires_at = expires_at; token_config.expires_at = expires_at;
} }
if let Some(revoked) = data.revoked { if let Some(revoked) = data.revoked {
token_config.revoked = revoked; token_config.revoked = revoked;
} }
token_config.updated_at = Utc::now(); token_config.updated_at = Utc::now();
common_store.put::<_, Str, SerdeBincode<Token>>(&mut writer, &token_key, &token_config)?;
common_store writer.commit()?;
.put::<_, Str, SerdeBincode<Token>>(&mut writer, &token_key, &token_config)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?;
Ok(tide::Response::new(200).body_json(&token_config).unwrap()) Ok(tide::Response::new(200).body_json(&token_config).unwrap())
} }
@ -170,19 +156,11 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
pub async fn delete(ctx: Request<Data>) -> SResult<Response> { pub async fn delete(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let request_key = ctx.url_param("key")?; let request_key = ctx.url_param("key")?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.main_write_txn().map_err(ResponseError::internal)?; let mut writer = db.main_write_txn()?;
let common_store = db.common_store(); let common_store = db.common_store();
let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key); let token_key = format!("{}{}", TOKEN_PREFIX_KEY, request_key);
common_store.delete::<_, Str>(&mut writer, &token_key)?;
common_store writer.commit()?;
.delete::<_, Str>(&mut writer, &token_key)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?;
Ok(tide::Response::new(204)) Ok(tide::Response::new(204))
} }

View File

@ -32,12 +32,9 @@ pub async fn search_with_url_query(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let schema = index let schema = index.main.schema(&reader)?
.main
.schema(&reader)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::open_index("No Schema found"))?; .ok_or(ResponseError::open_index("No Schema found"))?;
let query: SearchQuery = ctx.query() let query: SearchQuery = ctx.query()
@ -201,10 +198,8 @@ pub async fn search_multi_index(mut ctx: Request<Data>) -> SResult<Response> {
} }
} }
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let response = search_builder let response = search_builder.search(&reader)?;
.search(&reader)
.map_err(ResponseError::internal)?;
Ok((index_uid, response)) Ok((index_uid, response))
}) })
.collect(); .collect();

View File

@ -29,7 +29,7 @@ pub async fn get(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let settings = match index.main.customs(&reader).unwrap() { let settings = match index.main.customs(&reader).unwrap() {
Some(bytes) => bincode::deserialize(bytes).unwrap(), Some(bytes) => bincode::deserialize(bytes).unwrap(),
@ -64,8 +64,8 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let mut current_settings = match index.main.customs(&reader).unwrap() { let mut current_settings = match index.main.customs(&reader).unwrap() {
Some(bytes) => bincode::deserialize(bytes).unwrap(), Some(bytes) => bincode::deserialize(bytes).unwrap(),
@ -82,11 +82,9 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
let bytes = bincode::serialize(&current_settings).unwrap(); let bytes = bincode::serialize(&current_settings).unwrap();
let update_id = index let update_id = index.customs_update(&mut writer, bytes)?;
.customs_update(&mut writer, bytes)
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())

View File

@ -8,7 +8,7 @@ use sysinfo::{NetworkExt, Pid, ProcessExt, ProcessorExt, System, SystemExt};
use tide::{Request, Response}; use tide::{Request, Response};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::error::{ResponseError, SResult}; use crate::error::{SResult, IntoInternalError};
use crate::helpers::tide::RequestExt; use crate::helpers::tide::RequestExt;
use crate::models::token::ACL::*; use crate::models::token::ACL::*;
use crate::Data; use crate::Data;
@ -25,27 +25,12 @@ pub async fn index_stat(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let index_uid = ctx.url_param("index")?; let index_uid = ctx.url_param("index")?;
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let update_reader = db.update_read_txn().map_err(ResponseError::internal)?; let update_reader = db.update_read_txn()?;
let number_of_documents = index.main.number_of_documents(&reader)?;
let number_of_documents = index let fields_frequency = index.main.fields_frequency(&reader)?.unwrap_or_default();
.main let is_indexing = ctx.state().is_indexing(&update_reader, &index_uid)?.into_internal_error()?;
.number_of_documents(&reader)
.map_err(ResponseError::internal)?;
let fields_frequency = index
.main
.fields_frequency(&reader)
.map_err(ResponseError::internal)?
.unwrap_or_default();
let is_indexing = ctx
.state()
.is_indexing(&update_reader, &index_uid)
.map_err(ResponseError::internal)?
.ok_or(ResponseError::internal("'is_indexing' date not found"))?;
let response = IndexStatsResponse { let response = IndexStatsResponse {
number_of_documents, number_of_documents,
@ -69,8 +54,8 @@ pub async fn get_stats(ctx: Request<Data>) -> SResult<Response> {
let mut index_list = HashMap::new(); let mut index_list = HashMap::new();
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let update_reader = db.update_read_txn().map_err(ResponseError::internal)?; let update_reader = db.update_read_txn()?;
let indexes_set = ctx.state().db.indexes_uids(); let indexes_set = ctx.state().db.indexes_uids();
for index_uid in indexes_set { for index_uid in indexes_set {
@ -78,22 +63,14 @@ pub async fn get_stats(ctx: Request<Data>) -> SResult<Response> {
match index { match index {
Some(index) => { Some(index) => {
let number_of_documents = index let number_of_documents = index.main.number_of_documents(&reader)?;
.main
.number_of_documents(&reader)
.map_err(ResponseError::internal)?;
let fields_frequency = index let fields_frequency = index.main.fields_frequency(&reader)?.unwrap_or_default();
.main
.fields_frequency(&reader)
.map_err(ResponseError::internal)?
.unwrap_or_default();
let is_indexing = ctx let is_indexing = ctx
.state() .state()
.is_indexing(&update_reader, &index_uid) .is_indexing(&update_reader, &index_uid)?
.map_err(ResponseError::internal)? .into_internal_error()?;
.ok_or(ResponseError::internal("'is_indexing' date not found"))?;
let response = IndexStatsResponse { let response = IndexStatsResponse {
number_of_documents, number_of_documents,
@ -116,10 +93,7 @@ pub async fn get_stats(ctx: Request<Data>) -> SResult<Response> {
.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 = ctx let last_update = ctx.state().last_update(&reader)?;
.state()
.last_update(&reader)
.map_err(ResponseError::internal)?;
let response = StatsResult { let response = StatsResult {
database_size, database_size,

View File

@ -12,20 +12,10 @@ use crate::Data;
pub async fn get(ctx: Request<Data>) -> SResult<Response> { pub async fn get(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(SettingsRead)?; ctx.is_allowed(SettingsRead)?;
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let stop_words_fst = index.main.stop_words_fst(&reader)?;
let stop_words_fst = index let stop_words = stop_words_fst.unwrap_or_default().stream().into_strs()?;
.main
.stop_words_fst(&reader)
.map_err(ResponseError::internal)?;
let stop_words = stop_words_fst
.unwrap_or_default()
.stream()
.into_strs()
.map_err(ResponseError::internal)?;
Ok(tide::Response::new(200).body_json(&stop_words).unwrap()) Ok(tide::Response::new(200).body_json(&stop_words).unwrap())
} }
@ -37,17 +27,16 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
let data: BTreeSet<String> = ctx.body_json().await.map_err(ResponseError::bad_request)?; let data: BTreeSet<String> = ctx.body_json().await.map_err(ResponseError::bad_request)?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
stop_words: UpdateState::Update(data), stop_words: UpdateState::Update(data),
.. SettingsUpdate::default() .. SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index.settings_update(&mut writer, settings)?;
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())
@ -58,17 +47,16 @@ pub async fn delete(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
stop_words: UpdateState::Clear, stop_words: UpdateState::Clear,
.. SettingsUpdate::default() .. SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index.settings_update(&mut writer, settings)?;
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())

View File

@ -15,27 +15,24 @@ pub async fn get(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let reader = db.main_read_txn().map_err(ResponseError::internal)?; let reader = db.main_read_txn()?;
let synonyms_fst = index let synonyms_fst = index
.main .main
.synonyms_fst(&reader) .synonyms_fst(&reader)?;
.map_err(ResponseError::internal)?;
let synonyms_fst = synonyms_fst.unwrap_or_default(); let synonyms_fst = synonyms_fst.unwrap_or_default();
let synonyms_list = synonyms_fst.stream().into_strs().map_err(ResponseError::internal)?; let synonyms_list = synonyms_fst.stream().into_strs()?;
let mut response = IndexMap::new(); let mut response = IndexMap::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 let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
.synonyms(&reader, synonym.as_bytes())
.map_err(ResponseError::internal)?;
if let Some(list) = alternative_list { if let Some(list) = alternative_list {
let list = list.stream().into_strs().map_err(ResponseError::internal)?; let list = list.stream().into_strs()?;
response.insert(synonym, list); response.insert(synonym, list);
} }
} }
@ -51,17 +48,16 @@ pub async fn update(mut ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
synonyms: UpdateState::Update(data), synonyms: UpdateState::Update(data),
.. SettingsUpdate::default() .. SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index.settings_update(&mut writer, settings)?;
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())
@ -74,17 +70,16 @@ pub async fn delete(ctx: Request<Data>) -> SResult<Response> {
let index = ctx.index()?; let index = ctx.index()?;
let db = &ctx.state().db; let db = &ctx.state().db;
let mut writer = db.update_write_txn().map_err(ResponseError::internal)?; let mut writer = db.update_write_txn()?;
let settings = SettingsUpdate { let settings = SettingsUpdate {
synonyms: UpdateState::Clear, synonyms: UpdateState::Clear,
.. SettingsUpdate::default() .. SettingsUpdate::default()
}; };
let update_id = index.settings_update(&mut writer, settings) let update_id = index.settings_update(&mut writer, settings)?;
.map_err(ResponseError::internal)?;
writer.commit().map_err(ResponseError::internal)?; writer.commit()?;
let response_body = IndexUpdateResponse { update_id }; let response_body = IndexUpdateResponse { update_id };
Ok(tide::Response::new(202).body_json(&response_body).unwrap()) Ok(tide::Response::new(202).body_json(&response_body).unwrap())