2022-12-14 13:00:43 +01:00
use std ::fmt ::Display ;
2022-09-22 12:14:51 +02:00
use meilisearch_types ::error ::{ Code , ErrorCode } ;
2022-11-28 16:27:41 +01:00
use meilisearch_types ::tasks ::{ Kind , Status } ;
2022-10-20 18:00:07 +02:00
use meilisearch_types ::{ heed , milli } ;
2022-09-06 16:43:59 +02:00
use thiserror ::Error ;
2022-09-21 17:13:09 +02:00
use crate ::TaskId ;
2022-12-14 13:00:43 +01:00
#[ derive(Copy, Clone, Debug, PartialEq, Eq) ]
pub enum DateField {
BeforeEnqueuedAt ,
AfterEnqueuedAt ,
BeforeStartedAt ,
AfterStartedAt ,
BeforeFinishedAt ,
AfterFinishedAt ,
}
impl Display for DateField {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
match self {
DateField ::BeforeEnqueuedAt = > write! ( f , " beforeEnqueuedAt " ) ,
DateField ::AfterEnqueuedAt = > write! ( f , " afterEnqueuedAt " ) ,
DateField ::BeforeStartedAt = > write! ( f , " beforeStartedAt " ) ,
DateField ::AfterStartedAt = > write! ( f , " afterStartedAt " ) ,
DateField ::BeforeFinishedAt = > write! ( f , " beforeFinishedAt " ) ,
DateField ::AfterFinishedAt = > write! ( f , " afterFinishedAt " ) ,
}
}
}
impl From < DateField > for Code {
fn from ( date : DateField ) -> Self {
match date {
DateField ::BeforeEnqueuedAt = > Code ::InvalidTaskBeforeEnqueuedAt ,
DateField ::AfterEnqueuedAt = > Code ::InvalidTaskAfterEnqueuedAt ,
DateField ::BeforeStartedAt = > Code ::InvalidTaskBeforeStartedAt ,
DateField ::AfterStartedAt = > Code ::InvalidTaskAfterStartedAt ,
DateField ::BeforeFinishedAt = > Code ::InvalidTaskBeforeFinishedAt ,
DateField ::AfterFinishedAt = > Code ::InvalidTaskAfterFinishedAt ,
}
}
}
2022-10-22 16:35:42 +02:00
#[ allow(clippy::large_enum_variant) ]
2022-09-06 16:43:59 +02:00
#[ derive(Error, Debug) ]
pub enum Error {
2023-05-16 13:56:18 +02:00
#[ error( " {1} " ) ]
WithCustomErrorCode ( Code , Box < Self > ) ,
2023-09-07 11:16:51 +02:00
#[ error( " Received bad task id: {received} should be >= to {expected}. " ) ]
BadTaskId { received : TaskId , expected : TaskId } ,
2022-10-21 14:12:25 +02:00
#[ error( " Index `{0}` not found. " ) ]
2022-09-07 20:08:07 +02:00
IndexNotFound ( String ) ,
2022-10-21 14:12:25 +02:00
#[ error( " Index `{0}` already exists. " ) ]
2022-09-07 20:08:07 +02:00
IndexAlreadyExists ( String ) ,
2022-10-27 09:41:32 +02:00
#[ error(
" Indexes must be declared only once during a swap. `{0}` was specified several times. "
) ]
SwapDuplicateIndexFound ( String ) ,
#[ error(
" Indexes must be declared only once during a swap. {} were specified several times. " ,
. 0. iter ( ) . map ( | s | format! ( " ` {} ` " , s ) ) . collect ::< Vec < _ > > ( ) . join ( " , " )
) ]
SwapDuplicateIndexesFound ( Vec < String > ) ,
2023-01-05 23:21:44 +01:00
#[ error( " Index `{0}` not found. " ) ]
SwapIndexNotFound ( String ) ,
2023-04-12 18:46:24 +02:00
#[ error( " Meilisearch cannot receive write operations because the limit of the task database has been reached. Please delete tasks to continue performing write operations. " ) ]
2023-04-06 18:26:27 +02:00
NoSpaceLeftInTaskQueue ,
2023-01-05 23:21:44 +01:00
#[ error(
" Indexes {} not found. " ,
. 0. iter ( ) . map ( | s | format! ( " ` {} ` " , s ) ) . collect ::< Vec < _ > > ( ) . join ( " , " )
) ]
SwapIndexesNotFound ( Vec < String > ) ,
2022-10-16 01:39:01 +02:00
#[ error( " Corrupted dump. " ) ]
CorruptedDump ,
2022-11-28 16:27:41 +01:00
#[ error(
" Task `{field}` `{date}` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format. "
) ]
2022-12-14 13:00:43 +01:00
InvalidTaskDate { field : DateField , date : String } ,
2022-11-28 16:27:41 +01:00
#[ error( " Task uid `{task_uid}` is invalid. It should only contain numeric characters. " ) ]
InvalidTaskUids { task_uid : String } ,
#[ error(
" Task status `{status}` is invalid. Available task statuses are {}. " ,
enum_iterator ::all ::< Status > ( )
. map ( | s | format! ( " ` {s} ` " ) )
. collect ::< Vec < String > > ( )
. join ( " , " )
) ]
InvalidTaskStatuses { status : String } ,
#[ error(
" Task type `{type_}` is invalid. Available task types are {} " ,
enum_iterator ::all ::< Kind > ( )
. map ( | s | format! ( " ` {s} ` " ) )
. collect ::< Vec < String > > ( )
. join ( " , " )
) ]
InvalidTaskTypes { type_ : String } ,
#[ error(
" Task canceledBy `{canceled_by}` is invalid. It should only contains numeric characters separated by `,` character. "
) ]
InvalidTaskCanceledBy { canceled_by : String } ,
#[ error(
2024-09-16 21:22:24 +02:00
" {index_uid} is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_), and can not be more than 512 bytes. "
2022-11-28 16:27:41 +01:00
) ]
InvalidIndexUid { index_uid : String } ,
2022-10-21 14:12:25 +02:00
#[ error( " Task `{0}` not found. " ) ]
2022-09-21 17:13:09 +02:00
TaskNotFound ( TaskId ) ,
2023-01-19 12:42:08 +01:00
#[ error( " Query parameters to filter the tasks to delete are missing. Available query parameters are: `uids`, `indexUids`, `statuses`, `types`, `canceledBy`, `beforeEnqueuedAt`, `afterEnqueuedAt`, `beforeStartedAt`, `afterStartedAt`, `beforeFinishedAt`, `afterFinishedAt`. " ) ]
2022-10-15 11:17:06 +02:00
TaskDeletionWithEmptyQuery ,
2023-01-19 12:42:08 +01:00
#[ error( " Query parameters to filter the tasks to cancel are missing. Available query parameters are: `uids`, `indexUids`, `statuses`, `types`, `canceledBy`, `beforeEnqueuedAt`, `afterEnqueuedAt`, `beforeStartedAt`, `afterStartedAt`, `beforeFinishedAt`, `afterFinishedAt`. " ) ]
2022-10-18 14:48:40 +02:00
TaskCancelationWithEmptyQuery ,
2023-11-14 10:59:02 +01:00
#[ error( " Aborted task " ) ]
AbortedTask ,
2022-09-22 12:14:51 +02:00
2022-10-13 15:02:59 +02:00
#[ error(transparent) ]
Dump ( #[ from ] dump ::Error ) ,
2022-09-06 23:49:19 +02:00
#[ error(transparent) ]
Heed ( #[ from ] heed ::Error ) ,
#[ error(transparent) ]
Milli ( #[ from ] milli ::Error ) ,
2022-10-25 09:48:51 +02:00
#[ error( " An unexpected crash occurred when processing the task. " ) ]
2022-10-24 14:16:14 +02:00
ProcessBatchPanicked ,
2022-09-14 16:16:53 +02:00
#[ error(transparent) ]
FileStore ( #[ from ] file_store ::Error ) ,
#[ error(transparent) ]
2022-09-07 21:27:06 +02:00
IoError ( #[ from ] std ::io ::Error ) ,
2022-10-25 15:51:15 +02:00
#[ error(transparent) ]
Persist ( #[ from ] tempfile ::PersistError ) ,
2023-06-22 22:56:44 +02:00
#[ error(transparent) ]
FeatureNotEnabled ( #[ from ] FeatureNotEnabledError ) ,
2022-09-06 23:49:19 +02:00
#[ error(transparent) ]
Anyhow ( #[ from ] anyhow ::Error ) ,
2022-10-24 14:16:14 +02:00
// Irrecoverable errors:
#[ error(transparent) ]
CreateBatch ( Box < Self > ) ,
#[ error( " Corrupted task queue. " ) ]
CorruptedTaskQueue ,
#[ error(transparent) ]
TaskDatabaseUpdate ( Box < Self > ) ,
#[ error(transparent) ]
HeedTransaction ( heed ::Error ) ,
2023-04-03 21:08:47 +02:00
#[ cfg(test) ]
#[ error( " Planned failure for tests. " ) ]
PlannedFailure ,
}
2023-06-22 22:56:44 +02:00
#[ derive(Debug, thiserror::Error) ]
#[ error(
" {disabled_action} requires enabling the `{feature}` experimental feature. See {issue_link} "
) ]
pub struct FeatureNotEnabledError {
pub disabled_action : & 'static str ,
pub feature : & 'static str ,
pub issue_link : & 'static str ,
}
2023-04-03 21:08:47 +02:00
impl Error {
pub fn is_recoverable ( & self ) -> bool {
match self {
Error ::IndexNotFound ( _ )
2023-05-16 13:56:18 +02:00
| Error ::WithCustomErrorCode ( _ , _ )
2023-09-07 11:16:51 +02:00
| Error ::BadTaskId { .. }
2023-04-03 21:08:47 +02:00
| Error ::IndexAlreadyExists ( _ )
| Error ::SwapDuplicateIndexFound ( _ )
| Error ::SwapDuplicateIndexesFound ( _ )
| Error ::SwapIndexNotFound ( _ )
| Error ::NoSpaceLeftInTaskQueue
| Error ::SwapIndexesNotFound ( _ )
| Error ::CorruptedDump
| Error ::InvalidTaskDate { .. }
| Error ::InvalidTaskUids { .. }
| Error ::InvalidTaskStatuses { .. }
| Error ::InvalidTaskTypes { .. }
| Error ::InvalidTaskCanceledBy { .. }
| Error ::InvalidIndexUid { .. }
| Error ::TaskNotFound ( _ )
| Error ::TaskDeletionWithEmptyQuery
| Error ::TaskCancelationWithEmptyQuery
2023-11-14 10:59:02 +01:00
| Error ::AbortedTask
2023-04-03 21:08:47 +02:00
| Error ::Dump ( _ )
| Error ::Heed ( _ )
| Error ::Milli ( _ )
| Error ::ProcessBatchPanicked
| Error ::FileStore ( _ )
| Error ::IoError ( _ )
| Error ::Persist ( _ )
2023-06-22 22:56:44 +02:00
| Error ::FeatureNotEnabled ( _ )
2023-04-03 21:08:47 +02:00
| Error ::Anyhow ( _ ) = > true ,
Error ::CreateBatch ( _ )
| Error ::CorruptedTaskQueue
| Error ::TaskDatabaseUpdate ( _ )
| Error ::HeedTransaction ( _ ) = > false ,
#[ cfg(test) ]
Error ::PlannedFailure = > false ,
}
}
2023-05-16 13:56:18 +02:00
pub fn with_custom_error_code ( self , code : Code ) -> Self {
Self ::WithCustomErrorCode ( code , Box ::new ( self ) )
}
2022-09-06 16:43:59 +02:00
}
2022-09-22 12:14:51 +02:00
impl ErrorCode for Error {
fn error_code ( & self ) -> Code {
match self {
2023-05-16 13:56:18 +02:00
Error ::WithCustomErrorCode ( code , _ ) = > * code ,
2023-09-07 11:16:51 +02:00
Error ::BadTaskId { .. } = > Code ::BadRequest ,
2022-09-22 12:14:51 +02:00
Error ::IndexNotFound ( _ ) = > Code ::IndexNotFound ,
Error ::IndexAlreadyExists ( _ ) = > Code ::IndexAlreadyExists ,
2023-01-11 12:33:45 +01:00
Error ::SwapDuplicateIndexesFound ( _ ) = > Code ::InvalidSwapDuplicateIndexFound ,
Error ::SwapDuplicateIndexFound ( _ ) = > Code ::InvalidSwapDuplicateIndexFound ,
2023-01-18 14:16:00 +01:00
Error ::SwapIndexNotFound ( _ ) = > Code ::IndexNotFound ,
Error ::SwapIndexesNotFound ( _ ) = > Code ::IndexNotFound ,
2022-12-14 13:00:43 +01:00
Error ::InvalidTaskDate { field , .. } = > ( * field ) . into ( ) ,
Error ::InvalidTaskUids { .. } = > Code ::InvalidTaskUids ,
Error ::InvalidTaskStatuses { .. } = > Code ::InvalidTaskStatuses ,
Error ::InvalidTaskTypes { .. } = > Code ::InvalidTaskTypes ,
Error ::InvalidTaskCanceledBy { .. } = > Code ::InvalidTaskCanceledBy ,
2022-11-28 16:27:41 +01:00
Error ::InvalidIndexUid { .. } = > Code ::InvalidIndexUid ,
2022-09-22 12:14:51 +02:00
Error ::TaskNotFound ( _ ) = > Code ::TaskNotFound ,
2023-01-11 12:33:45 +01:00
Error ::TaskDeletionWithEmptyQuery = > Code ::MissingTaskFilters ,
Error ::TaskCancelationWithEmptyQuery = > Code ::MissingTaskFilters ,
2023-04-06 18:26:27 +02:00
// TODO: not sure of the Code to use
Error ::NoSpaceLeftInTaskQueue = > Code ::NoSpaceLeftOnDevice ,
2022-10-13 15:02:59 +02:00
Error ::Dump ( e ) = > e . error_code ( ) ,
Error ::Milli ( e ) = > e . error_code ( ) ,
2022-10-24 14:16:14 +02:00
Error ::ProcessBatchPanicked = > Code ::Internal ,
2022-12-19 20:50:40 +01:00
Error ::Heed ( e ) = > e . error_code ( ) ,
Error ::HeedTransaction ( e ) = > e . error_code ( ) ,
Error ::FileStore ( e ) = > e . error_code ( ) ,
Error ::IoError ( e ) = > e . error_code ( ) ,
Error ::Persist ( e ) = > e . error_code ( ) ,
2023-06-22 22:56:44 +02:00
Error ::FeatureNotEnabled ( _ ) = > Code ::FeatureNotEnabled ,
2023-01-05 23:21:44 +01:00
2022-12-19 20:50:40 +01:00
// Irrecoverable errors
2022-09-22 12:14:51 +02:00
Error ::Anyhow ( _ ) = > Code ::Internal ,
Error ::CorruptedTaskQueue = > Code ::Internal ,
2022-10-16 01:39:01 +02:00
Error ::CorruptedDump = > Code ::Internal ,
2022-10-24 14:16:14 +02:00
Error ::TaskDatabaseUpdate ( _ ) = > Code ::Internal ,
Error ::CreateBatch ( _ ) = > Code ::Internal ,
2023-04-03 21:08:47 +02:00
2023-11-14 10:59:02 +01:00
// This one should never be seen by the end user
Error ::AbortedTask = > Code ::Internal ,
2023-04-03 21:08:47 +02:00
#[ cfg(test) ]
Error ::PlannedFailure = > Code ::Internal ,
2022-09-22 12:14:51 +02:00
}
}
}