#configuration #merge #command-line-arguments #derive #single-line

converge

分层配置,可以表示为一行代码。`Converge` 特性将结构体的实例合并为一个新实例的结构体。`Converge` 特性可以派生,并且可以配合嵌套结构体的字段属性或自定义的 `strategy`。

5个版本

0.0.5 2023年8月5日
0.0.4 2022年5月4日
0.0.3 2022年4月21日
0.0.2 2022年4月21日
0.0.1 2022年4月20日

数据结构类别中排名#275


用于converge_test

MIT/Apache

18KB
123

Converge

使用少量代码的Rust应用程序分层配置系统。通过仅合并配置,配置源和合并方式的灵活性由用户控制。

简介

具有分层配置(命令行参数、环境和配置文件)的应用程序是用户所期望的。此库允许以最小的努力和代码将这些来源分层。

动机

Unix哲学和微服务思想都导致编写大量的应用程序。合理地预期这些应用程序将从命令行参数、环境和通常的配置文件中获取配置。随着应用程序的成熟,配置选项的数量往往会增加。管理这些配置的一种简单方法是重复且容易出错,并且向其中添加测试会增加重复。

关于

此库允许用户自由决定配置文件格式、命令行解析方法,并且依赖性最小。它与作为字段的配置项的结构一起工作。这些结构必须实现一个具有单个方法的特质,这个方法对于大多数结构通常是可派生的。

此方法与不可变数据结构一起工作,代码量非常少,但以在分层过程中复制配置为代价。这是一个合理的折衷方案,因为它通常只在一个应用程序的生命周期中发生一次。

快速入门

它基于一个特质 `Converge`,该特质包含一个名为 `converge` 的单方法,该方法位于 `converge` 包中。

pub trait Converge<Rhs = Self> {
    fn converge(self, default: Rhs) -> Self;
}

可以使用 `converge_derive` 派生此特质,如下所示。

#[derive(Converge)]
pub struct Config {
    pub config_file: Option<String>,
    pub loglevel: Option<i8>,
    pub xunit_local_globs: Option<Vec<String>>,
    pub environment_sk: Option<String>,
    pub environment_keys: Option<Vec<String>>,
    pub project_sk: Option<String>,
    pub project_identifier: Option<String>,
    pub project_human_name: Option<String>,
    pub run_identifier: Option<String>,
    pub run_sk: Option<String>,
    pub service_url: Option<String>,
}

可以从这些结构中填充的数据可以嵌套,然后可以将它们耦合在一起,以派生具有清晰和简单预知的新的实例。

let config_commandline : Config = parse_commandline_to_config();
let config_file : Config = parse_file_to_config();
let config_env : Config = parse_env_to_config();
let cfg = config_commandline.converge(config_file).converge(config_env);

存在类型为 T 的字段,它们不是可选值,但这并不常见,因为在这种情况下 converge 只会取左侧的值。

设计您的配置结构

实现 Converge 特性的结构应该包含一个逻辑分组,以表示您可能希望作为分层配置一部分使用的每个设置。

嵌套 Converge 结构的示例

#[derive(Converge)]
pub struct ConfigRabbitMqCredentials {
    pub username: Option<String>,
    pub password: Option<String>,
}

#[derive(Converge)]
pub struct ConfigRabbitMQ {
    pub host: Option<String>,
    pub port: Option<i32>,
    #[converge(nest)]
    pub credentials: Option<ConfigRabbitMqCredentials>,
}

当使用也实现 Converge 的字段类型时,可以使用 #[converge(nest)] 属性来标记字段也支持 Converge,这允许 converge 通过 converge 在此结构上使用。

使用自定义字段收敛策略进行推导

#[derive(Converge)]
pub struct ConfigRabbitMqCredentials {
    pub username: Option<String>,
    pub password: Option<String>,
}

#[derive(Converge)]
pub struct ConfigRabbitMQ {
    pub host: Option<String>,
    pub port: Option<i32>,
    #[converge(strategy = converge::strategies::vec::replace_empty)]
    pub credentials: Vec<ConfigRabbitMqCredentials>,
}

字段也可以使用自定义策略来标记自定义收敛。其中策略是函数的路径,形式为

fn custom_function<T>(lhs: T, rhs: T) -> T

其中 T 与字段的类型匹配。 converge crate 包括一些按容器类型分组的通用泛型策略。

如何集成数据源

该库预计将与其他库结合使用,以解析配置文件格式、命令行和执行环境变量。实际上,这些库提供的最终结构通常与输入源紧密相关。 Converge trait 要求每个源提供公共数据结构。通过为您常见的数据格式实现 From traitTryFrom trait,可以将 Converge 应用到这些数据源。

相关库

我们可以推荐的一些提供配置数据的数据源库的非详尽列表。

替代方案

可能的替代方案的非详尽列表。

  • merge
    • 与 converge 类似的思想。
  • twelf
    • 支持 12-Factor 的 Rust 配置解决方案。

依赖关系

~255–700KB
~17K SLoC