Skip to content

Commit

Permalink
Prepare release v0.14.0 "Hakuna Matata" 🐗 🦁 (#3594)
Browse files Browse the repository at this point in the history
  • Loading branch information
LesnyRumcajs authored Oct 16, 2023
1 parent de94867 commit 43b417b
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 23 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@

### Added

### Changed

### Removed

### Fixed

## Forest v0.14.0 "Hakuna Matata"

### Breaking

### Added

- [#3422](https://github.com/ChainSafe/forest/issues/3422) Add NV21 (Watermelon)
support for calibration network.

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "forest-filecoin"
version = "0.13.0"
version = "0.14.0"
authors = ["ChainSafe Systems <[email protected]>"]
repository = "https://github.com/ChainSafe/forest"
edition = "2021"
Expand Down
62 changes: 50 additions & 12 deletions src/db/migration/migration_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ use semver::Version;
use tracing::info;

use super::v0_12_1::Migration0_12_1_0_13_0;
use super::void_migration::MigrationVoid;

/// Migration trait. It is expected that the [`MigrationOperation::migrate`] method will pick up the relevant database
/// existing under `chain_data_path` and create a new migration database in the same directory.
pub(super) trait MigrationOperation {
fn new(from: Version, to: Version) -> Self
where
Self: Sized;
/// Performs pre-migration checks. This is the place to check if the database is in a valid
/// state and if the migration can be performed. Note that some of the higher-level checks
/// (like checking if the database exists) are performed by the [`Migration`].
Expand All @@ -32,6 +36,8 @@ pub(super) trait MigrationOperation {
/// Performs post-migration checks. This is the place to check if the migration database is
/// ready to be used by Forest and renamed into a versioned database.
fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()>;
/// Returns the name of the temporary database that will be created during the migration.
fn temporary_db_name(&self) -> String;
}

/// Migrations map. The key is the starting version and the value is the tuple of the target version
Expand All @@ -48,15 +54,18 @@ type MigrationsMap = MultiMap<Version, (Version, Migrator)>;
/// The usage is:
/// `<FROM version> -> <TO version> @ <Migrator object>`
macro_rules! create_migrations {
($($from:literal -> $to:literal @ $migration:path),* $(,)?) => {
($($from:literal -> $to:literal @ $migration:tt),* $(,)?) => {
pub(super) static MIGRATIONS: Lazy<MigrationsMap> = Lazy::new(|| {
MigrationsMap::from_iter(
[
$((
Version::from_str($from).unwrap(),
(
Version::from_str($to).unwrap(),
Arc::new($migration) as _,
Arc::new($migration::new(
$from.parse().expect("invalid <from> version"),
$to.parse().expect("invalid <to> version")))
as _,
)),
)*
]
Expand All @@ -68,6 +77,7 @@ pub(super) static MIGRATIONS: Lazy<MigrationsMap> = Lazy::new(|| {

create_migrations!(
"0.12.1" -> "0.13.0" @ Migration0_12_1_0_13_0,
"0.13.0" -> "0.14.0" @ MigrationVoid,
);

pub struct Migration {
Expand Down Expand Up @@ -259,6 +269,17 @@ mod tests {
fn post_checks(&self, _chain_data_path: &Path) -> anyhow::Result<()> {
Ok(())
}

fn new(_from: Version, _to: Version) -> Self
where
Self: Sized,
{
Self {}
}

fn temporary_db_name(&self) -> String {
"".into()
}
}

#[test]
Expand Down Expand Up @@ -385,37 +406,54 @@ mod tests {
}
}

struct SimpleMigration0_1_0_0_2_0;
struct SimpleMigration0_1_0_0_2_0 {
from: Version,
to: Version,
}

impl MigrationOperation for SimpleMigration0_1_0_0_2_0 {
fn pre_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
let path = chain_data_path.join("0.1.0");
let path = chain_data_path.join(self.from.to_string());
if !path.exists() {
anyhow::bail!("0.1.0 does not exist");
anyhow::bail!("{} does not exist", self.from);
}
Ok(())
}

fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
fs::create_dir(chain_data_path.join("migration_0_1_0_0_2_0")).unwrap();
Ok(chain_data_path.join("migration_0_1_0_0_2_0"))
let temp_db_path = chain_data_path.join(self.temporary_db_name());
fs::create_dir(&temp_db_path).unwrap();
Ok(temp_db_path)
}

fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
let path = chain_data_path.join("migration_0_1_0_0_2_0");
let path = chain_data_path.join(self.temporary_db_name());
if !path.exists() {
anyhow::bail!("migration_0_1_0_0_2_0 does not exist");
anyhow::bail!("{} does not exist", path.display());
}
Ok(())
}

fn new(from: Version, to: Version) -> Self
where
Self: Sized,
{
Self { from, to }
}

fn temporary_db_name(&self) -> String {
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
}
}

#[test]
fn test_migration_map_migration() {
let from = Version::new(0, 1, 0);
let to = Version::new(0, 2, 0);
let migration = Migration {
from: Version::new(0, 1, 0),
to: Version::new(0, 2, 0),
migrator: Arc::new(SimpleMigration0_1_0_0_2_0),
from: from.clone(),
to: to.clone(),
migrator: Arc::new(SimpleMigration0_1_0_0_2_0::new(from, to)),
};

let temp_dir = TempDir::new().unwrap();
Expand Down
1 change: 1 addition & 0 deletions src/db/migration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
mod db_migration;
mod migration_map;
mod v0_12_1;
mod void_migration;

pub use db_migration::DbMigration;
30 changes: 21 additions & 9 deletions src/db/migration/v0_12_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
//! coming from the rolling database and ParityDb.

use fs_extra::dir::CopyOptions;
use semver::Version;
use std::path::{Path, PathBuf};
use tracing::info;

use super::migration_map::MigrationOperation;

#[derive(Default)]
pub(super) struct Migration0_12_1_0_13_0;

/// Temporary database path for the migration.
const MIGRATION_DB_0_12_1_0_13_0: &str = "migration_0_12_1_to_0_13_0";
pub(super) struct Migration0_12_1_0_13_0 {
from: Version,
to: Version,
}

/// Migrates the database from version 0.12.1 to 0.13.0
/// This migration is needed because the `Settings` column in the `ParityDb` table changed to
Expand All @@ -29,9 +29,9 @@ impl MigrationOperation for Migration0_12_1_0_13_0 {
}

fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
let source_db = chain_data_path.join("0.12.1");
let source_db = chain_data_path.join(self.from.to_string());

let temp_db_path = chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0);
let temp_db_path = chain_data_path.join(self.temporary_db_name());
if temp_db_path.exists() {
info!(
"removing old temporary database {temp_db_path}",
Expand Down Expand Up @@ -137,14 +137,26 @@ impl MigrationOperation for Migration0_12_1_0_13_0 {
}

fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
if !chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0).exists() {
let temp_db_name = self.temporary_db_name();
if !chain_data_path.join(&temp_db_name).exists() {
anyhow::bail!(
"migration database {} does not exist",
chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0).display()
chain_data_path.join(temp_db_name).display()
);
}
Ok(())
}

fn new(from: Version, to: Version) -> Self
where
Self: Sized,
{
Self { from, to }
}

fn temporary_db_name(&self) -> String {
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
}
}

/// Database settings from Forest `v0.12.1`
Expand Down
107 changes: 107 additions & 0 deletions src/db/migration/void_migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2019-2023 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

//! Migration logic from any version that requires no migration logic.

use fs_extra::dir::CopyOptions;
use semver::Version;
use std::path::{Path, PathBuf};
use tracing::info;

use super::migration_map::MigrationOperation;

pub(super) struct MigrationVoid {
from: Version,
to: Version,
}

impl MigrationOperation for MigrationVoid {
fn pre_checks(&self, _chain_data_path: &Path) -> anyhow::Result<()> {
Ok(())
}

fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
let source_db = chain_data_path.join(self.from.to_string());

let temp_db_path = chain_data_path.join(self.temporary_db_name());
if temp_db_path.exists() {
info!(
"removing old temporary database {temp_db_path}",
temp_db_path = temp_db_path.display()
);
std::fs::remove_dir_all(&temp_db_path)?;
}

info!(
"copying old database from {source_db} to {temp_db_path}",
source_db = source_db.display(),
temp_db_path = temp_db_path.display()
);
fs_extra::copy_items(
&[source_db.as_path()],
temp_db_path.clone(),
&CopyOptions::default().copy_inside(true),
)?;

Ok(temp_db_path)
}

fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
let temp_db_name = self.temporary_db_name();
if !chain_data_path.join(&temp_db_name).exists() {
anyhow::bail!(
"migration database {} does not exist",
chain_data_path.join(temp_db_name).display()
);
}
Ok(())
}

fn new(from: Version, to: Version) -> Self
where
Self: Sized,
{
Self { from, to }
}

fn temporary_db_name(&self) -> String {
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
}
}

#[cfg(test)]
mod test {
use super::*;
use semver::Version;
use tempfile::TempDir;

#[test]
fn test_migration_void() {
let migration = MigrationVoid::new(Version::new(1, 0, 0), Version::new(1, 0, 1));
let chain_data_path = TempDir::new().unwrap();

// create a file in the temporary database directory, under a directory (to ensure that the
// directory is copied recursively).
let content_dir = chain_data_path.path().join("1.0.0").join("R'lyeh");
std::fs::create_dir_all(&content_dir).unwrap();

let content_file = content_dir.join("cthulhu");
let chant = "ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn";
std::fs::write(content_file, chant).unwrap();

let path = chain_data_path.path();
migration.pre_checks(path).unwrap();
let temp_db_path = migration.migrate(path).unwrap();
migration.post_checks(path).unwrap();

// check that the temporary database directory exists and contains the file with the
// expected content.
let temp_db_content_dir = temp_db_path.join("R'lyeh");
let temp_db_content_file = temp_db_content_dir.join("cthulhu");
assert!(temp_db_content_file.exists());
assert_eq!(
std::fs::read_to_string(temp_db_content_file).unwrap(),
chant
);
}
}

0 comments on commit 43b417b

Please sign in to comment.