chore: migrate to object_store

Move to the more modern and maintained object_store
library to access generic buckets.

We should be able also to do streaming of files now,
and proceed by implementing paginated results for listings
if we want.

Fixes #1.
This commit is contained in:
Matteo Settenvini 2025-08-03 20:47:12 +02:00
parent 996be0f6df
commit 32e2a5ea4a
Signed by: matteo
GPG key ID: 1C1B12600D81DE05
11 changed files with 765 additions and 558 deletions

View file

@ -3,17 +3,27 @@
mod common;
use scraper::{Html, Selector};
use {
object_store::{PutPayload, path::Path as ObjectStorePath},
scraper::{Html, Selector},
};
#[test_log::test(tokio::test)]
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn serves_files() -> anyhow::Result<()> {
let test = common::Test::new().await?;
test.bucket
.put_object("file.txt", "I am a file".as_bytes())
.put(
&ObjectStorePath::from("file.txt"),
PutPayload::from_static("I am a file".as_bytes()),
)
.await?;
test.bucket
.put_object("folder/file.txt", "I am a file in a folder".as_bytes())
.put(
&ObjectStorePath::from("folder/file.txt"),
PutPayload::from_static("I am a file in a folder".as_bytes()),
)
.await?;
let resp = reqwest::get(test.base_url.join("file.txt")?).await?;
@ -25,15 +35,21 @@ async fn serves_files() -> anyhow::Result<()> {
Ok(())
}
#[test_log::test(tokio::test)]
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn serves_top_level_folder() -> anyhow::Result<()> {
let test = common::Test::new().await?;
test.bucket
.put_object("file.txt", "I am a file".as_bytes())
.put(
&ObjectStorePath::from("file.txt"),
PutPayload::from_static("I am a file".as_bytes()),
)
.await?;
test.bucket
.put_object("folder/file.txt", "I am a file in a folder".as_bytes())
.put(
&ObjectStorePath::from("folder/file.txt"),
PutPayload::from_static("I am a file in a folder".as_bytes()),
)
.await?;
// Check that a file in the toplevel is listed:
@ -43,6 +59,7 @@ async fn serves_top_level_folder() -> anyhow::Result<()> {
"Request failed with {}",
resp.status()
);
let text = resp.text().await?;
println!("{}", &text);
let document = Html::parse_document(&text);
@ -55,8 +72,8 @@ async fn serves_top_level_folder() -> anyhow::Result<()> {
let selector =
Selector::parse(r#"table > tbody > tr:nth-child(1) > td:first-child > a"#).unwrap();
for item in document.select(&selector) {
assert_eq!(item.attr("href"), Some("folder/"));
assert_eq!(item.text().next(), Some("folder/"));
assert_eq!(item.attr("href"), Some("folder"));
assert_eq!(item.text().next(), Some("folder"));
}
let selector =
@ -69,15 +86,22 @@ async fn serves_top_level_folder() -> anyhow::Result<()> {
Ok(())
}
#[test_log::test(tokio::test)]
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn serves_second_level_folder() -> anyhow::Result<()> {
let test = common::Test::new().await?;
test.bucket
.put_object("file.txt", "I am a file".as_bytes())
.put(
&ObjectStorePath::from("file.txt"),
PutPayload::from_static("I am a file".as_bytes()),
)
.await?;
test.bucket
.put_object("folder/file.txt", "I am a file in a folder".as_bytes())
.put(
&ObjectStorePath::from("folder/file.txt"),
PutPayload::from_static("I am a file in a folder".as_bytes()),
)
.await?;
// Check that a file in the second level is listed:
@ -113,15 +137,21 @@ async fn serves_second_level_folder() -> anyhow::Result<()> {
Ok(())
}
#[test_log::test(tokio::test)]
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn serves_second_level_folder_without_ending_slash() -> anyhow::Result<()> {
let test = common::Test::new().await?;
test.bucket
.put_object("file.txt", "I am a file".as_bytes())
.put(
&ObjectStorePath::from("file.txt"),
PutPayload::from_static("I am a file".as_bytes()),
)
.await?;
test.bucket
.put_object("folder/file.txt", "I am a file in a folder".as_bytes())
.put(
&ObjectStorePath::from("folder/file.txt"),
PutPayload::from_static("I am a file in a folder".as_bytes()),
)
.await?;
// Check that a file in the second level is listed even without an ending slash: