refactor: centralize scanner runtime source helpers (#3827)

* refactor: batch lifecycle runtime source handles

* refactor: centralize scanner runtime source helpers
This commit is contained in:
Zhengchao An
2026-06-24 22:05:03 +08:00
committed by GitHub
parent 5cc8bd7952
commit a935854b32
19 changed files with 191 additions and 101 deletions
@@ -4603,8 +4603,8 @@ mod tests {
use super::super::super::Endpoint;
use super::super::super::{EndpointServerPools, Endpoints, PoolEndpoints};
use super::*;
use crate::app::context::{resolve_outbound_tls_generation, set_test_outbound_tls_generation};
use http::{HeaderMap, HeaderValue, Uri};
use rustfs_common::{get_global_outbound_tls_generation, set_global_outbound_tls_generation};
use rustfs_policy::policy::action::S3Action;
use serial_test::serial;
use temp_env::with_var;
@@ -5864,7 +5864,7 @@ mod tests {
#[tokio::test]
#[serial]
async fn test_site_replication_peer_client_rebuilds_when_generation_changes() {
let previous_generation = get_global_outbound_tls_generation();
let previous_generation = resolve_outbound_tls_generation().0;
let previous_cache = {
let mut cache = SITE_REPLICATION_PEER_CLIENT.lock().await;
let snapshot = cache.clone();
@@ -5872,7 +5872,7 @@ mod tests {
snapshot
};
set_global_outbound_tls_generation(101);
set_test_outbound_tls_generation(101);
site_replication_peer_client()
.await
.expect("initial client build should succeed");
@@ -5882,7 +5882,7 @@ mod tests {
assert!(matches!(cached.entry, SiteReplicationPeerClientCacheEntry::Ready(_)));
drop(cache);
set_global_outbound_tls_generation(102);
set_test_outbound_tls_generation(102);
site_replication_peer_client()
.await
.expect("new generation should rebuild client");
@@ -5892,7 +5892,7 @@ mod tests {
assert!(matches!(cached.entry, SiteReplicationPeerClientCacheEntry::Ready(_)));
drop(cache);
set_global_outbound_tls_generation(previous_generation);
set_test_outbound_tls_generation(previous_generation);
let mut cache = SITE_REPLICATION_PEER_CLIENT.lock().await;
*cache = previous_cache;
}
+43 -1
View File
@@ -33,7 +33,7 @@ use super::StorageClassConfig;
use super::TierConfigMgr;
use super::metadata_sys::BucketMetadataSys;
use super::new_object_layer_fn;
use super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, ReplicationStats};
use super::{BucketBandwidthMonitor, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats};
use crate::config::RustFSBufferConfig;
use rustfs_config::server_config::Config;
use rustfs_credentials::Credentials;
@@ -67,6 +67,11 @@ pub fn resolve_outbound_tls_generation() -> TlsGeneration {
resolve_outbound_tls_generation_with(get_global_app_context(), || default_outbound_tls_runtime_interface().generation())
}
#[cfg(test)]
pub(crate) fn set_test_outbound_tls_generation(generation: u64) {
rustfs_common::set_global_outbound_tls_generation(generation);
}
/// Resolve outbound TLS state using AppContext-first precedence.
pub async fn resolve_outbound_tls_state() -> GlobalPublishedOutboundTlsState {
resolve_outbound_tls_state_with(get_global_app_context()).await
@@ -230,6 +235,11 @@ pub fn resolve_tier_config_handle() -> Arc<RwLock<TierConfigMgr>> {
resolve_tier_config_handle_with(get_global_app_context(), || default_tier_config_interface().handle())
}
/// Resolve lifecycle expiry state using AppContext-first precedence.
pub fn resolve_expiry_state_handle() -> Arc<RwLock<ExpiryState>> {
resolve_expiry_state_handle_with(get_global_app_context(), || default_expiry_state_interface().handle())
}
/// Resolve server config using AppContext-first precedence.
pub fn resolve_server_config() -> Option<Config> {
resolve_server_config_with(get_global_app_context(), || default_server_config_interface().get())
@@ -510,6 +520,15 @@ fn resolve_tier_config_handle_with(
context.map(|context| context.tier_config().handle()).unwrap_or_else(fallback)
}
fn resolve_expiry_state_handle_with(
context: Option<Arc<AppContext>>,
fallback: impl FnOnce() -> Arc<RwLock<ExpiryState>>,
) -> Arc<RwLock<ExpiryState>> {
context
.map(|context| context.expiry_state().handle())
.unwrap_or_else(fallback)
}
fn resolve_server_config_with(context: Option<Arc<AppContext>>, fallback: impl FnOnce() -> Option<Config>) -> Option<Config> {
context.map_or_else(fallback, |context| context.server_config().get())
}
@@ -847,6 +866,16 @@ mod tests {
}
}
struct TestExpiryStateInterface {
expiry_state: Arc<RwLock<ExpiryState>>,
}
impl ExpiryStateInterface for TestExpiryStateInterface {
fn handle(&self) -> Arc<RwLock<ExpiryState>> {
self.expiry_state.clone()
}
}
struct TestServerConfigInterface {
config: Option<Config>,
published: Arc<AtomicUsize>,
@@ -974,6 +1003,8 @@ mod tests {
..Default::default()
};
let tier_config = TierConfigMgr::new();
let context_expiry_state = ExpiryState::new();
let fallback_expiry_state = ExpiryState::new();
let server_config = Config::new();
let context_server_config_published = Arc::new(AtomicUsize::new(0));
let fallback_server_config_published = Arc::new(AtomicUsize::new(0));
@@ -1101,6 +1132,9 @@ mod tests {
tier_config: Arc::new(TestTierConfigInterface {
tier_config: tier_config.clone(),
}),
expiry_state: Arc::new(TestExpiryStateInterface {
expiry_state: context_expiry_state.clone(),
}),
server_config: Arc::new(TestServerConfigInterface {
config: Some(server_config.clone()),
published: context_server_config_published.clone(),
@@ -1222,6 +1256,10 @@ mod tests {
&resolve_tier_config_handle_with(Some(context.clone()), TierConfigMgr::new),
&tier_config
));
assert!(Arc::ptr_eq(
&resolve_expiry_state_handle_with(Some(context.clone()), || fallback_expiry_state.clone()),
&context_expiry_state
));
assert_eq!(
resolve_server_config_with(Some(context.clone()), || None).expect("context server config"),
server_config
@@ -1334,6 +1372,10 @@ mod tests {
fallback_region
);
assert!(Arc::ptr_eq(&resolve_tier_config_handle_with(None, || tier_config.clone()), &tier_config));
assert!(Arc::ptr_eq(
&resolve_expiry_state_handle_with(None, || fallback_expiry_state.clone()),
&fallback_expiry_state
));
assert_eq!(
resolve_server_config_with(None, || Some(server_config.clone())).expect("fallback server config"),
server_config
+16 -8
View File
@@ -16,9 +16,9 @@ use super::super::{ECStore, set_object_store_resolver};
use super::handles::{
IamHandle, KmsHandle, default_action_credential_interface, default_boot_time_interface, default_bucket_metadata_interface,
default_bucket_monitor_interface, default_buffer_config_interface, default_deployment_id_interface,
default_endpoints_interface, default_internode_metrics_interface, default_kms_runtime_interface,
default_local_node_name_interface, default_lock_client_interface, default_lock_clients_interface,
default_notification_system_interface, default_notify_interface, default_oidc_interface,
default_endpoints_interface, default_expiry_state_interface, default_internode_metrics_interface,
default_kms_runtime_interface, default_local_node_name_interface, default_lock_client_interface,
default_lock_clients_interface, default_notification_system_interface, default_notify_interface, default_oidc_interface,
default_outbound_tls_runtime_interface, default_performance_metrics_interface, default_region_interface,
default_replication_pool_interface, default_replication_stats_interface, default_runtime_port_interface,
default_s3select_db_interface, default_scanner_metrics_interface, default_server_config_interface,
@@ -26,11 +26,11 @@ use super::handles::{
};
use super::interfaces::{
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
DeploymentIdInterface, EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface,
LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface, NotifyInterface,
OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface,
ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, ServerConfigInterface,
StorageClassInterface, TierConfigInterface, TierStatsInterface,
DeploymentIdInterface, EndpointsInterface, ExpiryStateInterface, IamInterface, InternodeMetricsInterface, KmsInterface,
KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface,
NotifyInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface,
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface,
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
};
use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::KmsServiceManager;
@@ -67,6 +67,7 @@ pub struct AppContext {
action_credentials: Arc<dyn ActionCredentialInterface>,
region: Arc<dyn RegionInterface>,
tier_config: Arc<dyn TierConfigInterface>,
expiry_state: Arc<dyn ExpiryStateInterface>,
server_config: Arc<dyn ServerConfigInterface>,
storage_class: Arc<dyn StorageClassInterface>,
buffer_config: Arc<dyn BufferConfigInterface>,
@@ -102,6 +103,7 @@ impl AppContext {
action_credentials: default_action_credential_interface(),
region: default_region_interface(),
tier_config: default_tier_config_interface(),
expiry_state: default_expiry_state_interface(),
server_config: default_server_config_interface(),
storage_class: default_storage_class_interface(),
buffer_config: default_buffer_config_interface(),
@@ -225,6 +227,10 @@ impl AppContext {
self.tier_config.clone()
}
pub fn expiry_state(&self) -> Arc<dyn ExpiryStateInterface> {
self.expiry_state.clone()
}
pub fn server_config(&self) -> Arc<dyn ServerConfigInterface> {
self.server_config.clone()
}
@@ -266,6 +272,7 @@ pub(super) struct AppContextTestInterfaces {
pub(super) action_credentials: Arc<dyn ActionCredentialInterface>,
pub(super) region: Arc<dyn RegionInterface>,
pub(super) tier_config: Arc<dyn TierConfigInterface>,
pub(super) expiry_state: Arc<dyn ExpiryStateInterface>,
pub(super) server_config: Arc<dyn ServerConfigInterface>,
pub(super) storage_class: Arc<dyn StorageClassInterface>,
pub(super) buffer_config: Arc<dyn BufferConfigInterface>,
@@ -302,6 +309,7 @@ impl AppContext {
action_credentials: interfaces.action_credentials,
region: interfaces.region,
tier_config: interfaces.tier_config,
expiry_state: interfaces.expiry_state,
server_config: interfaces.server_config,
storage_class: interfaces.storage_class,
buffer_config: interfaces.buffer_config,
+20 -6
View File
@@ -18,17 +18,17 @@ use super::super::TierConfigMgr;
use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys};
use super::super::{
collect_scanner_metrics_report, get_daily_all_tier_stats, get_global_boot_time, get_global_bucket_monitor,
get_global_deployment_id, get_global_endpoints_opt, get_global_lock_client, get_global_lock_clients,
get_global_deployment_id, get_global_endpoints_opt, get_global_expiry_state, get_global_lock_client, get_global_lock_clients,
get_global_notification_sys, get_global_region, get_global_replication_pool, get_global_replication_stats,
get_global_tier_config_mgr, global_rustfs_port, set_global_storage_class,
};
use super::interfaces::{
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
DeploymentIdInterface, EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface,
LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface, NotifyInterface,
OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface,
ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, ServerConfigInterface,
StorageClassInterface, TierConfigInterface, TierStatsInterface,
DeploymentIdInterface, EndpointsInterface, ExpiryStateInterface, IamInterface, InternodeMetricsInterface, KmsInterface,
KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface,
NotifyInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface,
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface,
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
};
use crate::config::{RustFSBufferConfig, get_global_buffer_config};
use async_trait::async_trait;
@@ -368,6 +368,16 @@ impl TierConfigInterface for TierConfigHandle {
}
}
/// Default lifecycle expiry state interface adapter.
#[derive(Default)]
pub struct ExpiryStateHandle;
impl ExpiryStateInterface for ExpiryStateHandle {
fn handle(&self) -> Arc<RwLock<super::super::ExpiryState>> {
get_global_expiry_state()
}
}
/// Default server config interface adapter.
#[derive(Default)]
pub struct ServerConfigHandle;
@@ -498,6 +508,10 @@ pub fn default_tier_config_interface() -> Arc<dyn TierConfigInterface> {
Arc::new(TierConfigHandle)
}
pub fn default_expiry_state_interface() -> Arc<dyn ExpiryStateInterface> {
Arc::new(ExpiryStateHandle)
}
pub fn default_server_config_interface() -> Arc<dyn ServerConfigInterface> {
Arc::new(ServerConfigHandle)
}
+6 -1
View File
@@ -18,7 +18,7 @@ use super::super::ScannerMetricsReport;
use super::super::StorageClassConfig;
use super::super::TierConfigMgr;
use super::super::metadata_sys::BucketMetadataSys;
use super::super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, ReplicationStats};
use super::super::{BucketBandwidthMonitor, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats};
use crate::config::RustFSBufferConfig;
use async_trait::async_trait;
use rustfs_config::server_config::Config;
@@ -193,6 +193,11 @@ pub trait TierConfigInterface: Send + Sync {
fn handle(&self) -> Arc<RwLock<TierConfigMgr>>;
}
/// Lifecycle expiry state interface for transition cleanup queues.
pub trait ExpiryStateInterface: Send + Sync {
fn handle(&self) -> Arc<RwLock<ExpiryState>>;
}
/// Server config interface for application-layer and server modules.
pub trait ServerConfigInterface: Send + Sync {
fn get(&self) -> Option<Config>;
@@ -13,8 +13,7 @@
// limitations under the License.
use super::{
AppWarmBackend, ECStore, Endpoint, EndpointServerPools, Endpoints, GLOBAL_TierConfigMgr, PoolEndpoints, TierConfig, TierType,
WarmBackendGetOpts,
AppWarmBackend, ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints, TierConfig, TierType, WarmBackendGetOpts,
metadata::{BUCKET_LIFECYCLE_CONFIG, OBJECT_LOCK_CONFIG},
metadata_sys,
object_api_utils::to_s3s_etag,
@@ -22,6 +21,7 @@ use super::{
};
use super::{multipart_usecase::DefaultMultipartUsecase, object_usecase::DefaultObjectUsecase};
use crate::app::bucket_usecase::DefaultBucketUsecase;
use crate::app::context::resolve_tier_config_handle;
use crate::storage::ecfs::FS;
use crate::storage::{
StorageObjectInfo as ObjectInfo, StorageObjectOptions as ObjectOptions, StoragePutObjReader as PutObjReader,
@@ -337,7 +337,8 @@ impl AppWarmBackend for MockWarmBackend {
async fn register_mock_tier(tier_name: &str) -> MockWarmBackend {
let backend = MockWarmBackend::default();
let mut tier_config_mgr = GLOBAL_TierConfigMgr.write().await;
let tier_config_mgr_handle = resolve_tier_config_handle();
let mut tier_config_mgr = tier_config_mgr_handle.write().await;
tier_config_mgr.tiers.insert(
tier_name.to_string(),
TierConfig {
+5 -37
View File
@@ -80,11 +80,6 @@ mod ecstore_data_usage {
};
}
#[cfg(test)]
mod ecstore_global {
pub(crate) use crate::storage::ecstore_global::GLOBAL_TierConfigMgr;
}
#[allow(unused_imports)]
mod ecstore_tier {
pub(crate) use crate::storage::ecstore_tier::{tier, tier_config, warm_backend};
@@ -97,6 +92,7 @@ pub(crate) type DynReader = crate::storage::DynReader;
pub(crate) type DynReplicationPool = crate::storage::DynReplicationPool;
pub(crate) type ECStore = crate::storage::ECStore;
pub(crate) type EndpointServerPools = crate::storage::EndpointServerPools;
pub(crate) type ExpiryState = crate::storage::ExpiryState;
pub(crate) type HashReader = crate::storage::HashReader;
pub(crate) type NotificationSys = crate::storage::NotificationSys;
pub(crate) type BucketBandwidthMonitor = crate::storage::BucketBandwidthMonitor;
@@ -208,27 +204,11 @@ pub(crate) mod lifecycle {
}
pub(crate) mod bucket_lifecycle_ops {
use std::ops::Deref;
use std::sync::Arc;
use super::ECStore;
use super::bucket_lifecycle_audit::LcEventSrc;
pub(crate) type ExpiryState = super::super::ecstore_bucket::lifecycle::bucket_lifecycle_ops::ExpiryState;
pub(crate) struct GlobalExpiryStateCompat;
#[allow(non_upper_case_globals)]
pub(crate) static GLOBAL_ExpiryState: GlobalExpiryStateCompat = GlobalExpiryStateCompat;
impl Deref for GlobalExpiryStateCompat {
type Target = Arc<tokio::sync::RwLock<ExpiryState>>;
fn deref(&self) -> &Self::Target {
&super::super::ecstore_bucket::lifecycle::bucket_lifecycle_ops::GLOBAL_ExpiryState
}
}
#[cfg(test)]
pub(crate) async fn init_background_expiry(api: Arc<ECStore>) {
super::super::ecstore_bucket::lifecycle::bucket_lifecycle_ops::init_background_expiry(api).await;
@@ -623,22 +603,6 @@ pub(crate) fn is_err_version_not_found(err: &Error) -> bool {
crate::storage::is_err_version_not_found(err)
}
#[cfg(test)]
pub(crate) struct GlobalTierConfigMgrCompat;
#[cfg(test)]
#[allow(non_upper_case_globals)]
pub(crate) static GLOBAL_TierConfigMgr: GlobalTierConfigMgrCompat = GlobalTierConfigMgrCompat;
#[cfg(test)]
impl std::ops::Deref for GlobalTierConfigMgrCompat {
type Target = Arc<tokio::sync::RwLock<TierConfigMgr>>;
fn deref(&self) -> &Self::Target {
&ecstore_global::GLOBAL_TierConfigMgr
}
}
pub(crate) fn get_global_endpoints_opt() -> Option<EndpointServerPools> {
crate::storage::get_global_endpoints_opt()
}
@@ -667,6 +631,10 @@ pub(crate) fn get_global_tier_config_mgr() -> Arc<tokio::sync::RwLock<TierConfig
crate::storage::get_global_tier_config_mgr()
}
pub(crate) fn get_global_expiry_state() -> Arc<tokio::sync::RwLock<ExpiryState>> {
crate::storage::get_global_expiry_state()
}
pub(crate) fn new_object_layer_fn() -> Option<Arc<ECStore>> {
crate::storage::new_object_layer_fn()
}
+4 -2
View File
@@ -45,7 +45,8 @@ use super::{
versioning_sys::BucketVersioningSys,
};
use crate::app::context::{
AppContext, get_global_app_context, resolve_notify_interface_for_context, resolve_object_store_handle_for_context,
AppContext, get_global_app_context, resolve_expiry_state_handle, resolve_notify_interface_for_context,
resolve_object_store_handle_for_context,
};
use crate::config::RustFSBufferConfig;
use crate::delete_tail_activity::{DeleteTailActivityGuard, DeleteTailStage};
@@ -294,7 +295,8 @@ async fn enqueue_transitioned_delete_cleanup(
super::lifecycle::tier_delete_journal::persist_tier_delete_journal_entry(store, &je).await?;
let mut expiry_state = super::lifecycle::bucket_lifecycle_ops::GLOBAL_ExpiryState.write().await;
let expiry_state = resolve_expiry_state_handle();
let mut expiry_state = expiry_state.write().await;
if let Err(err) = expiry_state.enqueue_tier_journal_entry(&je).await {
warn!(
bucket,
+6 -1
View File
@@ -235,6 +235,7 @@ pub(crate) type Endpoint = ecstore_disk::endpoint::Endpoint;
pub(crate) type Endpoints = ecstore_layout::Endpoints;
pub(crate) type EndpointServerPools = ecstore_layout::EndpointServerPools;
pub(crate) type EventArgs = ecstore_event::EventArgs;
pub(crate) type ExpiryState = ecstore_bucket::lifecycle::bucket_lifecycle_ops::ExpiryState;
pub(crate) type FileInfoVersions = ecstore_disk::FileInfoVersions;
pub(crate) type FileReader = ecstore_disk::FileReader;
pub(crate) type FileWriter = ecstore_disk::FileWriter;
@@ -316,7 +317,11 @@ pub(crate) fn get_global_boot_time() -> Option<std::time::SystemTime> {
}
pub(crate) fn get_daily_all_tier_stats() -> DailyAllTierStats {
ecstore_bucket::lifecycle::bucket_lifecycle_ops::GLOBAL_TransitionState.get_daily_all_tier_stats()
ecstore_bucket::lifecycle::bucket_lifecycle_ops::get_global_transition_state().get_daily_all_tier_stats()
}
pub(crate) fn get_global_expiry_state() -> Arc<tokio::sync::RwLock<ExpiryState>> {
ecstore_bucket::lifecycle::bucket_lifecycle_ops::get_global_expiry_state()
}
pub(crate) async fn try_migrate_bucket_metadata(store: Arc<ECStore>) {