implements the batch details

This commit is contained in:
Tamo 2024-11-19 17:06:00 +01:00
parent 5d10c2312b
commit 229fa0f902
No known key found for this signature in database
GPG key ID: 20CD8020AFA88D69
110 changed files with 493 additions and 275 deletions

View file

@ -3,6 +3,7 @@ use time::{Duration, OffsetDateTime};
use crate::{
batches::{Batch, BatchId},
task_view::DetailsView,
tasks::serialize_duration,
};
@ -10,6 +11,7 @@ use crate::{
#[serde(rename_all = "camelCase")]
pub struct BatchView {
pub uid: BatchId,
pub details: DetailsView,
#[serde(serialize_with = "serialize_duration", default)]
pub duration: Option<Duration>,
#[serde(with = "time::serde::rfc3339", default)]
@ -22,6 +24,7 @@ impl BatchView {
pub fn from_batch(batch: &Batch) -> Self {
Self {
uid: batch.uid,
details: batch.details.clone(),
duration: batch.finished_at.map(|finished_at| finished_at - batch.started_at),
started_at: batch.started_at,
finished_at: batch.finished_at,

View file

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::task_view::DetailsView;
pub type BatchId = u32;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -8,6 +10,8 @@ pub type BatchId = u32;
pub struct Batch {
pub uid: BatchId,
pub details: DetailsView,
#[serde(with = "time::serde::rfc3339")]
pub started_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339::option")]

View file

@ -378,6 +378,64 @@ impl Settings<Unchecked> {
self.embedders = Setting::Set(configs);
Ok(self)
}
pub fn merge(&mut self, other: &Self) {
// For most settings only the latest version is kept
*self = Self {
displayed_attributes: other
.displayed_attributes
.clone()
.or(self.displayed_attributes.clone()),
searchable_attributes: other
.searchable_attributes
.clone()
.or(self.searchable_attributes.clone()),
filterable_attributes: other
.filterable_attributes
.clone()
.or(self.filterable_attributes.clone()),
sortable_attributes: other
.sortable_attributes
.clone()
.or(self.sortable_attributes.clone()),
ranking_rules: other.ranking_rules.clone().or(self.ranking_rules.clone()),
stop_words: other.stop_words.clone().or(self.stop_words.clone()),
non_separator_tokens: other
.non_separator_tokens
.clone()
.or(self.non_separator_tokens.clone()),
separator_tokens: other.separator_tokens.clone().or(self.separator_tokens.clone()),
dictionary: other.dictionary.clone().or(self.dictionary.clone()),
synonyms: other.synonyms.clone().or(self.synonyms.clone()),
distinct_attribute: other
.distinct_attribute
.clone()
.or(self.distinct_attribute.clone()),
proximity_precision: other.proximity_precision.or(self.proximity_precision),
typo_tolerance: other.typo_tolerance.clone().or(self.typo_tolerance.clone()),
faceting: other.faceting.clone().or(self.faceting.clone()),
pagination: other.pagination.clone().or(self.pagination.clone()),
search_cutoff_ms: other.search_cutoff_ms.or(self.search_cutoff_ms),
localized_attributes: other
.localized_attributes
.clone()
.or(self.localized_attributes.clone()),
embedders: match (self.embedders.clone(), other.embedders.clone()) {
(Setting::NotSet, set) | (set, Setting::NotSet) => set,
(Setting::Set(_) | Setting::Reset, Setting::Reset) => Setting::Reset,
(Setting::Reset, Setting::Set(embedder)) => Setting::Set(embedder),
// If both are set we must merge the embeddings settings
(Setting::Set(mut this), Setting::Set(other)) => {
for (k, v) in other {
this.insert(k, v);
}
Setting::Set(this)
}
},
_kind: PhantomData,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -868,6 +926,12 @@ impl From<ProximityPrecisionView> for ProximityPrecision {
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq)]
pub struct WildcardSetting(Setting<Vec<String>>);
impl WildcardSetting {
pub fn or(self, other: Self) -> Self {
Self(self.0.or(other.0))
}
}
impl From<Setting<Vec<String>>> for WildcardSetting {
fn from(setting: Setting<Vec<String>>) -> Self {
Self(setting)

View file

@ -1,5 +1,5 @@
use milli::Object;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use time::{Duration, OffsetDateTime};
use crate::batches::BatchId;
@ -50,7 +50,7 @@ impl TaskView {
}
}
#[derive(Default, Debug, PartialEq, Eq, Clone, Serialize)]
#[derive(Default, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DetailsView {
#[serde(skip_serializing_if = "Option::is_none")]
@ -86,6 +86,128 @@ pub struct DetailsView {
pub swaps: Option<Vec<IndexSwap>>,
}
impl DetailsView {
pub fn accumulate(&mut self, other: &Self) {
*self = Self {
received_documents: match (self.received_documents, other.received_documents) {
(None, None) => None,
(None, Some(doc)) | (Some(doc), None) => Some(doc),
(Some(left), Some(right)) => Some(left + right),
},
indexed_documents: match (self.indexed_documents, other.indexed_documents) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(doc))) | (Some(Some(doc)), None | Some(None)) => {
Some(Some(doc))
}
(Some(Some(left)), Some(Some(right))) => Some(Some(left + right)),
},
edited_documents: match (self.edited_documents, other.edited_documents) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(doc))) | (Some(Some(doc)), None | Some(None)) => {
Some(Some(doc))
}
(Some(Some(left)), Some(Some(right))) => Some(Some(left + right)),
},
primary_key: match (&self.primary_key, &other.primary_key) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(doc))) | (Some(Some(doc)), None | Some(None)) => {
Some(Some(doc.to_string()))
}
// In the case we receive multiple primary keys (which shouldn't happens) we only return the first one encountered.
(Some(Some(left)), Some(Some(_right))) => Some(Some(left.to_string())),
},
provided_ids: match (self.provided_ids, other.provided_ids) {
(None, None) => None,
(None, Some(ids)) | (Some(ids), None) => Some(ids),
(Some(left), Some(right)) => Some(left + right),
},
deleted_documents: match (self.deleted_documents, other.deleted_documents) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(doc))) | (Some(Some(doc)), None | Some(None)) => {
Some(Some(doc))
}
(Some(Some(left)), Some(Some(right))) => Some(Some(left + right)),
},
matched_tasks: match (self.matched_tasks, other.matched_tasks) {
(None, None) => None,
(None, Some(task)) | (Some(task), None) => Some(task),
(Some(left), Some(right)) => Some(left + right),
},
canceled_tasks: match (self.canceled_tasks, other.canceled_tasks) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(task))) | (Some(Some(task)), None | Some(None)) => {
Some(Some(task))
}
(Some(Some(left)), Some(Some(right))) => Some(Some(left + right)),
},
deleted_tasks: match (self.deleted_tasks, other.deleted_tasks) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(task))) | (Some(Some(task)), None | Some(None)) => {
Some(Some(task))
}
(Some(Some(left)), Some(Some(right))) => Some(Some(left + right)),
},
original_filter: match (&self.original_filter, &other.original_filter) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(filter)))
| (Some(Some(filter)), None | Some(None)) => Some(Some(filter.to_string())),
// In this case, we cannot really merge both filters or return an array so we're going to return
// all the conditions one after the other.
(Some(Some(left)), Some(Some(right))) => Some(Some(format!("{left}&{right}"))),
},
dump_uid: match (&self.dump_uid, &other.dump_uid) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(dump_uid)))
| (Some(Some(dump_uid)), None | Some(None)) => Some(Some(dump_uid.to_string())),
// We should never be able to batch multiple dumps at the same time. So we return
// the first one we encounter but that shouldn't be an issue anyway.
(Some(Some(left)), Some(Some(_right))) => Some(Some(left.to_string())),
},
context: match (&self.context, &other.context) {
(None, None) => None,
(None, Some(None)) | (Some(None), None) | (Some(None), Some(None)) => Some(None),
(None | Some(None), Some(Some(ctx))) | (Some(Some(ctx)), None | Some(None)) => {
Some(Some(ctx.clone()))
}
// We should never be able to batch multiple documents edited at the same time. So we return
// the first one we encounter but that shouldn't be an issue anyway.
(Some(Some(left)), Some(Some(_right))) => Some(Some(left.clone())),
},
function: match (&self.function, &other.function) {
(None, None) => None,
(None, Some(fun)) | (Some(fun), None) => Some(fun.to_string()),
// We should never be able to batch multiple documents edited at the same time. So we return
// the first one we encounter but that shouldn't be an issue anyway.
(Some(left), Some(_right)) => Some(left.to_string()),
},
settings: match (self.settings.clone(), other.settings.clone()) {
(None, None) => None,
(None, Some(settings)) | (Some(settings), None) => Some(settings),
(Some(mut left), Some(right)) => {
left.merge(&right);
Some(left)
}
},
swaps: match (self.swaps.clone(), other.swaps.clone()) {
(None, None) => None,
(None, Some(swaps)) | (Some(swaps), None) => Some(swaps),
(Some(mut left), Some(mut right)) => {
left.append(&mut right);
Some(left)
}
},
}
}
}
impl From<Details> for DetailsView {
fn from(details: Details) -> Self {
match details {