improve dump status

This commit is contained in:
many 2020-10-12 10:57:19 +02:00
parent 0a9c9670e7
commit e049aead16
No known key found for this signature in database
GPG key ID: 2CEF23B75189EACA
4 changed files with 79 additions and 33 deletions

View file

@ -13,10 +13,11 @@ use meilisearch_core::settings::Settings;
use meilisearch_core::update::{apply_settings_update, apply_documents_addition};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tempfile::TempDir;
use crate::Data;
use crate::error::Error;
use crate::error::{Error, ResponseError};
use crate::helpers::compression;
use crate::routes::index;
use crate::routes::index::IndexResponse;
@ -112,7 +113,7 @@ fn import_index_v1(
// extract `settings.json` file and import content
let settings = settings_from_path(&index_path)?;
let settings = settings.to_update().map_err(|_e| Error::dump_failed())?;
let settings = settings.to_update().map_err(|e| Error::dump_failed(format!("importing settings for index {}; {}", index_uid, e)))?;
apply_settings_update(write_txn, &index, settings)?;
// create iterator over documents in `documents.jsonl` to make batch importation
@ -199,17 +200,17 @@ pub fn import_dump(
#[serde(rename_all = "snake_case")]
pub enum DumpStatus {
Done,
Processing,
DumpProcessFailed,
InProgress,
Failed,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DumpInfo {
pub uid: String,
pub status: DumpStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub error: Option<serde_json::Value>,
}
impl DumpInfo {
@ -217,15 +218,15 @@ impl DumpInfo {
Self { uid, status, error: None }
}
pub fn with_error(mut self, error: String) -> Self {
self.status = DumpStatus::DumpProcessFailed;
self.error = Some(error);
pub fn with_error(mut self, error: ResponseError) -> Self {
self.status = DumpStatus::Failed;
self.error = Some(json!(error));
self
}
pub fn dump_already_in_progress(&self) -> bool {
self.status == DumpStatus::Processing
self.status == DumpStatus::InProgress
}
pub fn get_current() -> Option<Self> {
@ -299,10 +300,10 @@ fn dump_index_documents(data: &web::Data<Data>, reader: &MainReader, folder_path
/// Write error with a context.
fn fail_dump_process<E: std::error::Error>(dump_info: DumpInfo, context: &str, error: E) {
let error = format!("Something went wrong during dump process: {}; {}", context, error);
let error_message = format!("{}; {}", context, error);
error!("{}", &error);
dump_info.with_error(error).set_current();
error!("Something went wrong during dump process: {}", &error_message);
dump_info.with_error(Error::dump_failed(error_message).into()).set_current();
}
/// Main function of dump.
@ -395,7 +396,7 @@ fn dump_process(data: web::Data<Data>, dumps_folder: PathBuf, dump_info: DumpInf
}
pub fn init_dump_process(data: &web::Data<Data>, dumps_folder: &Path) -> Result<DumpInfo, Error> {
create_dir_all(dumps_folder).or(Err(Error::dump_failed()))?;
create_dir_all(dumps_folder).map_err(|e| Error::dump_failed(format!("creating temporary directory {}", e)))?;
// check if a dump is already in progress
if let Some(resume) = DumpInfo::get_current() {
@ -407,7 +408,7 @@ pub fn init_dump_process(data: &web::Data<Data>, dumps_folder: &Path) -> Result<
// generate a new dump info
let info = DumpInfo::new(
generate_uid(),
DumpStatus::Processing
DumpStatus::InProgress
);
info.set_current();

View file

@ -5,7 +5,7 @@ use actix_http::ResponseBuilder;
use actix_web as aweb;
use actix_web::error::{JsonPayloadError, QueryPayloadError};
use actix_web::http::StatusCode;
use serde_json::json;
use serde::ser::{Serialize, Serializer, SerializeStruct};
use meilisearch_error::{ErrorCode, Code};
@ -54,7 +54,7 @@ pub enum Error {
PayloadTooLarge,
UnsupportedMediaType,
DumpAlreadyInProgress,
DumpProcessFailed,
DumpProcessFailed(String),
}
impl error::Error for Error {}
@ -81,7 +81,7 @@ impl ErrorCode for Error {
PayloadTooLarge => Code::PayloadTooLarge,
UnsupportedMediaType => Code::UnsupportedMediaType,
DumpAlreadyInProgress => Code::DumpAlreadyInProgress,
DumpProcessFailed => Code::DumpProcessFailed,
DumpProcessFailed(_) => Code::DumpProcessFailed,
}
}
}
@ -189,8 +189,8 @@ impl Error {
Error::DumpAlreadyInProgress
}
pub fn dump_failed() -> Error {
Error::DumpProcessFailed
pub fn dump_failed(message: String) -> Error {
Error::DumpProcessFailed(message)
}
}
@ -215,19 +215,31 @@ impl fmt::Display for Error {
Self::PayloadTooLarge => f.write_str("Payload too large"),
Self::UnsupportedMediaType => f.write_str("Unsupported media type"),
Self::DumpAlreadyInProgress => f.write_str("Another dump is already in progress"),
Self::DumpProcessFailed => f.write_str("Dump process failed"),
Self::DumpProcessFailed(message) => write!(f, "Dump process failed: {}", message),
}
}
}
impl Serialize for ResponseError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let struct_name = "ResponseError";
let field_count = 4;
let mut state = serializer.serialize_struct(struct_name, field_count)?;
state.serialize_field("message", &self.to_string())?;
state.serialize_field("errorCode", &self.error_name())?;
state.serialize_field("errorType", &self.error_type())?;
state.serialize_field("errorLink", &self.error_url())?;
state.end()
}
}
impl aweb::error::ResponseError for ResponseError {
fn error_response(&self) -> aweb::HttpResponse {
ResponseBuilder::new(self.status_code()).json(json!({
"message": self.to_string(),
"errorCode": self.error_name(),
"errorType": self.error_type(),
"errorLink": self.error_url(),
}))
ResponseBuilder::new(self.status_code()).json(&self)
}
fn status_code(&self) -> StatusCode {