2

2022-20: Iteration 13 汇报

 2 years ago
source link: https://xuanwo.io/reports/2022-20/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2022-20: Iteration 13 汇报

Iteration 13 从 5/7 开始到 5/20 结束,为期两周。这个周期成功合并了不少之前提交的 PR,感觉非常有成就感。

difftastic

difftastic difftastic 是一个使用 Rust 开发的能理解语义的 diff 工具。

在这个周期中,我合并了两个 PR:

fix: Bad padding of column numbers at the end of files 修复了文件末尾的 padding 不正确问题:

bug.png

这里的 str2 应当需要跟上面的 Violets 悬空对齐,但是并没有。简单的调试后发现是计算 padding 的时候错误地忽略了一些情况,去掉之后就修复了:

fixed.png

feat: Improve binary content guess 则是改进了二进制内容的检测算法。

在过去,difftastic 使用一种比较简单粗暴的方法来检测二进制文件:

let num_replaced = String::from_utf8_lossy(bytes)
    .to_string()
    .chars()
    .take(1000)
    .filter(|c| *c == std::char::REPLACEMENT_CHARACTER || *c == '\0')
    .count();

num_replaced > 20

在前一千个字节中寻找非法的 Unicode 字符以及 \0,如果超过 20 个就认为是二进制文件。在 Issue Treat PDFs as binary files 中,作者希望能够检测 PDF 并将其作为二进制文件处理。给定一个文件头,要求我们判断是否为二进制文件,其实很容易可以想到根据 magic number 来判断。我在 PR 中引入了 tree_magic_mini 来检测这段内容的 MIME,并对常见的二进制类型做了统一的处理:

let mime = tree_magic_mini::from_u8(bytes);
match mime {
    // Treat pdf as binary.
    "application/pdf" => return true,
    // Treat all image content as binary.
    v if v.starts_with("image/") => return true,
    // Treat all audio content as binary.
    v if v.starts_with("audio/") => return true,
    // Treat all video content as binary.
    v if v.starts_with("video/") => return true,
    // Treat all font content as binary.
    v if v.starts_with("font/") => return true,
    _ => {}
}

这样 difftastic 就能够正确地处理绝大多数二进制类型了。

databend

正如上个周报中提到的,这个周期我花了不少功夫来提升 Databend 配置的兼容性。在 RFC: Config Backward Compatibility 的推动下,我为 databend-querydatabend-meta 都加上了配置的兼容层。同时在 PR refactor: Reuse StorageConfig in stage 中还为内部的 Storage 相关配置做了大范围重构,使得内部的逻辑都可以共享同一个配置文件,不需要再重复实现相似的逻辑。

处理 databend-meta 的配置兼容比较坎坷,因为内部的配置项特别多,又经历了不少重构,所以 meta 有不少配置项,其中不少配置项还都没有遵循统一的命名风格。所以在纠结了很久之后,我发现了 serfig 的全新用法:

pub fn load() -> MetaResult<Self> {
    let arg_conf = Self::parse();

    let mut builder: serfig::Builder<Self> = serfig::Builder::default();

    // Load from the config file first.
    {
        let config_file = if !arg_conf.config_file.is_empty() {
            arg_conf.config_file.clone()
        } else if let Ok(path) = env::var("METASRV_CONFIG_FILE") {
            path
        } else {
            "".to_string()
        };

        builder = builder.collect(from_file(Toml, &config_file));
    }

    // Then, load from env.
    let cfg_via_env: ConfigViaEnv = serfig::Builder::default()
        .collect(from_env())
        .build()
        .map_err(|e| MetaError::InvalidConfig(e.to_string()))?;
    builder = builder.collect(from_self(cfg_via_env.into()));

    // Finally, load from args.
    builder = builder.collect(from_self(arg_conf));

    builder
        .build()
        .map_err(|e| MetaError::InvalidConfig(e.to_string()))
}

用户可以维护一个独立的 cfg env wrapper,从 env loading 数据并转换成 cfg。不过这种用法对于少量的 env 不兼容来说还是比较麻烦。@DCjanus 在 Issue Add bind attribute support 中同样提到了类似的需求。

下个周期后专注于 Databend 读取压缩文件的支持,后面 databend 将能够实现直接读取 gzip,zstd 等压缩文件~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK