introduce a trait to upgrade the indexes

This commit is contained in:
Tamo 2025-01-23 10:50:16 +01:00 committed by Louis Dureuil
parent fd5649091d
commit c27c923439
No known key found for this signature in database
4 changed files with 104 additions and 46 deletions

View File

@ -316,7 +316,10 @@ impl IndexScheduler {
Ok(vec![task]) Ok(vec![task])
} }
Batch::UpgradeDatabase { mut tasks } => { Batch::UpgradeDatabase { mut tasks } => {
let ret = catch_unwind(AssertUnwindSafe(|| self.process_upgrade(progress))); let KindWithContent::UpgradeDatabase { from } = tasks.last().unwrap().kind else {
unreachable!();
};
let ret = catch_unwind(AssertUnwindSafe(|| self.process_upgrade(from, progress)));
match ret { match ret {
Ok(Ok(())) => (), Ok(Ok(())) => (),
Ok(Err(e)) => return Err(Error::DatabaseUpgrade(Box::new(e))), Ok(Err(e)) => return Err(Error::DatabaseUpgrade(Box::new(e))),

View File

@ -4,7 +4,11 @@ use meilisearch_types::milli::progress::{Progress, VariableNameStep};
use crate::{Error, IndexScheduler, Result}; use crate::{Error, IndexScheduler, Result};
impl IndexScheduler { impl IndexScheduler {
pub(super) fn process_upgrade(&self, progress: Progress) -> Result<()> { pub(super) fn process_upgrade(
&self,
db_version: (u32, u32, u32),
progress: Progress,
) -> Result<()> {
#[cfg(test)] #[cfg(test)]
self.maybe_fail(crate::test_utils::FailureLocation::ProcessUpgrade)?; self.maybe_fail(crate::test_utils::FailureLocation::ProcessUpgrade)?;
@ -19,9 +23,13 @@ impl IndexScheduler {
)); ));
let index = self.index(uid)?; let index = self.index(uid)?;
let mut index_wtxn = index.write_txn()?; let mut index_wtxn = index.write_txn()?;
let regen_stats = let regen_stats = milli::update::upgrade::upgrade(
milli::update::upgrade::upgrade(&mut index_wtxn, &index, progress.clone()) &mut index_wtxn,
.map_err(|e| Error::from_milli(e, Some(uid.to_string())))?; &index,
db_version,
progress.clone(),
)
.map_err(|e| Error::from_milli(e, Some(uid.to_string())))?;
if regen_stats { if regen_stats {
let stats = crate::index_mapper::IndexStats::new(&index, &index_wtxn) let stats = crate::index_mapper::IndexStats::new(&index, &index_wtxn)
.map_err(|e| Error::from_milli(e, Some(uid.to_string())))?; .map_err(|e| Error::from_milli(e, Some(uid.to_string())))?;

View File

@ -1,32 +1,39 @@
mod v1_12; mod v1_12;
use heed::RwTxn; use heed::RwTxn;
use v1_12::{v1_12_3_to_v1_13, v1_12_to_v1_12_3}; use v1_12::{V1_12_3_To_Current, V1_12_To_V1_12_3};
use crate::progress::{Progress, VariableNameStep}; use crate::progress::{Progress, VariableNameStep};
use crate::{Index, InternalError, Result}; use crate::{Index, InternalError, Result};
trait UpgradeIndex {
/// Returns true if the index scheduler must regenerate its cached stats
fn upgrade(
&self,
wtxn: &mut RwTxn,
index: &Index,
original: (u32, u32, u32),
progress: Progress,
) -> Result<bool>;
fn target_version(&self) -> (u32, u32, u32);
}
/// Return true if the cached stats of the index must be regenerated /// Return true if the cached stats of the index must be regenerated
pub fn upgrade(wtxn: &mut RwTxn, index: &Index, progress: Progress) -> Result<bool> { pub fn upgrade(
let from = index.get_version(wtxn)?; wtxn: &mut RwTxn,
let upgrade_functions = [ index: &Index,
( db_version: (u32, u32, u32),
v1_12_to_v1_12_3 as fn(&mut RwTxn, &Index, Progress) -> Result<bool>, progress: Progress,
"Upgrading from v1.12.(0/1/2) to v1.12.3", ) -> Result<bool> {
), let from = index.get_version(wtxn)?.unwrap_or(db_version);
( let upgrade_functions: &[&dyn UpgradeIndex] = &[&V1_12_To_V1_12_3 {}, &V1_12_3_To_Current()];
v1_12_3_to_v1_13 as fn(&mut RwTxn, &Index, Progress) -> Result<bool>,
"Upgrading from v1.12.3+ to v1.13",
),
];
let start = match from { let start = match from {
// If there was no version it means we're coming from the v1.12 (1, 12, 0..=2) => 0,
None | Some((1, 12, 0..=2)) => 0, (1, 12, 3..) => 1,
Some((1, 12, 3..)) => 1,
// We must handle the current version in the match because in case of a failure some index may have been upgraded but not other. // We must handle the current version in the match because in case of a failure some index may have been upgraded but not other.
Some((1, 13, _)) => return Ok(false), (1, 13, _) => return Ok(false),
Some((major, minor, patch)) => { (major, minor, patch) => {
return Err(InternalError::CannotUpgradeToVersion(major, minor, patch).into()) return Err(InternalError::CannotUpgradeToVersion(major, minor, patch).into())
} }
}; };
@ -34,14 +41,26 @@ pub fn upgrade(wtxn: &mut RwTxn, index: &Index, progress: Progress) -> Result<bo
enum UpgradeVersion {} enum UpgradeVersion {}
let upgrade_path = &upgrade_functions[start..]; let upgrade_path = &upgrade_functions[start..];
let mut current_version = from;
let mut regenerate_stats = false; let mut regenerate_stats = false;
for (i, (upgrade_function, upgrade_msg)) in upgrade_path.iter().enumerate() { for (i, upgrade) in upgrade_path.iter().enumerate() {
let target = upgrade.target_version();
progress.update_progress(VariableNameStep::<UpgradeVersion>::new( progress.update_progress(VariableNameStep::<UpgradeVersion>::new(
upgrade_msg.to_string(), format!(
"Upgrading from v{}.{}.{} to v{}.{}.{}",
current_version.0,
current_version.1,
current_version.2,
target.0,
target.1,
target.2
),
i as u32, i as u32,
upgrade_path.len() as u32, upgrade_path.len() as u32,
)); ));
regenerate_stats |= (upgrade_function)(wtxn, index, progress.clone())?; regenerate_stats |= upgrade.upgrade(wtxn, index, from, progress.clone())?;
current_version = target;
} }
Ok(regenerate_stats) Ok(regenerate_stats)

View File

@ -1,28 +1,56 @@
use heed::RwTxn; use heed::RwTxn;
use crate::constants::{VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH};
use crate::progress::Progress; use crate::progress::Progress;
use crate::{make_enum_progress, Index, Result}; use crate::{make_enum_progress, Index, Result};
// The field distribution was not computed correctly in the v1.12 until the v1.12.3 use super::UpgradeIndex;
pub(super) fn v1_12_to_v1_12_3(
wtxn: &mut RwTxn, #[allow(non_camel_case_types)]
index: &Index, pub(super) struct V1_12_To_V1_12_3 {}
progress: Progress,
) -> Result<bool> { impl UpgradeIndex for V1_12_To_V1_12_3 {
make_enum_progress! { fn upgrade(
enum FieldDistribution { &self,
RebuildingFieldDistribution, wtxn: &mut RwTxn,
} index: &Index,
}; _original: (u32, u32, u32),
progress.update_progress(FieldDistribution::RebuildingFieldDistribution); progress: Progress,
crate::update::new::reindex::field_distribution(index, wtxn, &progress)?; ) -> Result<bool> {
Ok(true) make_enum_progress! {
enum FieldDistribution {
RebuildingFieldDistribution,
}
};
progress.update_progress(FieldDistribution::RebuildingFieldDistribution);
crate::update::new::reindex::field_distribution(index, wtxn, &progress)?;
Ok(true)
}
fn target_version(&self) -> (u32, u32, u32) {
(1, 12, 3)
}
} }
pub(super) fn v1_12_3_to_v1_13( #[allow(non_camel_case_types)]
_wtxn: &mut RwTxn, pub(super) struct V1_12_3_To_Current();
_index: &Index,
_progress: Progress, impl UpgradeIndex for V1_12_3_To_Current {
) -> Result<bool> { fn upgrade(
Ok(false) &self,
_wtxn: &mut RwTxn,
_index: &Index,
_original: (u32, u32, u32),
_progress: Progress,
) -> Result<bool> {
Ok(false)
}
fn target_version(&self) -> (u32, u32, u32) {
(
VERSION_MAJOR.parse().unwrap(),
VERSION_MINOR.parse().unwrap(),
VERSION_PATCH.parse().unwrap(),
)
}
} }