[][src]Struct exonum::runtime::migrations::LinearMigrations

pub struct LinearMigrations { /* fields omitted */ }

Linearly ordered migrations.

This type allows to construct a MigrateData implementation that will follow migrations performed during service evolution. In this way, the mechanism is similar to how migrations are implemented in apps involving relational databases:

  • Migration scripts will be applied to service data in a specific order during evolution of a particular service instance. Each script will be applied exactly once.
  • Several migration scripts may be applied sequentially if the instance is old enough.
  • Migrations for different service instances are independent, and migration scripts for them are fully reusable.

Retaining Old Data Types

Migration script logic needs retain the knowledge about data types used in the service in the past. Since these data types may be unused currently, retaining them may place a burden on the service. To mitigate this, you can provide a minimum supported starting version of the service via set_min_version.

Pre-releases

Special care must be taken to support pre-release versions (i.e., versions like 0.2.0-pre.2 or 1.2.34-rc.5). As per the semver specification:

  • Any pre-release version is lesser than a corresponding version without a pre-release suffix
  • Pre-release versions with the same base triple are ordered alphabetically by their suffixes

The support of prerelease versions needs to be explicitly enabled by using the with_prereleases constructor. Otherwise, a prerelease mentioned in the builder stage will lead to a panic, and select will return an error if a prerelease is specified as a start_version.

Examples

Consider the following hypothetical evolution of a crypto-token service:

VersionMigration
0.2.0#1: Split name in user accounts into first_name and last_name
0.3.0-
0.4.0#2: Consolidate token metadata into a single Entry
0.4.1-
0.4.2#3: Compute total number of tokens and add it to metadata

In this case:

  • If a service instance is migrated from version 0.1.0 to the newest version 0.4.2, all three scripts need to be executed.
  • If an instance is migrated from 0.2.0 or 0.3.0, only scripts #2 and #3 need to be executed.
  • If an instance is migrated from 0.4.0 or 0.4.1, only script #3 needs to be executed.
  • If the instance version is 0.4.2, no scripts need to be executed.

The migrations can be described in the service code as follows:

fn split_account_name(ctx: &mut MigrationContext) -> Result<(), MigrationError> {
    // script logic...
}

fn consolidate_metadata(ctx: &mut MigrationContext) -> Result<(), MigrationError> {
    // script logic...
}

fn compute_total_tokens(ctx: &mut MigrationContext) -> Result<(), MigrationError> {
    // script logic...
}

fn migrations() -> LinearMigrations {
    LinearMigrations::new(Version::new(0, 4, 3))
        .add_script(Version::new(0, 2, 0), split_account_name)
        .add_script(Version::new(0, 4, 0), consolidate_metadata)
        .add_script(Version::new(0, 4, 2), compute_total_tokens)
}

/// Service with migrations.
pub struct TokenService;

impl MigrateData for TokenService {
    fn migration_scripts(
        &self,
        start_version: &Version,
    ) -> Result<Vec<MigrationScript>, InitMigrationError> {
        migrations().select(start_version)
    }
}

// Check that the migration scripts are selected properly.
let scripts = TokenService.migration_scripts(&Version::new(0, 3, 0))?;
assert_eq!(scripts.len(), 2);
assert_eq!(*scripts[0].end_version(), Version::new(0, 4, 0));

Methods

impl LinearMigrations[src]

pub fn new(latest_version: Version) -> Self[src]

Creates a new set of migrations with the specified latest supported version.

Panics

  • If latest_version is a prerelease.

pub fn with_prereleases(latest_version: Version) -> Self[src]

Creates a new set of migrations with the specified latest supported version.

Unlike the new constructor, this one indicates that prerelease versions are allowed in the list of migrations and as the start version.

pub fn set_min_version(self, version: Version) -> Self[src]

Signals to return an error if the starting version is less than the specified version.

Panics

  • If version is a prerelease and this instance was not created by the with_prereleases constructor.

pub fn add_script<F>(self, version: Version, script: F) -> Self where
    F: FnOnce(&mut MigrationContext) -> Result<(), MigrationError> + Send + 'static, 
[src]

Adds a migration script at the specified version.

Panics

  • If version is a prerelease and this instance was not created by the with_prereleases constructor.

pub fn select(
    self,
    start_version: &Version
) -> Result<Vec<MigrationScript>, InitMigrationError>
[src]

Selects a list of migration scripts based on the provided start version of the artifact.

Trait Implementations

impl Debug for LinearMigrations[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,