mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
refactor(app): add lifecycle state context boundary (#4099)
This commit is contained in:
@@ -42,7 +42,7 @@ migration PR removes or replaces each item.
|
||||
| `GLOBAL_OBJECT_API`, `GLOBAL_OBJECT_STORE_RESOLVER` | `crates/ecstore/src/runtime/global.rs` | Runtime migration target | Do not migrate first; it is tied to storage startup, IAM-after-storage AppContext publication, and data-plane resolver compatibility. |
|
||||
| `GLOBAL_ENDPOINTS`, `GLOBAL_IS_ERASURE`, `GLOBAL_IS_DIST_ERASURE`, `GLOBAL_IS_ERASURE_SD`, `GLOBAL_ROOT_DISK_THRESHOLD` | `crates/ecstore/src/runtime/global.rs` and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | Endpoint, setup-type, and root-disk-threshold access now stays behind ECStore runtime helpers; move endpoint ownership only after readiness and quorum behavior have explicit coverage. |
|
||||
| `GLOBAL_LOCAL_DISK_MAP`, `GLOBAL_LOCAL_DISK_ID_MAP`, `GLOBAL_LOCAL_DISK_SET_DRIVES` | `crates/ecstore/src/runtime/global.rs` and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | Local disk map, disk-id cache, and set-drive access now stay behind ECStore runtime-source helpers instead of direct global access; preserve disk lookup, remote/local classification, and test reset hooks in later ownership changes. |
|
||||
| `GLOBAL_EXPIRY_STATE`, `GLOBAL_TRANSITION_STATE`, `GLOBAL_LIFECYCLE_SYS` | `crates/ecstore/src/bucket/lifecycle/*`, `crates/ecstore/src/runtime/global.rs`, and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | Lifecycle state globals now stay behind ECStore lifecycle owner helpers and ECStore runtime-source helpers; scanner expiry-state access now uses the ECStore runtime `expiry_state_handle` boundary; `GLOBAL_EXPIRY_STATE` remains the first code-bearing ownership candidate because AppContext already has an `ExpiryStateInterface`, resolver, and tests. |
|
||||
| `GLOBAL_EXPIRY_STATE`, `GLOBAL_TRANSITION_STATE`, `GLOBAL_LIFECYCLE_SYS` | `crates/ecstore/src/bucket/lifecycle/*`, `crates/ecstore/src/runtime/global.rs`, and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | Lifecycle state globals now stay behind ECStore lifecycle owner helpers and ECStore runtime-source helpers; RustFS AppContext has expiry/transition state interfaces and resolver coverage; scanner expiry-state access still uses the ECStore runtime `expiry_state_handle` boundary until scanner gets an injected provider. |
|
||||
| `GLOBAL_REPLICATION_POOL`, `GLOBAL_REPLICATION_STATS`, `GLOBAL_BUCKET_MONITOR` | `crates/ecstore/src/bucket/replication/*`, `crates/ecstore/src/runtime/global.rs` | Runtime migration target | Replication pool/stat access now stays behind replication owner and ECStore runtime-source helpers; bucket-monitor direct access now stays behind ECStore runtime helpers while AppContext/runtime-source resolvers remain the caller boundary. |
|
||||
| `GLOBAL_TIER_CONFIG_MGR`, `GLOBAL_STORAGE_CLASS`, `GLOBAL_CONFIG_SYS`, `GLOBAL_SERVER_CONFIG` | `crates/ecstore/src/config`, `crates/config`, `rustfs/src/app/context/runtime_sources.rs` | Runtime migration target | Tier config manager reads and reloads now use the ECStore runtime-source helper; move remaining config state through config/runtime-source owners only, without combining storage-class behavior or persistence changes. |
|
||||
| `GLOBAL_EVENT_NOTIFIER`, `GLOBAL_NOTIFICATION_SYS` | `crates/ecstore/src/runtime/global.rs`, `crates/ecstore/src/runtime/sources.rs`, and `crates/ecstore/src/services/*` | Runtime migration target | `GLOBAL_EVENT_NOTIFIER` and `GLOBAL_NOTIFICATION_SYS` access now stay behind ECStore runtime-source and notification owner helpers; move remaining notification ownership only through notify/runtime-source boundaries. |
|
||||
|
||||
@@ -29,7 +29,7 @@ pub use interfaces::*;
|
||||
use super::storage_api::context::bucket::metadata_sys::BucketMetadataSys;
|
||||
use super::storage_api::context::runtime::{
|
||||
BucketBandwidthMonitor, DailyAllTierStats, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr, TransitionState,
|
||||
};
|
||||
use super::storage_api::context::{ECStore, EndpointServerPools};
|
||||
use crate::config::RustFSBufferConfig;
|
||||
@@ -248,6 +248,11 @@ pub fn resolve_expiry_state_handle() -> Option<Arc<RwLock<ExpiryState>>> {
|
||||
resolve_expiry_state_handle_with(get_global_app_context())
|
||||
}
|
||||
|
||||
/// Resolve lifecycle transition state using AppContext-first precedence.
|
||||
pub fn resolve_transition_state_handle() -> Option<Arc<TransitionState>> {
|
||||
resolve_transition_state_handle_with(get_global_app_context())
|
||||
}
|
||||
|
||||
/// Resolve server config using AppContext-first precedence.
|
||||
pub fn resolve_server_config() -> Option<Config> {
|
||||
resolve_server_config_with(get_global_app_context())
|
||||
@@ -444,6 +449,10 @@ fn resolve_expiry_state_handle_with(context: Option<Arc<AppContext>>) -> Option<
|
||||
context.map(|context| context.expiry_state().handle())
|
||||
}
|
||||
|
||||
fn resolve_transition_state_handle_with(context: Option<Arc<AppContext>>) -> Option<Arc<TransitionState>> {
|
||||
context.map(|context| context.transition_state().handle())
|
||||
}
|
||||
|
||||
fn resolve_server_config_with(context: Option<Arc<AppContext>>) -> Option<Config> {
|
||||
context.and_then(|context| context.server_config().get())
|
||||
}
|
||||
@@ -485,7 +494,7 @@ mod tests {
|
||||
EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface,
|
||||
LockClientInterface, LockClientsInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface,
|
||||
RegionInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, TransitionStateInterface,
|
||||
};
|
||||
use crate::config::{RustFSBufferConfig, WorkloadProfile};
|
||||
use async_trait::async_trait;
|
||||
@@ -798,6 +807,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
struct TestTransitionStateInterface {
|
||||
transition_state: Arc<TransitionState>,
|
||||
}
|
||||
|
||||
impl TransitionStateInterface for TestTransitionStateInterface {
|
||||
fn handle(&self) -> Arc<TransitionState> {
|
||||
self.transition_state.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct TestServerConfigInterface {
|
||||
config: Option<Config>,
|
||||
published: Arc<AtomicUsize>,
|
||||
@@ -937,6 +956,7 @@ mod tests {
|
||||
};
|
||||
let tier_config = TierConfigMgr::new();
|
||||
let context_expiry_state = ExpiryState::new();
|
||||
let context_transition_state = TransitionState::new();
|
||||
let server_config = Config::new();
|
||||
let context_server_config_published = Arc::new(AtomicUsize::new(0));
|
||||
let context_storage_class_published = Arc::new(AtomicUsize::new(0));
|
||||
@@ -1047,6 +1067,9 @@ mod tests {
|
||||
expiry_state: Arc::new(TestExpiryStateInterface {
|
||||
expiry_state: context_expiry_state.clone(),
|
||||
}),
|
||||
transition_state: Arc::new(TestTransitionStateInterface {
|
||||
transition_state: context_transition_state.clone(),
|
||||
}),
|
||||
server_config: Arc::new(TestServerConfigInterface {
|
||||
config: Some(server_config.clone()),
|
||||
published: context_server_config_published.clone(),
|
||||
@@ -1176,6 +1199,10 @@ mod tests {
|
||||
&resolve_expiry_state_handle_with(Some(context.clone())).expect("context expiry state"),
|
||||
&context_expiry_state
|
||||
));
|
||||
assert!(Arc::ptr_eq(
|
||||
&resolve_transition_state_handle_with(Some(context.clone())).expect("context transition state"),
|
||||
&context_transition_state
|
||||
));
|
||||
assert_eq!(
|
||||
resolve_server_config_with(Some(context.clone())).expect("context server config"),
|
||||
server_config
|
||||
@@ -1221,6 +1248,7 @@ mod tests {
|
||||
assert!(resolve_region_with(None).is_none());
|
||||
assert!(resolve_tier_config_handle_with(None).is_none());
|
||||
assert!(resolve_expiry_state_handle_with(None).is_none());
|
||||
assert!(resolve_transition_state_handle_with(None).is_none());
|
||||
assert!(resolve_server_config_with(None).is_none());
|
||||
assert!(!publish_server_config_with(None, Config::new()));
|
||||
assert!(!publish_storage_class_config_with(None, StorageClassConfig::default()));
|
||||
|
||||
@@ -23,7 +23,8 @@ use super::handles::{
|
||||
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,
|
||||
default_storage_class_interface, default_tier_config_interface, default_tier_stats_interface, oidc_interface,
|
||||
default_storage_class_interface, default_tier_config_interface, default_tier_stats_interface,
|
||||
default_transition_state_interface, oidc_interface,
|
||||
};
|
||||
use super::interfaces::{
|
||||
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
|
||||
@@ -31,7 +32,7 @@ use super::interfaces::{
|
||||
KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface,
|
||||
NotifyInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface,
|
||||
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, TransitionStateInterface,
|
||||
};
|
||||
use rustfs_iam::{oidc::OidcSys, store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_kms::KmsServiceManager;
|
||||
@@ -69,6 +70,7 @@ pub struct AppContext {
|
||||
region: Arc<dyn RegionInterface>,
|
||||
tier_config: Arc<dyn TierConfigInterface>,
|
||||
expiry_state: Arc<dyn ExpiryStateInterface>,
|
||||
transition_state: Arc<dyn TransitionStateInterface>,
|
||||
server_config: Arc<dyn ServerConfigInterface>,
|
||||
storage_class: Arc<dyn StorageClassInterface>,
|
||||
buffer_config: Arc<dyn BufferConfigInterface>,
|
||||
@@ -105,6 +107,7 @@ impl AppContext {
|
||||
region: default_region_interface(),
|
||||
tier_config: default_tier_config_interface(),
|
||||
expiry_state: default_expiry_state_interface(),
|
||||
transition_state: default_transition_state_interface(),
|
||||
server_config: default_server_config_interface(),
|
||||
storage_class: default_storage_class_interface(),
|
||||
buffer_config: default_buffer_config_interface(),
|
||||
@@ -238,6 +241,10 @@ impl AppContext {
|
||||
self.expiry_state.clone()
|
||||
}
|
||||
|
||||
pub fn transition_state(&self) -> Arc<dyn TransitionStateInterface> {
|
||||
self.transition_state.clone()
|
||||
}
|
||||
|
||||
pub fn server_config(&self) -> Arc<dyn ServerConfigInterface> {
|
||||
self.server_config.clone()
|
||||
}
|
||||
@@ -280,6 +287,7 @@ pub(super) struct AppContextTestInterfaces {
|
||||
pub(super) region: Arc<dyn RegionInterface>,
|
||||
pub(super) tier_config: Arc<dyn TierConfigInterface>,
|
||||
pub(super) expiry_state: Arc<dyn ExpiryStateInterface>,
|
||||
pub(super) transition_state: Arc<dyn TransitionStateInterface>,
|
||||
pub(super) server_config: Arc<dyn ServerConfigInterface>,
|
||||
pub(super) storage_class: Arc<dyn StorageClassInterface>,
|
||||
pub(super) buffer_config: Arc<dyn BufferConfigInterface>,
|
||||
@@ -317,6 +325,7 @@ impl AppContext {
|
||||
region: interfaces.region,
|
||||
tier_config: interfaces.tier_config,
|
||||
expiry_state: interfaces.expiry_state,
|
||||
transition_state: interfaces.transition_state,
|
||||
server_config: interfaces.server_config,
|
||||
storage_class: interfaces.storage_class,
|
||||
buffer_config: interfaces.buffer_config,
|
||||
|
||||
@@ -16,7 +16,7 @@ use super::super::storage_api::context::EndpointServerPools;
|
||||
use super::super::storage_api::context::bucket::metadata_sys::BucketMetadataSys;
|
||||
use super::super::storage_api::context::runtime::{
|
||||
BucketBandwidthMonitor, DailyAllTierStats, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr, TransitionState,
|
||||
};
|
||||
use super::interfaces::{
|
||||
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
|
||||
@@ -24,7 +24,7 @@ use super::interfaces::{
|
||||
KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface,
|
||||
NotifyInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface,
|
||||
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface,
|
||||
ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, TransitionStateInterface,
|
||||
};
|
||||
use super::runtime_sources;
|
||||
use crate::config::RustFSBufferConfig;
|
||||
@@ -390,6 +390,16 @@ impl ExpiryStateInterface for ExpiryStateHandle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Default lifecycle transition state interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct TransitionStateHandle;
|
||||
|
||||
impl TransitionStateInterface for TransitionStateHandle {
|
||||
fn handle(&self) -> Arc<TransitionState> {
|
||||
runtime_sources::transition_state()
|
||||
}
|
||||
}
|
||||
|
||||
/// Default server config interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct ServerConfigHandle;
|
||||
@@ -528,6 +538,10 @@ pub fn default_expiry_state_interface() -> Arc<dyn ExpiryStateInterface> {
|
||||
Arc::new(ExpiryStateHandle)
|
||||
}
|
||||
|
||||
pub fn default_transition_state_interface() -> Arc<dyn TransitionStateInterface> {
|
||||
Arc::new(TransitionStateHandle)
|
||||
}
|
||||
|
||||
pub fn default_server_config_interface() -> Arc<dyn ServerConfigInterface> {
|
||||
Arc::new(ServerConfigHandle)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use super::super::storage_api::context::EndpointServerPools;
|
||||
use super::super::storage_api::context::bucket::metadata_sys::BucketMetadataSys;
|
||||
use super::super::storage_api::context::runtime::{
|
||||
BucketBandwidthMonitor, DailyAllTierStats, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr, TransitionState,
|
||||
};
|
||||
use crate::config::RustFSBufferConfig;
|
||||
use async_trait::async_trait;
|
||||
@@ -197,6 +197,11 @@ pub trait ExpiryStateInterface: Send + Sync {
|
||||
fn handle(&self) -> Arc<RwLock<ExpiryState>>;
|
||||
}
|
||||
|
||||
/// Lifecycle transition state interface for transition queues and tier stats.
|
||||
pub trait TransitionStateInterface: Send + Sync {
|
||||
fn handle(&self) -> Arc<TransitionState>;
|
||||
}
|
||||
|
||||
/// Server config interface for application-layer and server modules.
|
||||
pub trait ServerConfigInterface: Send + Sync {
|
||||
fn get(&self) -> Option<Config>;
|
||||
|
||||
@@ -18,10 +18,11 @@ use super::super::storage_api::context::EndpointServerPools;
|
||||
use super::super::storage_api::context::bucket::metadata_sys::BucketMetadataSys;
|
||||
use super::super::storage_api::context::runtime::{
|
||||
BucketBandwidthMonitor, DailyAllTierStats, DynReplicationPool, ExpiryState, NotificationSys, ReplicationStats,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr, 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_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,
|
||||
ScannerMetricsReport, StorageClassConfig, TierConfigMgr, TransitionState, 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_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, get_global_transition_state, global_rustfs_port, set_global_storage_class,
|
||||
};
|
||||
use crate::config::{RustFSBufferConfig, get_global_buffer_config};
|
||||
use rustfs_config::server_config::{Config, get_global_server_config, set_global_server_config};
|
||||
@@ -180,6 +181,10 @@ pub fn expiry_state() -> Arc<RwLock<ExpiryState>> {
|
||||
get_global_expiry_state()
|
||||
}
|
||||
|
||||
pub fn transition_state() -> Arc<TransitionState> {
|
||||
get_global_transition_state()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn object_store() -> Option<Arc<ECStore>> {
|
||||
super::super::storage_api::context::runtime::new_object_layer_fn()
|
||||
|
||||
@@ -125,6 +125,7 @@ pub(crate) mod runtime {
|
||||
pub(crate) type ScannerMetricsReport = rustfs_common::metrics::ScannerMetricsReport;
|
||||
pub(crate) type StorageClassConfig = crate::storage::storage_api::ecstore_config::storageclass::Config;
|
||||
pub(crate) type TierConfigMgr = crate::storage::storage_api::TierConfigMgr;
|
||||
pub(crate) type TransitionState = crate::storage::storage_api::TransitionState;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) type TierConfig = crate::storage::storage_api::ecstore_tier::tier_config::TierConfig;
|
||||
@@ -171,6 +172,10 @@ pub(crate) mod runtime {
|
||||
crate::storage::storage_api::get_global_expiry_state()
|
||||
}
|
||||
|
||||
pub(crate) fn get_global_transition_state() -> Arc<TransitionState> {
|
||||
crate::storage::storage_api::get_global_transition_state()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new_object_layer_fn() -> Option<Arc<crate::storage::storage_api::ECStore>> {
|
||||
crate::storage::storage_api::ecstore_global::new_object_layer_fn()
|
||||
|
||||
@@ -515,6 +515,7 @@ pub(crate) type ReplicationStats = ecstore_bucket::replication::ReplicationStats
|
||||
pub(crate) type SetupType = ecstore_layout::SetupType;
|
||||
pub(crate) type StorageError = ecstore_error::StorageError;
|
||||
pub(crate) type TierConfigMgr = ecstore_tier::TierConfigMgr;
|
||||
pub(crate) type TransitionState = ecstore_bucket::lifecycle::bucket_lifecycle_ops::TransitionState;
|
||||
pub(crate) type Error = ecstore_error::Error;
|
||||
pub(crate) type Result<T> = ecstore_error::Result<T>;
|
||||
pub(crate) type UpdateMetadataOpts = ecstore_disk::UpdateMetadataOpts;
|
||||
@@ -582,6 +583,10 @@ pub(crate) fn get_global_expiry_state() -> Arc<tokio::sync::RwLock<ExpiryState>>
|
||||
ecstore_bucket::lifecycle::bucket_lifecycle_ops::get_global_expiry_state()
|
||||
}
|
||||
|
||||
pub(crate) fn get_global_transition_state() -> Arc<TransitionState> {
|
||||
ecstore_bucket::lifecycle::bucket_lifecycle_ops::get_global_transition_state()
|
||||
}
|
||||
|
||||
pub(crate) async fn try_migrate_bucket_metadata(store: Arc<ECStore>) {
|
||||
ecstore_bucket::migration::try_migrate_bucket_metadata(store).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user