enable errors in updates

This commit is contained in:
marin postma 2021-06-21 18:42:47 +02:00
parent 56686dee40
commit 1e4592dd7e
No known key found for this signature in database
GPG Key ID: 6088B7721C3E39F9
7 changed files with 52 additions and 86 deletions

View File

@ -1,4 +1,3 @@
use std::error;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
@ -8,9 +7,7 @@ use actix_web::dev::BaseHttpResponseBuilder;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use meilisearch_error::{Code, ErrorCode}; use meilisearch_error::{Code, ErrorCode};
use milli::UserError; use milli::UserError;
use serde::ser::{Serialize, SerializeStruct, Serializer}; use serde::{Serialize, Deserialize};
use crate::index_controller::error::IndexControllerError;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum AuthenticationError { pub enum AuthenticationError {
@ -29,56 +26,34 @@ impl ErrorCode for AuthenticationError {
} }
} }
#[derive(Debug)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ResponseError { pub struct ResponseError {
inner: Box<dyn ErrorCode>, #[serde(skip)]
} code: StatusCode,
message: String,
impl error::Error for ResponseError {} error_code: String,
error_type: String,
impl ErrorCode for ResponseError { error_link: String,
fn error_code(&self) -> Code {
self.inner.error_code()
}
} }
impl fmt::Display for ResponseError { impl fmt::Display for ResponseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f) self.message.fmt(f)
} }
} }
macro_rules! response_error { impl<T> From<T> for ResponseError
($($other:path), *) => { where T: ErrorCode
$( {
impl From<$other> for ResponseError { fn from(other: T) -> Self {
fn from(error: $other) -> ResponseError { Self {
ResponseError { code: other.http_status(),
inner: Box::new(error), message: other.to_string(),
} error_code: other.error_name(),
} error_type: other.error_type(),
} error_link: other.error_url(),
}
)*
};
}
response_error!(IndexControllerError, AuthenticationError);
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()
} }
} }
@ -89,7 +64,7 @@ impl aweb::error::ResponseError for ResponseError {
} }
fn status_code(&self) -> StatusCode { fn status_code(&self) -> StatusCode {
self.http_status() self.code
} }
} }
@ -110,25 +85,6 @@ impl<E: Error> ErrorCode for PayloadError<E> {
} }
} }
impl<E> From<PayloadError<E>> for ResponseError
where
E: Error + Sync + Send + 'static,
{
fn from(other: PayloadError<E>) -> Self {
ResponseError {
inner: Box::new(other),
}
}
}
pub fn payload_error_handler<E>(err: E) -> ResponseError
where
E: Error + Sync + Send + 'static,
{
let error = PayloadError(err);
error.into()
}
macro_rules! internal_error { macro_rules! internal_error {
($target:ty : $($other:path), *) => { ($target:ty : $($other:path), *) => {
$( $(
@ -168,7 +124,7 @@ impl ErrorCode for MilliError<'_> {
| UserError::InvalidDocumentId { .. } | UserError::InvalidDocumentId { .. }
| UserError::InvalidStoreFile | UserError::InvalidStoreFile
| UserError::NoSpaceLeftOnDevice | UserError::NoSpaceLeftOnDevice
| UserError::DocumentLimitReached => todo!(), | UserError::DocumentLimitReached => Code::Internal,
UserError::InvalidFilter(_) => Code::Filter, UserError::InvalidFilter(_) => Code::Filter,
UserError::InvalidFilterAttribute(_) => Code::Filter, UserError::InvalidFilterAttribute(_) => Code::Filter,
UserError::MissingDocumentId { .. } => Code::MissingDocumentId, UserError::MissingDocumentId { .. } => Code::MissingDocumentId,
@ -181,3 +137,11 @@ impl ErrorCode for MilliError<'_> {
} }
} }
} }
pub fn payload_error_handler<E>(err: E) -> ResponseError
where
E: Error + Sync + Send + 'static,
{
let error = PayloadError(err);
error.into()
}

View File

@ -86,7 +86,7 @@ impl UpdateHandler {
match result { match result {
Ok(result) => Ok(meta.process(result)), Ok(result) => Ok(meta.process(result)),
Err(e) => Err(meta.fail(e.to_string())), Err(e) => Err(meta.fail(e.into())),
} }
} }
} }

View File

@ -1,6 +1,8 @@
use meilisearch_error::Code; use meilisearch_error::Code;
use meilisearch_error::ErrorCode; use meilisearch_error::ErrorCode;
use crate::index::error::IndexError;
use super::dump_actor::error::DumpActorError; use super::dump_actor::error::DumpActorError;
use super::index_actor::error::IndexActorError; use super::index_actor::error::IndexActorError;
use super::update_actor::error::UpdateActorError; use super::update_actor::error::UpdateActorError;
@ -20,6 +22,8 @@ pub enum IndexControllerError {
UpdateActor(#[from] UpdateActorError), UpdateActor(#[from] UpdateActorError),
#[error("error with dump: {0}")] #[error("error with dump: {0}")]
DumpActor(#[from] DumpActorError), DumpActor(#[from] DumpActorError),
#[error("error with index: {0}")]
IndexError(#[from] IndexError),
} }
impl ErrorCode for IndexControllerError { impl ErrorCode for IndexControllerError {
@ -30,6 +34,7 @@ impl ErrorCode for IndexControllerError {
IndexControllerError::IndexActor(e) => e.error_code(), IndexControllerError::IndexActor(e) => e.error_code(),
IndexControllerError::UpdateActor(e) => e.error_code(), IndexControllerError::UpdateActor(e) => e.error_code(),
IndexControllerError::DumpActor(e) => e.error_code(), IndexControllerError::DumpActor(e) => e.error_code(),
IndexControllerError::IndexError(e) => e.error_code(),
} }
} }
} }

View File

@ -30,7 +30,7 @@ use self::error::IndexControllerError;
mod dump_actor; mod dump_actor;
pub mod error; pub mod error;
mod index_actor; pub mod index_actor;
mod snapshot; mod snapshot;
mod update_actor; mod update_actor;
mod updates; mod updates;

View File

@ -332,7 +332,7 @@ impl UpdateStore {
let result = let result =
match handle.block_on(index_handle.update(index_uuid, processing.clone(), file)) { match handle.block_on(index_handle.update(index_uuid, processing.clone(), file)) {
Ok(result) => result, Ok(result) => result,
Err(e) => Err(processing.fail(e.to_string())), Err(e) => Err(processing.fail(e.into())),
}; };
// Once the pending update have been successfully processed // Once the pending update have been successfully processed

View File

@ -3,9 +3,7 @@ use milli::update::{DocumentAdditionResult, IndexDocumentsMethod, UpdateFormat};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use crate::index::{Settings, Unchecked}; use crate::{error::ResponseError, index::{Settings, Unchecked}};
pub type UpdateError = String;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UpdateResult { pub enum UpdateResult {
@ -116,7 +114,7 @@ impl Processing {
} }
} }
pub fn fail(self, error: UpdateError) -> Failed { pub fn fail(self, error: ResponseError) -> Failed {
Failed { Failed {
from: self, from: self,
error, error,
@ -143,12 +141,12 @@ impl Aborted {
} }
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Failed { pub struct Failed {
#[serde(flatten)] #[serde(flatten)]
pub from: Processing, pub from: Processing,
pub error: UpdateError, pub error: ResponseError,
pub failed_at: DateTime<Utc>, pub failed_at: DateTime<Utc>,
} }
@ -162,7 +160,7 @@ impl Failed {
} }
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "status", rename_all = "camelCase")] #[serde(tag = "status", rename_all = "camelCase")]
pub enum UpdateStatus { pub enum UpdateStatus {
Processing(Processing), Processing(Processing),

View File

@ -4,6 +4,7 @@ use actix_web::{get, HttpResponse};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::error::ResponseError;
use crate::index::{Settings, Unchecked}; use crate::index::{Settings, Unchecked};
use crate::index_controller::{UpdateMeta, UpdateResult, UpdateStatus}; use crate::index_controller::{UpdateMeta, UpdateResult, UpdateStatus};
@ -89,10 +90,8 @@ pub struct FailedUpdateResult {
pub update_id: u64, pub update_id: u64,
#[serde(rename = "type")] #[serde(rename = "type")]
pub update_type: UpdateType, pub update_type: UpdateType,
pub error: String, #[serde(flatten)]
pub error_type: String, pub response: ResponseError,
pub error_code: String,
pub error_link: String,
pub duration: f64, // in seconds pub duration: f64, // in seconds
pub enqueued_at: DateTime<Utc>, pub enqueued_at: DateTime<Utc>,
pub processed_at: DateTime<Utc>, pub processed_at: DateTime<Utc>,
@ -181,13 +180,13 @@ impl From<UpdateStatus> for UpdateStatusResponse {
// necessary since chrono::duration don't expose a f64 secs method. // necessary since chrono::duration don't expose a f64 secs method.
let duration = Duration::from_millis(duration as u64).as_secs_f64(); let duration = Duration::from_millis(duration as u64).as_secs_f64();
let update_id = failed.id();
let response = failed.error;
let content = FailedUpdateResult { let content = FailedUpdateResult {
update_id: failed.id(), update_id,
update_type, update_type,
error: failed.error, response,
error_type: String::from("todo"),
error_code: String::from("todo"),
error_link: String::from("todo"),
duration, duration,
enqueued_at: failed.from.from.enqueued_at, enqueued_at: failed.from.from.enqueued_at,
processed_at: failed.failed_at, processed_at: failed.failed_at,