2个版本

0.1.1 2021年2月21日
0.1.0 2020年12月19日

#606 in 异步

自定义许可证

105KB
2K SLoC

Docs.rs

什么是

为Rust提供的异步感知和可扩展的分层配置系统 允许您从多个来源收集配置,包括但不限于

  • 文件
  • 环境
  • 内存中

它围绕 Serde 构建,负责将数据格式转换为其他格式。它经过实战检验且性能良好。 充分利用其功能! 的数据模型允许根据需要分层配置树,并将其转换为Rust结构或直接从树中检索配置值。此外,它允许使用简单的DSL进行配置部分的范围,同时保持相同的功能。它是考虑异步和可扩展性构建的。得益于 async_trait crate,可以定义异步配置源。

如何

以下是库的基本构建块的流程图。

来源 是例如文件或来自远程服务的数据。它们有两种类型 - 同步(阻塞,不需要 Futures 执行器)和 异步(非阻塞,但需要 Futures 执行器)。

每个来源都与一个 Format(例如 jsonyaml)相关联,由 serde 支持的反序列化器表示。

它们共同构成一个 ProviderAsyncProvider,负责从内部库结构中获取和反序列化配置。一些 Provider 不是由 SourceFormat 组成的,而是独立的结构,用于从不适合 SourceFormat 区分的来源获取数据,例如负责获取环境变量的提供者。

所有上述实体都是库公开的 特性。对于您作为 Miau 的用户来说,这意味着如果您发现某些功能缺失(无论是格式还是特定来源),您都可以轻松将其插入到管道中,充分利用其他组件。

flow of data

提供者都是懒加载的,这意味着除非被告知,否则它们不会执行任何操作。这是由 ConfigurationBuilderAsyncConfigurationBuilder 的责任来调用它们 拥有 的提供者,并适当地分层结果实体以形成 Configuration

Configuration 由有序的树(可以说它是一个有序的森林)组成,每个源一个,按顺序分层,以便为您的应用程序的不同环境提供正确的覆盖行为。

在这个阶段,您可以使用结果实体用简单的 DSL 读取配置。

"key1:[index1]:key2:key3:[index2]"

每次您想指定要读取 map 中的条目时,请使用简单的字符串。当您想读取 数组 中的特定索引时,请使用 [number](一个由方括号包围的整数)。不同的键由 ":" 字符分隔。

需要注意的是,由于使用的内存模型,从 Configuration 获取的值不一定总能借用。因此,无法获取所有类型值的 &str。虽然其中一些可能可行,但出于易于使用的考虑,最好始终检索 String。同样也适用于所有其他引用。

Configuration 可以转换为任何实现 serdeDeserialize 特性的结构体,并且没有借用字段(实际上是实现 DeserializeOwned)。

库还提供了缩放能力,即允许您关注配置的所选子部分,并将其视为顶级节点。

下面是基本示例。

请记住,由于库中存在多个包含配置的结构体,因此通过所有这些结构体共同实现的通用特性行使读取权限 - ConfigurationRead。它必须在作用域内才能访问读取方法。

use miau::{
    builder::ConfigurationBuilder, configuration::ConfigurationRead, format, format::Json5,
    provider::EnvironmentProvider, source::FileSource,
};
use std::collections::HashMap;
use std::env;

fn main() {
    let mut some_collection: HashMap<String, String> = HashMap::new();
    some_collection.insert("key".into(), "value".into());

    let mut builder = ConfigurationBuilder::default();

    let result = builder
        .add_provider(EnvironmentProvider::with_prefix("ASDFA")) 
        .add(
            FileSource::from_path("./files/config.json"), 
            format::json(),
        )
        .add(
            FileSource::from_path("./files/config.json5"),
            Json5::default(), 
        )
        .add_provider(some_collection)
        .build();

    let configuration = match result {
        Ok(configuration) => configuration,
        Err(e) => panic!(
            "You should handle it more gracefull in your app! {}",
            e.pretty_display()
        ),
    };

    // `get` method is defined in ConfigurationRead trait. It has to be in scope!
    let from_map_then_array: Option<i32> = configuration.get("map:[1]");
}

有关更多示例,请参阅源代码存储库中的示例文件夹,以了解如何构建配置和定义您自己的来源。

为什么

在用 Rust 编写自己的应用程序时,此库的作者注意到现有的用于创建分层配置的库要么维护不力,要么缺乏对 async 的支持,或者在其他方面扩展性不足。

此库的目标是提供不太可能经常更改的分层配置的核心功能,并通过特性进行扩展。它不打算让 Miau 变得笨重或因特定用例而充满可选依赖项。

这就是为什么它的唯一重依赖项是 serde,并且它只定义了可以使用标准库实现的 SourcesProviders。只有最流行的格式是 Miau 的一部分,而且它们都带有功能标志。这也是为什么没有实现 async 特性 - 有多个重量级执行器。出于同样的原因,没有包含 HTTP 源 - HTTP 库数量众多。

应单独在 crate 中实现上述实用程序的支持(这是通过公共特性实现的)。

功能标志

默认情况下没有启用任何功能标志。

  • ini - 启用对 Ini 格式的支持
  • json - 启用对 Json 格式的支持
  • msgpack - 启用对 Message Pack 格式的支持
  • serde_json5 - 启用对 Json5 格式的支持
  • serde_toml - 启用对 Toml 格式的支持
  • yaml - 启用对 Yaml 格式的支持
  • all - 启用所有其他功能标志

贡献

Miau 如果贡献高质量、单元测试并通过其哲学(在 WhyHow 部分)相匹配,将接受一次性贡献。也欢迎愿意维护此库的人,因为此库的作者认为一个人无法真正长期维护开源库。

Miau 的第一版本中没有包含但可能因某些原因有用的功能:

  • 在发生某些事件或定期的情况下刷新配置的机制(然而,最好以通用方式在 crate 外部实现它)

在您的贡献中,请记得根据需要更新文档和资源(使用 generate_assets.sh 脚本)。

许可证

MIT

依赖项

~1–2.7MB
~55K SLoC