mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 04:17:10 +02:00
refactor the Task a little bit
This commit is contained in:
parent
e6c033bd6b
commit
e533e740d4
17 changed files with 1358 additions and 833 deletions
|
@ -15,6 +15,7 @@ serde = { version = "1.0.145", features = ["derive"] }
|
|||
serde_json = "1.0.85"
|
||||
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
||||
tokio = "1.0"
|
||||
uuid = { version = "1.1.2", features = ["serde", "v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "1.0.0"
|
||||
|
|
|
@ -2,9 +2,11 @@ use milli::update::IndexDocumentsMethod;
|
|||
use serde::{Deserialize, Serialize, Serializer};
|
||||
use std::{
|
||||
fmt::{Display, Write},
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
};
|
||||
use time::{Duration, OffsetDateTime};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
error::{Code, ResponseError},
|
||||
|
@ -13,74 +15,192 @@ use crate::{
|
|||
|
||||
pub type TaskId = u32;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TaskView {
|
||||
pub struct Task {
|
||||
pub uid: TaskId,
|
||||
#[serde(default)]
|
||||
pub index_uid: Option<String>,
|
||||
pub status: Status,
|
||||
// TODO use our own Kind for the user
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Kind,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub details: Option<DetailsView>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<ResponseError>,
|
||||
|
||||
#[serde(
|
||||
serialize_with = "serialize_duration",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default
|
||||
)]
|
||||
pub duration: Option<Duration>,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub enqueued_at: OffsetDateTime,
|
||||
#[serde(
|
||||
with = "time::serde::rfc3339::option",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default
|
||||
)]
|
||||
#[serde(with = "time::serde::rfc3339::option")]
|
||||
pub started_at: Option<OffsetDateTime>,
|
||||
#[serde(
|
||||
with = "time::serde::rfc3339::option",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default
|
||||
)]
|
||||
#[serde(with = "time::serde::rfc3339::option")]
|
||||
pub finished_at: Option<OffsetDateTime>,
|
||||
|
||||
pub error: Option<ResponseError>,
|
||||
pub details: Option<Details>,
|
||||
|
||||
pub status: Status,
|
||||
pub kind: KindWithContent,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
impl Task {
|
||||
pub fn index_uid(&self) -> Option<&str> {
|
||||
use KindWithContent::*;
|
||||
|
||||
match &self.kind {
|
||||
DumpExport { .. }
|
||||
| Snapshot
|
||||
| CancelTask { .. }
|
||||
| DeleteTasks { .. }
|
||||
| IndexSwap { .. } => None,
|
||||
DocumentImport { index_uid, .. }
|
||||
| DocumentDeletion { index_uid, .. }
|
||||
| DocumentClear { index_uid }
|
||||
| Settings { index_uid, .. }
|
||||
| IndexCreation { index_uid, .. }
|
||||
| IndexUpdate { index_uid, .. }
|
||||
| IndexDeletion { index_uid } => Some(index_uid),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the list of indexes updated by this tasks.
|
||||
pub fn indexes(&self) -> Option<Vec<&str>> {
|
||||
use KindWithContent::*;
|
||||
|
||||
match &self.kind {
|
||||
DumpExport { .. } | Snapshot | CancelTask { .. } | DeleteTasks { .. } => None,
|
||||
DocumentImport { index_uid, .. }
|
||||
| DocumentDeletion { index_uid, .. }
|
||||
| DocumentClear { index_uid }
|
||||
| Settings { index_uid, .. }
|
||||
| IndexCreation { index_uid, .. }
|
||||
| IndexUpdate { index_uid, .. }
|
||||
| IndexDeletion { index_uid } => Some(vec![index_uid]),
|
||||
IndexSwap { lhs, rhs } => Some(vec![lhs, rhs]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TaskDump {
|
||||
pub uid: TaskId,
|
||||
#[serde(default)]
|
||||
pub index_uid: Option<String>,
|
||||
pub status: Status,
|
||||
// TODO use our own Kind for the user
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Kind,
|
||||
pub enum KindWithContent {
|
||||
DocumentImport {
|
||||
index_uid: String,
|
||||
primary_key: Option<String>,
|
||||
method: IndexDocumentsMethod,
|
||||
content_file: Uuid,
|
||||
documents_count: u64,
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
DocumentDeletion {
|
||||
index_uid: String,
|
||||
documents_ids: Vec<String>,
|
||||
},
|
||||
DocumentClear {
|
||||
index_uid: String,
|
||||
},
|
||||
Settings {
|
||||
index_uid: String,
|
||||
new_settings: Settings<Unchecked>,
|
||||
is_deletion: bool,
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
IndexDeletion {
|
||||
index_uid: String,
|
||||
},
|
||||
IndexCreation {
|
||||
index_uid: String,
|
||||
primary_key: Option<String>,
|
||||
},
|
||||
IndexUpdate {
|
||||
index_uid: String,
|
||||
primary_key: Option<String>,
|
||||
},
|
||||
IndexSwap {
|
||||
lhs: String,
|
||||
rhs: String,
|
||||
},
|
||||
CancelTask {
|
||||
tasks: Vec<TaskId>,
|
||||
},
|
||||
DeleteTasks {
|
||||
query: String,
|
||||
tasks: Vec<TaskId>,
|
||||
},
|
||||
DumpExport {
|
||||
output: PathBuf,
|
||||
},
|
||||
Snapshot,
|
||||
}
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub details: Option<Details>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<ResponseError>,
|
||||
impl KindWithContent {
|
||||
pub fn as_kind(&self) -> Kind {
|
||||
match self {
|
||||
KindWithContent::DocumentImport { .. } => Kind::DocumentImport,
|
||||
KindWithContent::DocumentDeletion { .. } => Kind::DocumentDeletion,
|
||||
KindWithContent::DocumentClear { .. } => Kind::DocumentClear,
|
||||
KindWithContent::Settings { .. } => Kind::Settings,
|
||||
KindWithContent::IndexCreation { .. } => Kind::IndexCreation,
|
||||
KindWithContent::IndexDeletion { .. } => Kind::IndexDeletion,
|
||||
KindWithContent::IndexUpdate { .. } => Kind::IndexUpdate,
|
||||
KindWithContent::IndexSwap { .. } => Kind::IndexSwap,
|
||||
KindWithContent::CancelTask { .. } => Kind::CancelTask,
|
||||
KindWithContent::DeleteTasks { .. } => Kind::DeleteTasks,
|
||||
KindWithContent::DumpExport { .. } => Kind::DumpExport,
|
||||
KindWithContent::Snapshot => Kind::Snapshot,
|
||||
}
|
||||
}
|
||||
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub enqueued_at: OffsetDateTime,
|
||||
#[serde(
|
||||
with = "time::serde::rfc3339::option",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default
|
||||
)]
|
||||
pub started_at: Option<OffsetDateTime>,
|
||||
#[serde(
|
||||
with = "time::serde::rfc3339::option",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default
|
||||
)]
|
||||
pub finished_at: Option<OffsetDateTime>,
|
||||
pub fn indexes(&self) -> Option<Vec<&str>> {
|
||||
use KindWithContent::*;
|
||||
|
||||
match self {
|
||||
DumpExport { .. } | Snapshot | CancelTask { .. } | DeleteTasks { .. } => None,
|
||||
DocumentImport { index_uid, .. }
|
||||
| DocumentDeletion { index_uid, .. }
|
||||
| DocumentClear { index_uid }
|
||||
| Settings { index_uid, .. }
|
||||
| IndexCreation { index_uid, .. }
|
||||
| IndexUpdate { index_uid, .. }
|
||||
| IndexDeletion { index_uid } => Some(vec![index_uid]),
|
||||
IndexSwap { lhs, rhs } => Some(vec![lhs, rhs]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the default `Details` that correspond to this `KindWithContent`,
|
||||
/// `None` if it cannot be generated.
|
||||
pub fn default_details(&self) -> Option<Details> {
|
||||
match self {
|
||||
KindWithContent::DocumentImport {
|
||||
documents_count, ..
|
||||
} => Some(Details::DocumentAddition {
|
||||
received_documents: *documents_count,
|
||||
indexed_documents: 0,
|
||||
}),
|
||||
KindWithContent::DocumentDeletion {
|
||||
index_uid: _,
|
||||
documents_ids,
|
||||
} => Some(Details::DocumentDeletion {
|
||||
received_document_ids: documents_ids.len(),
|
||||
deleted_documents: None,
|
||||
}),
|
||||
KindWithContent::DocumentClear { .. } => Some(Details::ClearAll {
|
||||
deleted_documents: None,
|
||||
}),
|
||||
KindWithContent::Settings { new_settings, .. } => Some(Details::Settings {
|
||||
settings: new_settings.clone(),
|
||||
}),
|
||||
KindWithContent::IndexDeletion { .. } => None,
|
||||
KindWithContent::IndexCreation { primary_key, .. }
|
||||
| KindWithContent::IndexUpdate { primary_key, .. } => Some(Details::IndexInfo {
|
||||
primary_key: primary_key.clone(),
|
||||
}),
|
||||
KindWithContent::IndexSwap { .. } => {
|
||||
todo!()
|
||||
}
|
||||
KindWithContent::CancelTask { .. } => {
|
||||
None // TODO: check correctness of this return value
|
||||
}
|
||||
KindWithContent::DeleteTasks { query, tasks } => Some(Details::DeleteTasks {
|
||||
matched_tasks: tasks.len(),
|
||||
deleted_tasks: None,
|
||||
original_query: query.clone(),
|
||||
}),
|
||||
KindWithContent::DumpExport { .. } => None,
|
||||
KindWithContent::Snapshot => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
@ -123,15 +243,10 @@ impl FromStr for Status {
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum Kind {
|
||||
DocumentImport {
|
||||
method: IndexDocumentsMethod,
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
DocumentImport,
|
||||
DocumentDeletion,
|
||||
DocumentClear,
|
||||
Settings {
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
Settings,
|
||||
IndexCreation,
|
||||
IndexDeletion,
|
||||
IndexUpdate,
|
||||
|
@ -147,22 +262,11 @@ impl FromStr for Kind {
|
|||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"document_addition" => Ok(Kind::DocumentImport {
|
||||
method: IndexDocumentsMethod::ReplaceDocuments,
|
||||
// TODO this doesn't make sense
|
||||
allow_index_creation: false,
|
||||
}),
|
||||
"document_update" => Ok(Kind::DocumentImport {
|
||||
method: IndexDocumentsMethod::UpdateDocuments,
|
||||
// TODO this doesn't make sense
|
||||
allow_index_creation: false,
|
||||
}),
|
||||
"document_addition" => Ok(Kind::DocumentImport),
|
||||
"document_update" => Ok(Kind::DocumentImport),
|
||||
"document_deletion" => Ok(Kind::DocumentDeletion),
|
||||
"document_clear" => Ok(Kind::DocumentClear),
|
||||
"settings" => Ok(Kind::Settings {
|
||||
// TODO this doesn't make sense
|
||||
allow_index_creation: false,
|
||||
}),
|
||||
"settings" => Ok(Kind::Settings),
|
||||
"index_creation" => Ok(Kind::IndexCreation),
|
||||
"index_deletion" => Ok(Kind::IndexDeletion),
|
||||
"index_update" => Ok(Kind::IndexUpdate),
|
||||
|
@ -179,73 +283,6 @@ impl FromStr for Kind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DetailsView {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub received_documents: Option<u64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub indexed_documents: Option<u64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub primary_key: Option<Option<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub received_document_ids: Option<usize>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub deleted_documents: Option<Option<u64>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub matched_tasks: Option<usize>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub deleted_tasks: Option<Option<usize>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub original_query: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub dump_uid: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(flatten)]
|
||||
pub settings: Option<Settings<Unchecked>>,
|
||||
}
|
||||
|
||||
// A `Kind` specific version made for the dump. If modified you may break the dump.
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum KindDump {
|
||||
DocumentImport {
|
||||
primary_key: Option<String>,
|
||||
method: IndexDocumentsMethod,
|
||||
documents_count: u64,
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
DocumentDeletion {
|
||||
documents_ids: Vec<String>,
|
||||
},
|
||||
DocumentClear,
|
||||
Settings {
|
||||
new_settings: Settings<Unchecked>,
|
||||
is_deletion: bool,
|
||||
allow_index_creation: bool,
|
||||
},
|
||||
IndexDeletion,
|
||||
IndexCreation {
|
||||
primary_key: Option<String>,
|
||||
},
|
||||
IndexUpdate {
|
||||
primary_key: Option<String>,
|
||||
},
|
||||
IndexSwap {
|
||||
lhs: String,
|
||||
rhs: String,
|
||||
},
|
||||
CancelTask {
|
||||
tasks: Vec<TaskId>,
|
||||
},
|
||||
DeleteTasks {
|
||||
query: String,
|
||||
tasks: Vec<TaskId>,
|
||||
},
|
||||
DumpExport,
|
||||
Snapshot,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Details {
|
||||
|
@ -277,59 +314,10 @@ pub enum Details {
|
|||
},
|
||||
}
|
||||
|
||||
impl Details {
|
||||
pub fn as_details_view(&self) -> DetailsView {
|
||||
match self.clone() {
|
||||
Details::DocumentAddition {
|
||||
received_documents,
|
||||
indexed_documents,
|
||||
} => DetailsView {
|
||||
received_documents: Some(received_documents),
|
||||
indexed_documents: Some(indexed_documents),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::Settings { settings } => DetailsView {
|
||||
settings: Some(settings),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::IndexInfo { primary_key } => DetailsView {
|
||||
primary_key: Some(primary_key),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::DocumentDeletion {
|
||||
received_document_ids,
|
||||
deleted_documents,
|
||||
} => DetailsView {
|
||||
received_document_ids: Some(received_document_ids),
|
||||
deleted_documents: Some(deleted_documents),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::ClearAll { deleted_documents } => DetailsView {
|
||||
deleted_documents: Some(deleted_documents),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::DeleteTasks {
|
||||
matched_tasks,
|
||||
deleted_tasks,
|
||||
original_query,
|
||||
} => DetailsView {
|
||||
matched_tasks: Some(matched_tasks),
|
||||
deleted_tasks: Some(deleted_tasks),
|
||||
original_query: Some(original_query),
|
||||
..DetailsView::default()
|
||||
},
|
||||
Details::Dump { dump_uid } => DetailsView {
|
||||
dump_uid: Some(dump_uid),
|
||||
..DetailsView::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
fn serialize_duration<S: Serializer>(
|
||||
pub fn serialize_duration<S: Serializer>(
|
||||
duration: &Option<Duration>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
|
@ -376,3 +364,26 @@ fn serialize_duration<S: Serializer>(
|
|||
None => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assert_smol_debug_snapshot;
|
||||
use crate::heed::{types::SerdeJson, BytesDecode, BytesEncode};
|
||||
|
||||
use super::Details;
|
||||
|
||||
#[test]
|
||||
fn bad_deser() {
|
||||
let details = Details::DeleteTasks {
|
||||
matched_tasks: 1,
|
||||
deleted_tasks: None,
|
||||
original_query: "hello".to_owned(),
|
||||
};
|
||||
let serialised = SerdeJson::<Details>::bytes_encode(&details).unwrap();
|
||||
let deserialised = SerdeJson::<Details>::bytes_decode(&serialised).unwrap();
|
||||
assert_smol_debug_snapshot!(details, @r###"DeleteTasks { matched_tasks: 1, deleted_tasks: None, original_query: "hello" }"###);
|
||||
assert_smol_debug_snapshot!(deserialised, @r###"DeleteTasks { matched_tasks: 1, deleted_tasks: None, original_query: "hello" }"###);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue