Skip to main content

migrate

Attribute Macro migrate 

Source
#[migrate]
Expand description

Transforms a function into a migration step between two state versions.

The macro derives source and target types from the function signature:

  • from: the type of the first argument
  • to: the inner type of Result<T> return type

The function name becomes the migration step description in the registry.

§Attributes

  • #[rename(old_field => new_field)] — declares a field rename. Can be stacked. Generates a compile-time check that both fields exist on the respective types.

§Examples

Simple rename, no context:

mod v1 {
    #[amethystate(prefix = "app", version = 1)]
    pub struct Config {
        #[amestate(default = "localhost".to_string())]
        pub host: String,
        #[amestate(default = 8080)]
        pub port: u16,
    }
}

#[amethystate(prefix = "app", version = 2)]
pub struct Config {
    #[amestate(default = "localhost".to_string())]
    pub address: String,
    #[amestate(default = 8080)]
    pub port: u16,
}

#[migrate]
#[rename(host => address)]
fn migrate_config_v1_to_v2(old: AmeData<v1::Config>) -> amethystate::Result<AmeData<Config>> {
    Ok(AmeData::<Config> { address: old.host, port: old.port })
}

Manual key cleanup via MigrationContext:

#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, AmeType)]
pub struct ProxyEndpoint {
    pub url: String,
    pub timeout_ms: u32,
}

mod v1 {
    #[amethystate(prefix = "network", version = 1)]
    pub struct ProxyConfig {
        #[amestate(default = "default".into())]
        pub name: String,
        pub routes: ReactiveMap<String, String>,
    }
}

#[amethystate(prefix = "network", version = 2)]
pub struct ProxyConfig {
    #[amestate(default = "default".into())]
    pub name: String,
    pub endpoints: ReactiveMap<String, ProxyEndpoint>,
}

#[migrate]
fn migrate_proxy_config_v1_to_v2(
    old: AmeData<v1::ProxyConfig>,
    ctx: &mut amethystate::migration::MigrationContext,
) -> amethystate::Result<AmeData<ProxyConfig>> {
    for key in old.routes.keys() {
        ctx.delete(&format!("routes.{}", key))?;
    }
    let endpoints = old.routes.into_iter()
        .map(|(k, v)| (k, ProxyEndpoint { url: v, timeout_ms: 5000 }))
        .collect();
    Ok(AmeData::<ProxyConfig> { name: old.name, endpoints })
}