mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-09 22:59:59 +00:00
fix(select): pin object snapshot for query lifetime (#5835)
This commit is contained in:
@@ -27,6 +27,7 @@ documentation = "https://docs.rs/rustfs-test-utils/latest/rustfs_test_utils/"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
put-object-commit-barrier = ["rustfs-ecstore/test-util"]
|
||||
hotpath = [
|
||||
"hotpath/hotpath",
|
||||
"hotpath/tokio",
|
||||
@@ -51,7 +52,7 @@ hotpath-cpu = [
|
||||
|
||||
[dependencies]
|
||||
hotpath.workspace = true
|
||||
rustfs-ecstore = { workspace = true }
|
||||
rustfs-ecstore.workspace = true
|
||||
rustfs-storage-api = { workspace = true }
|
||||
tokio = { workspace = true, features = ["fs", "rt-multi-thread"] }
|
||||
tokio-util = { workspace = true, features = ["io", "compat"] }
|
||||
|
||||
@@ -26,8 +26,11 @@ pub(crate) mod fixture {
|
||||
pub(crate) use rustfs_ecstore::api::bucket::metadata_sys::init_bucket_metadata_sys;
|
||||
pub(crate) use rustfs_ecstore::api::disk::endpoint::Endpoint;
|
||||
pub(crate) use rustfs_ecstore::api::layout::{EndpointServerPools, Endpoints, PoolEndpoints};
|
||||
pub(crate) use rustfs_ecstore::api::object::{PutObjReader, SelectObjectSnapshot};
|
||||
#[cfg(feature = "put-object-commit-barrier")]
|
||||
pub(crate) use rustfs_ecstore::api::set_disk as ecstore_set_disk;
|
||||
pub(crate) use rustfs_ecstore::api::storage::{ECStore, init_local_disks};
|
||||
pub(crate) use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions};
|
||||
pub(crate) use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions, ObjectIO};
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) use rustfs_ecstore::api::config::com::{delete_config, read_config, save_config};
|
||||
|
||||
@@ -30,14 +30,38 @@ mod ecstore_test_compat;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Once};
|
||||
|
||||
#[cfg(feature = "put-object-commit-barrier")]
|
||||
use ecstore_test_compat::fixture::ecstore_set_disk;
|
||||
use ecstore_test_compat::fixture::{
|
||||
BucketOperations as _, BucketOptions, ECStore, Endpoint, EndpointServerPools, Endpoints, MakeBucketOptions, PoolEndpoints,
|
||||
init_bucket_metadata_sys, init_local_disks,
|
||||
BucketOperations as _, BucketOptions, ECStore, Endpoint, EndpointServerPools, Endpoints, MakeBucketOptions, ObjectIO as _,
|
||||
PoolEndpoints, PutObjReader, SelectObjectSnapshot, init_bucket_metadata_sys, init_local_disks,
|
||||
};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
static INIT_TRACING: Once = Once::new();
|
||||
|
||||
#[cfg(feature = "put-object-commit-barrier")]
|
||||
pub struct PutObjectCommitBarrier(ecstore_set_disk::test_util::PutObjectCommitBarrier);
|
||||
|
||||
#[cfg(feature = "put-object-commit-barrier")]
|
||||
impl PutObjectCommitBarrier {
|
||||
pub fn before_namespace(bucket: &str, object: &str) -> Self {
|
||||
Self(ecstore_set_disk::test_util::PutObjectCommitBarrier::install(
|
||||
bucket,
|
||||
object,
|
||||
ecstore_set_disk::test_util::PutObjectCommitPause::BeforeNamespace,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn wait_until_paused(&self) {
|
||||
self.0.wait_until_paused().await;
|
||||
}
|
||||
|
||||
pub async fn release_and_wait_until_namespace_pending(&self) {
|
||||
self.0.release_and_wait_until_namespace_pending().await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Install the standard test tracing subscriber once per process
|
||||
/// (`RUST_LOG`-driven). Safe to call from every test; later calls are no-ops.
|
||||
pub fn init_tracing() {
|
||||
@@ -90,6 +114,29 @@ impl TestECStoreEnv {
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("failed to create test bucket {bucket}: {e:?}"));
|
||||
}
|
||||
|
||||
/// Write one complete object body through the real ECStore test backend.
|
||||
pub async fn put_object_bytes(&self, bucket: &str, object: &str, bytes: Vec<u8>) {
|
||||
let mut reader = PutObjReader::from_vec(bytes);
|
||||
self.ecstore
|
||||
.put_object(bucket, object, &mut reader, &Default::default())
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("failed to write test object {bucket}/{object}: {e:?}"));
|
||||
}
|
||||
|
||||
/// Prepare the lock-backed object snapshot used by SelectObjectContent tests.
|
||||
///
|
||||
/// The concrete ECStore snapshot type stays behind this crate's test
|
||||
/// compatibility boundary; consumers can pass the inferred value directly
|
||||
/// to the S3 Select API without importing ECStore facade paths.
|
||||
pub async fn prepare_select_object_snapshot(&self, bucket: &str, object: &str) -> Arc<SelectObjectSnapshot> {
|
||||
Arc::new(
|
||||
self.ecstore
|
||||
.prepare_select_object_snapshot(bucket, object, &Default::default(), &Default::default())
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("failed to prepare test object snapshot {bucket}/{object}: {e:?}")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder for [`TestECStoreEnv`]. Defaults reproduce the historical heal
|
||||
|
||||
Reference in New Issue
Block a user