mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 20:37:15 +02:00
Merge branch 'main' into fix-3037
This commit is contained in:
commit
9c28632498
173 changed files with 5109 additions and 1714 deletions
|
@ -147,6 +147,11 @@ pub enum Code {
|
|||
MissingMasterKey,
|
||||
NoSpaceLeftOnDevice,
|
||||
DumpNotFound,
|
||||
InvalidTaskDateFilter,
|
||||
InvalidTaskStatusesFilter,
|
||||
InvalidTaskTypesFilter,
|
||||
InvalidTaskCanceledByFilter,
|
||||
InvalidTaskUidsFilter,
|
||||
TaskNotFound,
|
||||
TaskDeletionWithEmptyQuery,
|
||||
TaskCancelationWithEmptyQuery,
|
||||
|
@ -239,12 +244,27 @@ impl Code {
|
|||
MissingMasterKey => {
|
||||
ErrCode::authentication("missing_master_key", StatusCode::UNAUTHORIZED)
|
||||
}
|
||||
InvalidTaskDateFilter => {
|
||||
ErrCode::invalid("invalid_task_date_filter", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
InvalidTaskUidsFilter => {
|
||||
ErrCode::invalid("invalid_task_uids_filter", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
InvalidTaskStatusesFilter => {
|
||||
ErrCode::invalid("invalid_task_statuses_filter", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
InvalidTaskTypesFilter => {
|
||||
ErrCode::invalid("invalid_task_types_filter", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
InvalidTaskCanceledByFilter => {
|
||||
ErrCode::invalid("invalid_task_canceled_by_filter", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
TaskNotFound => ErrCode::invalid("task_not_found", StatusCode::NOT_FOUND),
|
||||
TaskDeletionWithEmptyQuery => {
|
||||
ErrCode::invalid("missing_filters", StatusCode::BAD_REQUEST)
|
||||
ErrCode::invalid("missing_task_filters", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
TaskCancelationWithEmptyQuery => {
|
||||
ErrCode::invalid("missing_filters", StatusCode::BAD_REQUEST)
|
||||
ErrCode::invalid("missing_task_filters", StatusCode::BAD_REQUEST)
|
||||
}
|
||||
DumpNotFound => ErrCode::invalid("dump_not_found", StatusCode::NOT_FOUND),
|
||||
NoSpaceLeftOnDevice => {
|
||||
|
|
|
@ -75,9 +75,9 @@ impl fmt::Display for IndexUidFormatError {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"invalid index uid `{}`, the uid must be an integer \
|
||||
or a string containing only alphanumeric characters \
|
||||
a-z A-Z 0-9, hyphens - and underscores _.",
|
||||
"`{}` is not a valid index uid. Index uid can be an \
|
||||
integer or a string containing only alphanumeric \
|
||||
characters, hyphens (-) and underscores (_).",
|
||||
self.invalid_uid,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::hash::Hash;
|
||||
use std::str::FromStr;
|
||||
|
||||
use enum_iterator::Sequence;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -9,7 +10,7 @@ use time::{Date, OffsetDateTime, PrimitiveDateTime};
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::error::{Code, ErrorCode};
|
||||
use crate::index_uid::IndexUid;
|
||||
use crate::index_uid::{IndexUid, IndexUidFormatError};
|
||||
use crate::star_or::StarOr;
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
@ -64,7 +65,15 @@ impl Key {
|
|||
let indexes = value
|
||||
.get("indexes")
|
||||
.map(|ind| {
|
||||
from_value(ind.clone()).map_err(|_| Error::InvalidApiKeyIndexes(ind.clone()))
|
||||
from_value::<Vec<String>>(ind.clone())
|
||||
// If it's not a vec of string, return an API key parsing error.
|
||||
.map_err(|_| Error::InvalidApiKeyIndexes(ind.clone()))
|
||||
.and_then(|ind| {
|
||||
ind.into_iter()
|
||||
// If it's not a valid Index uid, return an Index Uid parsing error.
|
||||
.map(|i| StarOr::<IndexUid>::from_str(&i).map_err(Error::from))
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
.ok_or(Error::MissingParameter("indexes"))??;
|
||||
|
||||
|
@ -339,10 +348,10 @@ pub enum Error {
|
|||
MissingParameter(&'static str),
|
||||
#[error("`actions` field value `{0}` is invalid. It should be an array of string representing action names.")]
|
||||
InvalidApiKeyActions(Value),
|
||||
#[error(
|
||||
"`{0}` is not a valid index uid. It should be an array of string representing index names."
|
||||
)]
|
||||
#[error("`indexes` field value `{0}` is invalid. It should be an array of string representing index names.")]
|
||||
InvalidApiKeyIndexes(Value),
|
||||
#[error("{0}")]
|
||||
InvalidApiKeyIndexUid(IndexUidFormatError),
|
||||
#[error("`expiresAt` field value `{0}` is invalid. It should follow the RFC 3339 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'.")]
|
||||
InvalidApiKeyExpiresAt(Value),
|
||||
#[error("`description` field value `{0}` is invalid. It should be a string or specified as a null value.")]
|
||||
|
@ -357,12 +366,20 @@ pub enum Error {
|
|||
ImmutableField(String),
|
||||
}
|
||||
|
||||
impl From<IndexUidFormatError> for Error {
|
||||
fn from(e: IndexUidFormatError) -> Self {
|
||||
Self::InvalidApiKeyIndexUid(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorCode for Error {
|
||||
fn error_code(&self) -> Code {
|
||||
match self {
|
||||
Self::MissingParameter(_) => Code::MissingParameter,
|
||||
Self::InvalidApiKeyActions(_) => Code::InvalidApiKeyActions,
|
||||
Self::InvalidApiKeyIndexes(_) => Code::InvalidApiKeyIndexes,
|
||||
Self::InvalidApiKeyIndexes(_) | Self::InvalidApiKeyIndexUid(_) => {
|
||||
Code::InvalidApiKeyIndexes
|
||||
}
|
||||
Self::InvalidApiKeyExpiresAt(_) => Code::InvalidApiKeyExpiresAt,
|
||||
Self::InvalidApiKeyDescription(_) => Code::InvalidApiKeyDescription,
|
||||
Self::InvalidApiKeyName(_) => Code::InvalidApiKeyName,
|
||||
|
|
|
@ -127,7 +127,6 @@ pub enum KindWithContent {
|
|||
tasks: RoaringBitmap,
|
||||
},
|
||||
DumpCreation {
|
||||
dump_uid: String,
|
||||
keys: Vec<Key>,
|
||||
instance_uid: Option<InstanceUid>,
|
||||
},
|
||||
|
@ -196,17 +195,16 @@ impl KindWithContent {
|
|||
}
|
||||
KindWithContent::DocumentDeletion { index_uid: _, documents_ids } => {
|
||||
Some(Details::DocumentDeletion {
|
||||
matched_documents: documents_ids.len(),
|
||||
provided_ids: documents_ids.len(),
|
||||
deleted_documents: None,
|
||||
})
|
||||
}
|
||||
KindWithContent::DocumentClear { .. } => {
|
||||
KindWithContent::DocumentClear { .. } | KindWithContent::IndexDeletion { .. } => {
|
||||
Some(Details::ClearAll { deleted_documents: None })
|
||||
}
|
||||
KindWithContent::SettingsUpdate { new_settings, .. } => {
|
||||
Some(Details::SettingsUpdate { settings: new_settings.clone() })
|
||||
}
|
||||
KindWithContent::IndexDeletion { .. } => None,
|
||||
KindWithContent::IndexCreation { primary_key, .. }
|
||||
| KindWithContent::IndexUpdate { primary_key, .. } => {
|
||||
Some(Details::IndexInfo { primary_key: primary_key.clone() })
|
||||
|
@ -217,14 +215,14 @@ impl KindWithContent {
|
|||
KindWithContent::TaskCancelation { query, tasks } => Some(Details::TaskCancelation {
|
||||
matched_tasks: tasks.len(),
|
||||
canceled_tasks: None,
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::TaskDeletion { query, tasks } => Some(Details::TaskDeletion {
|
||||
matched_tasks: tasks.len(),
|
||||
deleted_tasks: None,
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::DumpCreation { .. } => None,
|
||||
KindWithContent::DumpCreation { .. } => Some(Details::Dump { dump_uid: None }),
|
||||
KindWithContent::SnapshotCreation => None,
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +237,7 @@ impl KindWithContent {
|
|||
}
|
||||
KindWithContent::DocumentDeletion { index_uid: _, documents_ids } => {
|
||||
Some(Details::DocumentDeletion {
|
||||
matched_documents: documents_ids.len(),
|
||||
provided_ids: documents_ids.len(),
|
||||
deleted_documents: Some(0),
|
||||
})
|
||||
}
|
||||
|
@ -260,14 +258,14 @@ impl KindWithContent {
|
|||
KindWithContent::TaskCancelation { query, tasks } => Some(Details::TaskCancelation {
|
||||
matched_tasks: tasks.len(),
|
||||
canceled_tasks: Some(0),
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::TaskDeletion { query, tasks } => Some(Details::TaskDeletion {
|
||||
matched_tasks: tasks.len(),
|
||||
deleted_tasks: Some(0),
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::DumpCreation { .. } => None,
|
||||
KindWithContent::DumpCreation { .. } => Some(Details::Dump { dump_uid: None }),
|
||||
KindWithContent::SnapshotCreation => None,
|
||||
}
|
||||
}
|
||||
|
@ -298,16 +296,14 @@ impl From<&KindWithContent> for Option<Details> {
|
|||
KindWithContent::TaskCancelation { query, tasks } => Some(Details::TaskCancelation {
|
||||
matched_tasks: tasks.len(),
|
||||
canceled_tasks: None,
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::TaskDeletion { query, tasks } => Some(Details::TaskDeletion {
|
||||
matched_tasks: tasks.len(),
|
||||
deleted_tasks: None,
|
||||
original_query: query.clone(),
|
||||
original_filter: query.clone(),
|
||||
}),
|
||||
KindWithContent::DumpCreation { dump_uid, .. } => {
|
||||
Some(Details::Dump { dump_uid: dump_uid.clone() })
|
||||
}
|
||||
KindWithContent::DumpCreation { .. } => Some(Details::Dump { dump_uid: None }),
|
||||
KindWithContent::SnapshotCreation => None,
|
||||
}
|
||||
}
|
||||
|
@ -398,7 +394,23 @@ impl Kind {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Kind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Kind::DocumentAdditionOrUpdate => write!(f, "documentAdditionOrUpdate"),
|
||||
Kind::DocumentDeletion => write!(f, "documentDeletion"),
|
||||
Kind::SettingsUpdate => write!(f, "settingsUpdate"),
|
||||
Kind::IndexCreation => write!(f, "indexCreation"),
|
||||
Kind::IndexDeletion => write!(f, "indexDeletion"),
|
||||
Kind::IndexUpdate => write!(f, "indexUpdate"),
|
||||
Kind::IndexSwap => write!(f, "indexSwap"),
|
||||
Kind::TaskCancelation => write!(f, "taskCancelation"),
|
||||
Kind::TaskDeletion => write!(f, "taskDeletion"),
|
||||
Kind::DumpCreation => write!(f, "dumpCreation"),
|
||||
Kind::SnapshotCreation => write!(f, "snapshotCreation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl FromStr for Kind {
|
||||
type Err = ResponseError;
|
||||
|
||||
|
@ -450,14 +462,35 @@ pub enum Details {
|
|||
DocumentAdditionOrUpdate { received_documents: u64, indexed_documents: Option<u64> },
|
||||
SettingsUpdate { settings: Box<Settings<Unchecked>> },
|
||||
IndexInfo { primary_key: Option<String> },
|
||||
DocumentDeletion { matched_documents: usize, deleted_documents: Option<u64> },
|
||||
DocumentDeletion { provided_ids: usize, deleted_documents: Option<u64> },
|
||||
ClearAll { deleted_documents: Option<u64> },
|
||||
TaskCancelation { matched_tasks: u64, canceled_tasks: Option<u64>, original_query: String },
|
||||
TaskDeletion { matched_tasks: u64, deleted_tasks: Option<u64>, original_query: String },
|
||||
Dump { dump_uid: String },
|
||||
TaskCancelation { matched_tasks: u64, canceled_tasks: Option<u64>, original_filter: String },
|
||||
TaskDeletion { matched_tasks: u64, deleted_tasks: Option<u64>, original_filter: String },
|
||||
Dump { dump_uid: Option<String> },
|
||||
IndexSwap { swaps: Vec<IndexSwap> },
|
||||
}
|
||||
|
||||
impl Details {
|
||||
pub fn to_failed(&self) -> Self {
|
||||
let mut details = self.clone();
|
||||
match &mut details {
|
||||
Self::DocumentAdditionOrUpdate { indexed_documents, .. } => {
|
||||
*indexed_documents = Some(0)
|
||||
}
|
||||
Self::DocumentDeletion { deleted_documents, .. } => *deleted_documents = Some(0),
|
||||
Self::ClearAll { deleted_documents } => *deleted_documents = Some(0),
|
||||
Self::TaskCancelation { canceled_tasks, .. } => *canceled_tasks = Some(0),
|
||||
Self::TaskDeletion { deleted_tasks, .. } => *deleted_tasks = Some(0),
|
||||
Self::SettingsUpdate { .. }
|
||||
| Self::IndexInfo { .. }
|
||||
| Self::Dump { .. }
|
||||
| Self::IndexSwap { .. } => (),
|
||||
}
|
||||
|
||||
details
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize a `time::Duration` as a best effort ISO 8601 while waiting for
|
||||
/// https://github.com/time-rs/time/issues/378.
|
||||
/// This code is a port of the old code of time that was removed in 0.2.
|
||||
|
@ -520,11 +553,11 @@ mod tests {
|
|||
let details = Details::TaskDeletion {
|
||||
matched_tasks: 1,
|
||||
deleted_tasks: None,
|
||||
original_query: "hello".to_owned(),
|
||||
original_filter: "hello".to_owned(),
|
||||
};
|
||||
let serialised = SerdeJson::<Details>::bytes_encode(&details).unwrap();
|
||||
let deserialised = SerdeJson::<Details>::bytes_decode(&serialised).unwrap();
|
||||
meili_snap::snapshot!(format!("{:?}", details), @r###"TaskDeletion { matched_tasks: 1, deleted_tasks: None, original_query: "hello" }"###);
|
||||
meili_snap::snapshot!(format!("{:?}", deserialised), @r###"TaskDeletion { matched_tasks: 1, deleted_tasks: None, original_query: "hello" }"###);
|
||||
meili_snap::snapshot!(format!("{:?}", details), @r###"TaskDeletion { matched_tasks: 1, deleted_tasks: None, original_filter: "hello" }"###);
|
||||
meili_snap::snapshot!(format!("{:?}", deserialised), @r###"TaskDeletion { matched_tasks: 1, deleted_tasks: None, original_filter: "hello" }"###);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue