
测试 OpenDAL:以 PostgreSQL Service 为例
如果将人生比喻成在大海中航行,为了度过一个圆满的人生,首先自己必须拼命地划船。同时也需要伙伴的协助,需要他人的帮助。
但是仅凭这些,还无法到达遥远的目的地。只有借助推动航船前进的他力之风,航船才能驶入大洋,才能开始真正的航海。
—— 稻盛和夫 《思维方式》
OpenDAL 项目简介
OpenDAL 项目是一款虚拟的文件系统,它试图使用文件模型抽象化所有的存储后端,进而降低各类工程的建设成本(这就像 Java 的一处编译四处运行)。
目前 OpenDAL 已经进入 Apache 基金会,并完成毕业流程,成为国际顶级开源项目之一。
环境配置
请参考《使用 OpenDAL 连接 PostgreSQL》这篇文章,在你的系统上面配置好 OpenDAL 与 PostgreSQL 协同工作的环境。
# 使用 psql 直接连接到 PostgreSQL
# 这个测试可以判断你的环境变量是否配置正确
# 以及 PostgreSQL 服务端是否能够正常运行
psql -d postgres
在这个基础上面,下载 OpenDAL 的 Dev 版本。
git clone https://github.com/apache/opendal.git
配置我们自己的开发文件夹
cd opendal/core
mkdir dev
之后,调整 OpenDAL core 目录下面的 Cargo.toml 文件。
把 dev 文件夹和其附属目录加入到 Workspace 标签下面的 Members 里面(这是 Rust 特有的 “工作空间” 理念,是为大型项目中一个或者数个模块的开发、测试、改进准备的,具体可以参考 《Rust 官方网站有关 Workspace 的部分》。
就此,我们即可以在 dev 目录下面展开我们的开发工作,方法就是为每一个想要改进或者测试的模块设立一个对应的小项目文件夹。
为 PostgreSQL 的测试做准备
比如本文希望测试的是 OpenDAL 的 PostgreSQL-Service 部分,我们就可以创建一个名为 “try_postgresql” 的小项目。
# 每一个模块都可以成为一个小项目,而这些小项目就构成了一个个庞大工程的基石
cargo new try_postgresql
cd try_postgresql
cargo run
Rust 新创建的项目都会输出一句 “Hello,world!”
同时,我们也需要启动 PostgreSQL 服务端(重复:本文所使用的 PostgreSQL 是 《使用 OpenDAL 连接 PostgreSQL》 一文的延续,因此 OpenDAL 所使用的数据表等都是同该文章中的表保持一致的),用以应对即将到来的 OpenDAL 连接。
# 使用 psql 连接 PostgreSQL
psql -d postgres
# 创建为本次测试准备的数据表
create table try_postgresql (
/* 存储文件名 */
filename text,
/* 存储文件数据 */
filedata bytea,
/* OpenDAL 要求 文件名 具有 UNIQUE 约束 */
unique(filename)
);
为 try_postgresql 项目配备所需要的特性
# 假定目前处于 try_postgresql 目录下
# 引入 PostgreSQL 连接程序所需要的 anyhow 与 tokio 库
cargo add anyhow tokio
# 打开 tokio 库的全部特性
cargo add tokio --features full
# 打开 OpenDAL PostgreSQL 服务特性
cargo add opendal --features services-postgresql
在这个基础上,修改 try_postgresql 下面的 main.rs 的代码为如下:
use anyhow::Result;
use opendal::services::Postgresql;
use opendal::Operator;
#[tokio::main]
async fn main() -> Result<()> {
let builder = Postgresql::default()
.root("/")
/* 连接到本机 PostgreSQL 下面的 postgres */
/* 可参考 https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING */
.connection_string("postgresql://127.0.0.1:5432/postgres")
/* 使用我们前面创建的数据表 */
.table("try_postgresql")
/* 存储文件名的数据列 */
.key_field("filename")
/* 存储文件数据的数据列 */
.value_field("filedata");
let op = Operator::new(builder)?.finish();
/* 将 `Hello PostgreSQL` 写入到一个名为 `postgres.txt` 的文件夹中 */
op.write("postgres.txt", "Hello PostgreSQL").await?;
/* 构建 Reader */
let content = op
.reader_with("postgres.txt")
.await?
;
/* 经由 Reader 获取到一个 Buffer */
let bs = content.read(0..16).await?;
/* 提取 Buffer 中的内容,即为文件内容 */
println!("{:?}", bs.to_bytes());
Ok(())
}
之后,继续使用 cargo run
运行,可以得到如下结果:
修改 OpenDAL PostgreSQL Service 并查看效果
现在,我们已经配置好了一个用于测试 PostgreSQL Service 的小项目,接下来我们可以尝试修改 OpenDAL 用以查看修订后的效果。
再次回到 OpenDAL 的 core 目录下,依照如图所示顺序,找到 PostgreSQL-Service 所在部分,打开对应的代码文件。
找到 get 函数,做一些微调整。
/* 代码修改前*/
async fn get(&self, path: &str) -> Result<Option<Buffer>> {
let pool = self.get_client().await?;
let value: Option<Vec<u8>> = sqlx::query_scalar(&format!(
r#"SELECT "{}" FROM "{}" WHERE "{}" = $1 LIMIT 1"#,
self.value_field, self.table, self.key_field
))
/* 代码修改后 */
async fn get(&self, path: &str) -> Result<Option<Buffer>> {
let pool = self.get_client().await?;
let value: Option<Vec<u8>> = sqlx::query_scalar(&format!(
r#"SELECT 'Very Good, ' || "{}" FROM "{}" WHERE "{}" = $1 LIMIT 1"#,
self.value_field, self.table, self.key_field
))
在这之后,让我们再次运行那个测试程序:
就这样,我们实现了一次对 OpenDAL 的简单开发,它也为我们后续的很多工作奠定了坚实的基础(其它的存储接口,大致遵循着同样的流程)。
写在最后
感谢 @Xuanwo 老师,感谢 @尚卓燃 两位 OpenDAL 的研发人员,让我有了参与一个 Apache 顶级开源项目的机会(我想,这不仅仅是对我的履历可以加上一点分,更重要的,是让我有了更多的建设开源社区的经验,倒过头来,我可以依据这些经验去促进更多开源方面的同志的进步),同时感谢本科导师袁国铭,中国 PG 分会魏波老师,王其达老师,开放原子开源基金会张凯老师。
最后感谢稻盛和夫在其漫长的人生经历中总结出来的哲学,启发了我去高效的工作,带动更多人进步,为创建一个更为开放繁荣的开源生态而努力!