2024-11-04 17:55:55 +01:00
|
|
|
mod v1_10;
|
|
|
|
mod v1_11;
|
2024-12-10 15:12:50 +01:00
|
|
|
mod v1_12;
|
2024-11-04 17:55:55 +01:00
|
|
|
mod v1_9;
|
|
|
|
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
|
|
|
|
use anyhow::{bail, Context};
|
|
|
|
use meilisearch_types::versioning::create_version_file;
|
|
|
|
use v1_10::v1_9_to_v1_10;
|
2025-01-09 15:25:44 +01:00
|
|
|
use v1_12::{v1_11_to_v1_12, v1_12_to_v1_12_3};
|
2024-11-04 17:55:55 +01:00
|
|
|
|
|
|
|
use crate::upgrade::v1_11::v1_10_to_v1_11;
|
|
|
|
|
|
|
|
pub struct OfflineUpgrade {
|
|
|
|
pub db_path: PathBuf,
|
2025-01-16 12:56:23 +01:00
|
|
|
pub current_version: (u32, u32, u32),
|
|
|
|
pub target_version: (u32, u32, u32),
|
2024-11-04 17:55:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OfflineUpgrade {
|
|
|
|
pub fn upgrade(self) -> anyhow::Result<()> {
|
2025-01-20 10:32:20 +01:00
|
|
|
// Adding a version?
|
|
|
|
//
|
|
|
|
// 1. Update the LAST_SUPPORTED_UPGRADE_FROM_VERSION and LAST_SUPPORTED_UPGRADE_TO_VERSION.
|
|
|
|
// 2. Add new version to the upgrade list if necessary
|
|
|
|
// 3. Use `no_upgrade` as index for versions that are compatible.
|
|
|
|
|
|
|
|
if self.current_version == self.target_version {
|
|
|
|
println!("Database is already at the target version. Exiting.");
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.current_version > self.target_version {
|
|
|
|
bail!(
|
|
|
|
"Cannot downgrade from {}.{}.{} to {}.{}.{}. Downgrade not supported",
|
|
|
|
self.current_version.0,
|
|
|
|
self.current_version.1,
|
|
|
|
self.current_version.2,
|
|
|
|
self.target_version.0,
|
|
|
|
self.target_version.1,
|
|
|
|
self.target_version.2
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const FIRST_SUPPORTED_UPGRADE_FROM_VERSION: &str = "1.9.0";
|
2025-01-23 11:11:20 +01:00
|
|
|
const LAST_SUPPORTED_UPGRADE_FROM_VERSION: &str = "1.12.7";
|
2025-01-20 10:32:20 +01:00
|
|
|
const FIRST_SUPPORTED_UPGRADE_TO_VERSION: &str = "1.10.0";
|
2025-01-23 11:11:20 +01:00
|
|
|
const LAST_SUPPORTED_UPGRADE_TO_VERSION: &str = "1.12.7";
|
2025-01-20 10:32:20 +01:00
|
|
|
|
2024-11-04 17:55:55 +01:00
|
|
|
let upgrade_list = [
|
2025-01-13 09:31:27 +01:00
|
|
|
(
|
2025-01-16 12:56:23 +01:00
|
|
|
v1_9_to_v1_10 as fn(&Path, u32, u32, u32) -> Result<(), anyhow::Error>,
|
2025-01-13 09:31:27 +01:00
|
|
|
"1",
|
|
|
|
"10",
|
|
|
|
"0",
|
|
|
|
),
|
2024-11-04 17:55:55 +01:00
|
|
|
(v1_10_to_v1_11, "1", "11", "0"),
|
2024-12-10 15:12:50 +01:00
|
|
|
(v1_11_to_v1_12, "1", "12", "0"),
|
2025-01-09 15:25:44 +01:00
|
|
|
(v1_12_to_v1_12_3, "1", "12", "3"),
|
2024-11-04 17:55:55 +01:00
|
|
|
];
|
|
|
|
|
2025-01-20 10:32:20 +01:00
|
|
|
let no_upgrade: usize = upgrade_list.len();
|
|
|
|
|
2025-01-16 12:56:23 +01:00
|
|
|
let (current_major, current_minor, current_patch) = self.current_version;
|
|
|
|
|
|
|
|
let start_at = match (current_major, current_minor, current_patch) {
|
|
|
|
(1, 9, _) => 0,
|
|
|
|
(1, 10, _) => 1,
|
|
|
|
(1, 11, _) => 2,
|
2025-01-23 16:59:23 +01:00
|
|
|
(1, 12, 0..=2) => 3,
|
2025-01-23 11:11:20 +01:00
|
|
|
(1, 12, 3..=7) => no_upgrade,
|
2024-11-04 17:55:55 +01:00
|
|
|
_ => {
|
2025-01-20 10:32:20 +01:00
|
|
|
bail!("Unsupported current version {current_major}.{current_minor}.{current_patch}. Can only upgrade from versions in range [{}-{}]",
|
|
|
|
FIRST_SUPPORTED_UPGRADE_FROM_VERSION,
|
|
|
|
LAST_SUPPORTED_UPGRADE_FROM_VERSION);
|
2024-11-04 17:55:55 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-01-16 12:56:23 +01:00
|
|
|
let (target_major, target_minor, target_patch) = self.target_version;
|
2024-11-04 17:55:55 +01:00
|
|
|
|
2025-01-16 12:56:23 +01:00
|
|
|
let ends_at = match (target_major, target_minor, target_patch) {
|
|
|
|
(1, 10, _) => 0,
|
|
|
|
(1, 11, _) => 1,
|
2025-01-23 11:11:20 +01:00
|
|
|
(1, 12, 0..=2) => 2,
|
|
|
|
(1, 12, 3..=7) => 3,
|
2024-11-04 17:55:55 +01:00
|
|
|
_ => {
|
2025-01-20 10:32:20 +01:00
|
|
|
bail!("Unsupported target version {target_major}.{target_minor}.{target_patch}. Can only upgrade to versions in range [{}-{}]",
|
|
|
|
FIRST_SUPPORTED_UPGRADE_TO_VERSION,
|
|
|
|
LAST_SUPPORTED_UPGRADE_TO_VERSION);
|
2024-11-04 17:55:55 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
println!("Starting the upgrade from {current_major}.{current_minor}.{current_patch} to {target_major}.{target_minor}.{target_patch}");
|
|
|
|
|
2025-01-20 10:32:20 +01:00
|
|
|
if start_at == no_upgrade {
|
|
|
|
println!("No upgrade operation to perform, writing VERSION file");
|
2025-01-23 16:59:23 +01:00
|
|
|
create_version_file(
|
|
|
|
&self.db_path,
|
|
|
|
&target_major.to_string(),
|
|
|
|
&target_minor.to_string(),
|
|
|
|
&target_patch.to_string(),
|
|
|
|
)
|
|
|
|
.context("while writing VERSION file after the upgrade")?;
|
2025-01-20 10:32:20 +01:00
|
|
|
println!("Success");
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2024-11-04 17:55:55 +01:00
|
|
|
#[allow(clippy::needless_range_loop)]
|
|
|
|
for index in start_at..=ends_at {
|
|
|
|
let (func, major, minor, patch) = upgrade_list[index];
|
2025-01-13 09:31:27 +01:00
|
|
|
(func)(&self.db_path, current_major, current_minor, current_patch)?;
|
2024-11-04 17:55:55 +01:00
|
|
|
println!("Done");
|
|
|
|
// We're writing the version file just in case an issue arise _while_ upgrading.
|
|
|
|
// We don't want the DB to fail in an unknown state.
|
|
|
|
println!("Writing VERSION file");
|
|
|
|
|
|
|
|
create_version_file(&self.db_path, major, minor, patch)
|
|
|
|
.context("while writing VERSION file after the upgrade")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("Success");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|