mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
refactor: route admin status metrics through app context (#3780)
This commit is contained in:
@@ -5,13 +5,14 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
## Current Context
|
||||
|
||||
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
||||
- Branch: `overtrue/arch-admin-replication-stats-context`
|
||||
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165`.
|
||||
- Based on: API-164/API-165 local branch stacked on API-163 PR #3777.
|
||||
- Branch: `overtrue/arch-admin-status-metrics-context`
|
||||
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166`.
|
||||
- Based on: API-166 local branch stacked on API-164/API-165 local branch after API-163 PR #3777 merged.
|
||||
- PR type for this branch: `consumer-migration`
|
||||
- Runtime behavior changes: none.
|
||||
- Rust code changes: route admin replication stats reads through AppContext
|
||||
resolvers with legacy global fallback.
|
||||
- Rust code changes: route admin status and metrics reads for boot time, tier
|
||||
transition stats, and scanner metrics through AppContext resolvers with
|
||||
legacy global fallback.
|
||||
- CI/script changes: lock completed owner and test/fuzz boundaries against
|
||||
bare/glob imports, scattered raw ECStore facade subpaths, and startup
|
||||
runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade
|
||||
@@ -20,7 +21,7 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
and storage owner thin bridge regressions, plus app context and notify
|
||||
event-bridge thin module regressions; accept the reviewed AppContext resolver
|
||||
reverse dependencies in the layer baseline.
|
||||
- Docs changes: record the API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166 owner facade cleanup.
|
||||
- Docs changes: record the API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167 owner facade cleanup.
|
||||
|
||||
## Phase 0 Tasks
|
||||
|
||||
@@ -4401,6 +4402,21 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
stats global-read scan, Rust risk scan, branch freshness check, and
|
||||
three-expert review.
|
||||
|
||||
- [x] `API-167` Route admin status and metrics reads through AppContext.
|
||||
- Do: add AppContext interfaces for boot time, daily tier transition stats,
|
||||
and scanner metrics report reads, then route admin replication uptime, tier
|
||||
stats, and scanner status through those resolvers.
|
||||
- Acceptance: admin production handlers no longer directly read
|
||||
`GLOBAL_BOOT_TIME`, `GLOBAL_TransitionState`, or scanner `global_metrics`,
|
||||
while AppContext default adapters keep the existing global fallback.
|
||||
- Must preserve: replication metrics uptime defaults, tier stats filtering,
|
||||
scanner status payload shape, scanner runtime-config reporting, and existing
|
||||
storage owner global initialization.
|
||||
- Verification: RustFS compile coverage, targeted context resolver tests,
|
||||
migration guard, layer guard, formatting, diff hygiene, residual admin
|
||||
status global-read scan, Rust risk scan, branch freshness check, and
|
||||
three-expert review.
|
||||
|
||||
## Next PRs
|
||||
|
||||
1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries.
|
||||
@@ -4455,6 +4471,9 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
| Quality/architecture | pass | API-166 keeps admin replication stats reads behind AppContext resolver boundaries with a storage-owner fallback wrapper. |
|
||||
| Migration preservation | pass | Admin replication metrics, site-replication summaries, bandwidth enrichment, and missing-stats defaults are preserved. |
|
||||
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration/layer guards, diff hygiene, residual stats scan, and Rust risk scan passed for API-166. |
|
||||
| Quality/architecture | pass | API-167 keeps admin boot-time, tier-transition, and scanner metrics reads behind AppContext resolver boundaries. |
|
||||
| Migration preservation | pass | Replication uptime enrichment, tier stats filtering, scanner metrics JSON, and scanner runtime-config reporting are preserved. |
|
||||
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration/layer guards, diff hygiene, residual admin status scan, and Rust risk scan passed for API-167. |
|
||||
|
||||
## Verification Notes
|
||||
|
||||
@@ -4505,6 +4524,22 @@ Passed before push:
|
||||
- Rust risk scan: no new production unwrap/expect, panic/todo/unsafe, or cast
|
||||
risks added.
|
||||
|
||||
- Issue #660 API-167 current slice:
|
||||
- `cargo check --tests -p rustfs`: passed.
|
||||
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
|
||||
passed.
|
||||
- `cargo fmt --all`: passed.
|
||||
- `cargo fmt --all --check`: passed.
|
||||
- `git diff --check`: passed.
|
||||
- `bash -n scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||
- AppContext admin status resolver scan: passed; direct admin production
|
||||
`GLOBAL_BOOT_TIME`, `GLOBAL_TransitionState`, and scanner `global_metrics`
|
||||
reads are removed.
|
||||
- Rust risk scan: no new production unwrap/expect, panic/todo/unsafe, or cast
|
||||
risks added.
|
||||
|
||||
- Issue #660 API-163 current slice:
|
||||
- `cargo check --tests -p rustfs`: passed.
|
||||
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
use crate::admin::auth::validate_admin_request;
|
||||
use crate::admin::router::{AdminOperation, Operation, S3Router};
|
||||
use crate::app::context::resolve_scanner_metrics_report;
|
||||
use crate::auth::{check_key_valid, get_session_token};
|
||||
use crate::server::{ADMIN_PREFIX, RemoteAddr};
|
||||
use http::{HeaderMap, HeaderValue};
|
||||
use hyper::{Method, StatusCode};
|
||||
use matchit::Params;
|
||||
use rustfs_common::metrics::{ScannerMetricsReport, global_metrics};
|
||||
use rustfs_common::metrics::ScannerMetricsReport;
|
||||
use rustfs_credentials::Credentials;
|
||||
use rustfs_policy::policy::action::{Action, AdminAction};
|
||||
use s3s::header::CONTENT_TYPE;
|
||||
@@ -84,7 +85,7 @@ impl Operation for ScannerStatusHandler {
|
||||
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let _cred = validate_scanner_status_request(&req).await?;
|
||||
let response = ScannerStatusResponse {
|
||||
metrics: global_metrics().report().await,
|
||||
metrics: resolve_scanner_metrics_report().await,
|
||||
runtime_config: rustfs_scanner::scanner_runtime_config_status(),
|
||||
};
|
||||
let body = serde_json::to_vec(&response).map_err(|err| {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
#![allow(unused_variables, unused_mut, unused_must_use)]
|
||||
|
||||
use super::super::lifecycle::bucket_lifecycle_ops::GLOBAL_TransitionState;
|
||||
use super::super::{
|
||||
AdminError, DailyAllTierStats, ERR_TIER_ALREADY_EXISTS, ERR_TIER_BACKEND_IN_USE, ERR_TIER_BACKEND_NOT_EMPTY,
|
||||
ERR_TIER_CONNECT_ERR, ERR_TIER_INVALID_CREDENTIALS, ERR_TIER_MISSING_CREDENTIALS, ERR_TIER_NAME_NOT_UPPERCASE,
|
||||
@@ -24,7 +23,9 @@ use crate::{
|
||||
auth::validate_admin_request,
|
||||
router::{AdminOperation, Operation, S3Router},
|
||||
},
|
||||
app::context::{resolve_notification_system, resolve_object_store_handle, resolve_tier_config_handle},
|
||||
app::context::{
|
||||
resolve_daily_tier_stats, resolve_notification_system, resolve_object_store_handle, resolve_tier_config_handle,
|
||||
},
|
||||
auth::{check_key_valid, get_session_token},
|
||||
server::{ADMIN_PREFIX, RemoteAddr},
|
||||
storage::request_context::spawn_traced,
|
||||
@@ -748,7 +749,7 @@ impl Operation for GetTierInfo {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let info = filter_tier_stats(GLOBAL_TransitionState.get_daily_all_tier_stats(), tier_name);
|
||||
let info = filter_tier_stats(resolve_daily_tier_stats(), tier_name);
|
||||
|
||||
let data = serde_json::to_vec(&info)
|
||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("marshal tier err {e}")))?;
|
||||
|
||||
@@ -135,10 +135,6 @@ mod ecstore_error {
|
||||
pub(crate) use crate::storage::ecstore_error::StorageError;
|
||||
}
|
||||
|
||||
mod ecstore_global {
|
||||
pub(crate) use crate::storage::ecstore_global::GLOBAL_BOOT_TIME;
|
||||
}
|
||||
|
||||
#[allow(unused_imports)]
|
||||
mod ecstore_layout {
|
||||
pub(crate) use crate::storage::ecstore_layout::{EndpointServerPools, Endpoints, PoolEndpoints};
|
||||
@@ -264,21 +260,6 @@ pub(crate) mod bucket_target_sys {
|
||||
}
|
||||
|
||||
pub(crate) mod lifecycle {
|
||||
pub(crate) mod bucket_lifecycle_ops {
|
||||
use super::super::DailyAllTierStats;
|
||||
|
||||
pub(crate) struct GlobalTransitionStateCompat;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub(crate) static GLOBAL_TransitionState: GlobalTransitionStateCompat = GlobalTransitionStateCompat;
|
||||
|
||||
impl GlobalTransitionStateCompat {
|
||||
pub(crate) fn get_daily_all_tier_stats(&self) -> DailyAllTierStats {
|
||||
super::super::ecstore_bucket::lifecycle::bucket_lifecycle_ops::GLOBAL_TransitionState.get_daily_all_tier_stats()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod tier_last_day_stats {
|
||||
#[cfg(test)]
|
||||
pub(crate) type LastDayTierStats = super::super::ecstore_bucket::lifecycle::tier_last_day_stats::LastDayTierStats;
|
||||
@@ -498,16 +479,6 @@ pub(crate) async fn collect_local_metrics(
|
||||
ecstore_metrics::collect_local_metrics(types, opts).await
|
||||
}
|
||||
|
||||
pub(crate) struct BootTimeCompat;
|
||||
|
||||
pub(crate) static GLOBAL_BOOT_TIME: BootTimeCompat = BootTimeCompat;
|
||||
|
||||
impl BootTimeCompat {
|
||||
pub(crate) fn get(&self) -> Option<&'static std::time::SystemTime> {
|
||||
ecstore_global::GLOBAL_BOOT_TIME.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AdminErrorRef(fn() -> &'static AdminError);
|
||||
|
||||
impl Deref for AdminErrorRef {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::GLOBAL_BOOT_TIME;
|
||||
use super::PeerRestClient;
|
||||
use super::bandwidth::monitor::BandwidthDetails;
|
||||
use super::bucket_target_sys::{BucketTargetSys, PutObjectOptions, RemoveObjectOptions, S3ClientError, TargetClient};
|
||||
@@ -26,8 +25,9 @@ use super::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _};
|
||||
use crate::admin::console::{is_console_path, make_console_server};
|
||||
use crate::admin::handlers::oidc::is_oidc_path;
|
||||
use crate::app::context::{
|
||||
resolve_bucket_monitor_handle, resolve_deployment_id, resolve_notification_system, resolve_object_store_handle,
|
||||
resolve_region, resolve_replication_pool_handle, resolve_replication_stats_handle, resolve_server_config,
|
||||
resolve_boot_time, resolve_bucket_monitor_handle, resolve_deployment_id, resolve_notification_system,
|
||||
resolve_object_store_handle, resolve_region, resolve_replication_pool_handle, resolve_replication_stats_handle,
|
||||
resolve_server_config,
|
||||
};
|
||||
use crate::app::object_usecase::DefaultObjectUsecase;
|
||||
use crate::auth::{check_key_valid, get_session_token};
|
||||
@@ -1437,9 +1437,8 @@ async fn build_replication_metrics_response(bucket: &str, route: ReplicationExtR
|
||||
}
|
||||
|
||||
fn replication_metrics_uptime_seconds() -> i64 {
|
||||
GLOBAL_BOOT_TIME
|
||||
.get()
|
||||
.and_then(|boot_time| SystemTime::now().duration_since(*boot_time).ok())
|
||||
resolve_boot_time()
|
||||
.and_then(|boot_time| SystemTime::now().duration_since(boot_time).ok())
|
||||
.map(|uptime| uptime.as_secs() as i64)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
+125
-5
@@ -25,8 +25,10 @@ pub use global::*;
|
||||
pub use handles::*;
|
||||
pub use interfaces::*;
|
||||
|
||||
use super::DailyAllTierStats;
|
||||
use super::ECStore;
|
||||
use super::EndpointServerPools;
|
||||
use super::ScannerMetricsReport;
|
||||
use super::TierConfigMgr;
|
||||
use super::metadata_sys::BucketMetadataSys;
|
||||
use super::new_object_layer_fn;
|
||||
@@ -38,7 +40,7 @@ use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_kms::KmsServiceManager;
|
||||
use rustfs_lock::LockClient;
|
||||
use rustfs_tls_runtime::{GlobalPublishedOutboundTlsState, TlsGeneration};
|
||||
use std::{future::Future, sync::Arc};
|
||||
use std::{future::Future, sync::Arc, time::SystemTime};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// Resolve KMS runtime service manager using AppContext-first precedence.
|
||||
@@ -116,6 +118,22 @@ pub fn resolve_replication_stats_handle() -> Option<Arc<ReplicationStats>> {
|
||||
resolve_replication_stats_handle_with(get_global_app_context(), || default_replication_stats_interface().handle())
|
||||
}
|
||||
|
||||
/// Resolve boot time using AppContext-first precedence.
|
||||
pub fn resolve_boot_time() -> Option<SystemTime> {
|
||||
resolve_boot_time_with(get_global_app_context(), || default_boot_time_interface().get())
|
||||
}
|
||||
|
||||
/// Resolve daily tier transition statistics using AppContext-first precedence.
|
||||
pub fn resolve_daily_tier_stats() -> DailyAllTierStats {
|
||||
resolve_daily_tier_stats_with(get_global_app_context(), || default_tier_stats_interface().daily_all())
|
||||
}
|
||||
|
||||
/// Resolve scanner metrics report using AppContext-first precedence.
|
||||
pub async fn resolve_scanner_metrics_report() -> ScannerMetricsReport {
|
||||
resolve_scanner_metrics_report_with(get_global_app_context(), || async { default_scanner_metrics_interface().report().await })
|
||||
.await
|
||||
}
|
||||
|
||||
/// Resolve deployment identity using AppContext-first precedence.
|
||||
pub fn resolve_deployment_id() -> Option<String> {
|
||||
resolve_deployment_id_with(get_global_app_context(), || default_deployment_id_interface().get())
|
||||
@@ -241,6 +259,29 @@ fn resolve_replication_stats_handle_with(
|
||||
.or_else(fallback)
|
||||
}
|
||||
|
||||
fn resolve_boot_time_with(context: Option<Arc<AppContext>>, fallback: impl FnOnce() -> Option<SystemTime>) -> Option<SystemTime> {
|
||||
context.and_then(|context| context.boot_time().get()).or_else(fallback)
|
||||
}
|
||||
|
||||
fn resolve_daily_tier_stats_with(
|
||||
context: Option<Arc<AppContext>>,
|
||||
fallback: impl FnOnce() -> DailyAllTierStats,
|
||||
) -> DailyAllTierStats {
|
||||
context.map_or_else(fallback, |context| context.tier_stats().daily_all())
|
||||
}
|
||||
|
||||
async fn resolve_scanner_metrics_report_with<F, Fut>(context: Option<Arc<AppContext>>, fallback: F) -> ScannerMetricsReport
|
||||
where
|
||||
F: FnOnce() -> Fut,
|
||||
Fut: Future<Output = ScannerMetricsReport>,
|
||||
{
|
||||
if let Some(context) = context {
|
||||
return context.scanner_metrics().report().await;
|
||||
}
|
||||
|
||||
fallback().await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn resolve_object_store_handle_with(
|
||||
context: Option<Arc<AppContext>>,
|
||||
@@ -330,16 +371,17 @@ mod tests {
|
||||
default_replication_pool_interface,
|
||||
};
|
||||
use crate::app::context::interfaces::{
|
||||
ActionCredentialInterface, BucketMetadataInterface, BufferConfigInterface, DeploymentIdInterface, EndpointsInterface,
|
||||
IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface,
|
||||
OutboundTlsRuntimeInterface, RegionInterface, ReplicationStatsInterface, RuntimePortInterface, ServerConfigInterface,
|
||||
TierConfigInterface,
|
||||
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BufferConfigInterface, DeploymentIdInterface,
|
||||
EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface,
|
||||
OutboundTlsRuntimeInterface, RegionInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface,
|
||||
ServerConfigInterface, TierConfigInterface, TierStatsInterface,
|
||||
};
|
||||
use crate::config::{RustFSBufferConfig, WorkloadProfile};
|
||||
use async_trait::async_trait;
|
||||
use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_lock::{LocalClient, LockClient};
|
||||
use std::path::PathBuf;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use tempfile::TempDir;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
@@ -412,6 +454,37 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
struct TestBootTimeInterface {
|
||||
boot_time: Option<SystemTime>,
|
||||
}
|
||||
|
||||
impl BootTimeInterface for TestBootTimeInterface {
|
||||
fn get(&self) -> Option<SystemTime> {
|
||||
self.boot_time.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct TestTierStatsInterface {
|
||||
daily_stats: DailyAllTierStats,
|
||||
}
|
||||
|
||||
impl TierStatsInterface for TestTierStatsInterface {
|
||||
fn daily_all(&self) -> DailyAllTierStats {
|
||||
self.daily_stats.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct TestScannerMetricsInterface {
|
||||
report: ScannerMetricsReport,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ScannerMetricsInterface for TestScannerMetricsInterface {
|
||||
async fn report(&self) -> ScannerMetricsReport {
|
||||
self.report.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct TestEndpointsInterface {
|
||||
endpoints: Option<EndpointServerPools>,
|
||||
}
|
||||
@@ -571,6 +644,20 @@ mod tests {
|
||||
let bucket_metadata = Arc::new(RwLock::new(BucketMetadataSys::new(object_store.clone())));
|
||||
let context_replication_stats = Arc::new(ReplicationStats::new());
|
||||
let fallback_replication_stats = Arc::new(ReplicationStats::new());
|
||||
let context_boot_time = SystemTime::UNIX_EPOCH + Duration::from_secs(10);
|
||||
let fallback_boot_time = SystemTime::UNIX_EPOCH + Duration::from_secs(20);
|
||||
let mut context_daily_tier_stats = DailyAllTierStats::new();
|
||||
context_daily_tier_stats.insert("CONTEXT".to_string(), Default::default());
|
||||
let mut fallback_daily_tier_stats = DailyAllTierStats::new();
|
||||
fallback_daily_tier_stats.insert("FALLBACK".to_string(), Default::default());
|
||||
let context_scanner_metrics = ScannerMetricsReport {
|
||||
current_cycle: 7,
|
||||
..Default::default()
|
||||
};
|
||||
let fallback_scanner_metrics = ScannerMetricsReport {
|
||||
current_cycle: 13,
|
||||
..Default::default()
|
||||
};
|
||||
let tier_config = TierConfigMgr::new();
|
||||
let server_config = Config::new();
|
||||
let buffer_config = RustFSBufferConfig::new(WorkloadProfile::AiTraining);
|
||||
@@ -621,6 +708,15 @@ mod tests {
|
||||
replication_stats: Arc::new(TestReplicationStatsInterface {
|
||||
stats: Some(context_replication_stats.clone()),
|
||||
}),
|
||||
boot_time: Arc::new(TestBootTimeInterface {
|
||||
boot_time: Some(context_boot_time),
|
||||
}),
|
||||
tier_stats: Arc::new(TestTierStatsInterface {
|
||||
daily_stats: context_daily_tier_stats.clone(),
|
||||
}),
|
||||
scanner_metrics: Arc::new(TestScannerMetricsInterface {
|
||||
report: context_scanner_metrics.clone(),
|
||||
}),
|
||||
endpoints: Arc::new(TestEndpointsInterface {
|
||||
endpoints: Some(endpoints.clone()),
|
||||
}),
|
||||
@@ -678,6 +774,19 @@ mod tests {
|
||||
&resolve_replication_stats_handle_with(Some(context.clone()), || None).expect("context replication stats"),
|
||||
&context_replication_stats
|
||||
));
|
||||
assert_eq!(
|
||||
resolve_boot_time_with(Some(context.clone()), || Some(fallback_boot_time)).expect("context boot time"),
|
||||
context_boot_time
|
||||
);
|
||||
assert!(
|
||||
resolve_daily_tier_stats_with(Some(context.clone()), || fallback_daily_tier_stats.clone()).contains_key("CONTEXT")
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_scanner_metrics_report_with(Some(context.clone()), || async { fallback_scanner_metrics.clone() })
|
||||
.await
|
||||
.current_cycle,
|
||||
context_scanner_metrics.current_cycle
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_endpoints_handle_with(Some(context.clone()), || None)
|
||||
.expect("context endpoints")
|
||||
@@ -745,6 +854,17 @@ mod tests {
|
||||
.expect("fallback replication stats"),
|
||||
&fallback_replication_stats
|
||||
));
|
||||
assert_eq!(
|
||||
resolve_boot_time_with(None, || Some(fallback_boot_time)).expect("fallback boot time"),
|
||||
fallback_boot_time
|
||||
);
|
||||
assert!(resolve_daily_tier_stats_with(None, || fallback_daily_tier_stats.clone()).contains_key("FALLBACK"));
|
||||
assert_eq!(
|
||||
resolve_scanner_metrics_report_with(None, || async { fallback_scanner_metrics.clone() })
|
||||
.await
|
||||
.current_cycle,
|
||||
fallback_scanner_metrics.current_cycle
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_endpoints_handle_with(None, || Some(endpoints.clone()))
|
||||
.expect("fallback endpoints")
|
||||
|
||||
@@ -14,18 +14,20 @@
|
||||
|
||||
use super::super::{ECStore, set_object_store_resolver};
|
||||
use super::handles::{
|
||||
IamHandle, KmsHandle, default_action_credential_interface, default_bucket_metadata_interface,
|
||||
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_kms_runtime_interface, default_local_node_name_interface, default_lock_client_interface,
|
||||
default_notification_system_interface, default_notify_interface, default_outbound_tls_runtime_interface,
|
||||
default_region_interface, default_replication_pool_interface, default_replication_stats_interface,
|
||||
default_runtime_port_interface, default_server_config_interface, default_tier_config_interface,
|
||||
default_runtime_port_interface, default_scanner_metrics_interface, default_server_config_interface,
|
||||
default_tier_config_interface, default_tier_stats_interface,
|
||||
};
|
||||
use super::interfaces::{
|
||||
ActionCredentialInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, DeploymentIdInterface,
|
||||
EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface,
|
||||
NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface, ReplicationPoolInterface,
|
||||
ReplicationStatsInterface, RuntimePortInterface, ServerConfigInterface, TierConfigInterface,
|
||||
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
|
||||
DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface,
|
||||
LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface,
|
||||
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface,
|
||||
TierConfigInterface, TierStatsInterface,
|
||||
};
|
||||
use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_kms::KmsServiceManager;
|
||||
@@ -46,6 +48,9 @@ pub struct AppContext {
|
||||
bucket_monitor: Arc<dyn BucketMonitorInterface>,
|
||||
replication_pool: Arc<dyn ReplicationPoolInterface>,
|
||||
replication_stats: Arc<dyn ReplicationStatsInterface>,
|
||||
boot_time: Arc<dyn BootTimeInterface>,
|
||||
tier_stats: Arc<dyn TierStatsInterface>,
|
||||
scanner_metrics: Arc<dyn ScannerMetricsInterface>,
|
||||
endpoints: Arc<dyn EndpointsInterface>,
|
||||
deployment_id: Arc<dyn DeploymentIdInterface>,
|
||||
runtime_port: Arc<dyn RuntimePortInterface>,
|
||||
@@ -72,6 +77,9 @@ impl AppContext {
|
||||
bucket_monitor: default_bucket_monitor_interface(),
|
||||
replication_pool: default_replication_pool_interface(),
|
||||
replication_stats: default_replication_stats_interface(),
|
||||
boot_time: default_boot_time_interface(),
|
||||
tier_stats: default_tier_stats_interface(),
|
||||
scanner_metrics: default_scanner_metrics_interface(),
|
||||
endpoints: default_endpoints_interface(),
|
||||
deployment_id: default_deployment_id_interface(),
|
||||
runtime_port: default_runtime_port_interface(),
|
||||
@@ -138,6 +146,18 @@ impl AppContext {
|
||||
self.replication_stats.clone()
|
||||
}
|
||||
|
||||
pub fn boot_time(&self) -> Arc<dyn BootTimeInterface> {
|
||||
self.boot_time.clone()
|
||||
}
|
||||
|
||||
pub fn tier_stats(&self) -> Arc<dyn TierStatsInterface> {
|
||||
self.tier_stats.clone()
|
||||
}
|
||||
|
||||
pub fn scanner_metrics(&self) -> Arc<dyn ScannerMetricsInterface> {
|
||||
self.scanner_metrics.clone()
|
||||
}
|
||||
|
||||
pub fn endpoints(&self) -> Arc<dyn EndpointsInterface> {
|
||||
self.endpoints.clone()
|
||||
}
|
||||
@@ -191,6 +211,9 @@ pub(super) struct AppContextTestInterfaces {
|
||||
pub(super) bucket_monitor: Arc<dyn BucketMonitorInterface>,
|
||||
pub(super) replication_pool: Arc<dyn ReplicationPoolInterface>,
|
||||
pub(super) replication_stats: Arc<dyn ReplicationStatsInterface>,
|
||||
pub(super) boot_time: Arc<dyn BootTimeInterface>,
|
||||
pub(super) tier_stats: Arc<dyn TierStatsInterface>,
|
||||
pub(super) scanner_metrics: Arc<dyn ScannerMetricsInterface>,
|
||||
pub(super) endpoints: Arc<dyn EndpointsInterface>,
|
||||
pub(super) deployment_id: Arc<dyn DeploymentIdInterface>,
|
||||
pub(super) runtime_port: Arc<dyn RuntimePortInterface>,
|
||||
@@ -218,6 +241,9 @@ impl AppContext {
|
||||
bucket_monitor: interfaces.bucket_monitor,
|
||||
replication_pool: interfaces.replication_pool,
|
||||
replication_stats: interfaces.replication_stats,
|
||||
boot_time: interfaces.boot_time,
|
||||
tier_stats: interfaces.tier_stats,
|
||||
scanner_metrics: interfaces.scanner_metrics,
|
||||
endpoints: interfaces.endpoints,
|
||||
deployment_id: interfaces.deployment_id,
|
||||
runtime_port: interfaces.runtime_port,
|
||||
|
||||
@@ -16,15 +16,16 @@ use super::super::EndpointServerPools;
|
||||
use super::super::TierConfigMgr;
|
||||
use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys};
|
||||
use super::super::{
|
||||
get_global_bucket_monitor, get_global_deployment_id, get_global_endpoints_opt, get_global_lock_client,
|
||||
get_global_notification_sys, get_global_region, get_global_replication_pool, get_global_replication_stats,
|
||||
get_global_tier_config_mgr, global_rustfs_port,
|
||||
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_notification_sys, get_global_region,
|
||||
get_global_replication_pool, get_global_replication_stats, get_global_tier_config_mgr, global_rustfs_port,
|
||||
};
|
||||
use super::interfaces::{
|
||||
ActionCredentialInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, DeploymentIdInterface,
|
||||
EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface,
|
||||
NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface, ReplicationPoolInterface,
|
||||
ReplicationStatsInterface, RuntimePortInterface, ServerConfigInterface, TierConfigInterface,
|
||||
ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface,
|
||||
DeploymentIdInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface,
|
||||
LockClientInterface, NotificationSystemInterface, NotifyInterface, OutboundTlsRuntimeInterface, RegionInterface,
|
||||
ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, ScannerMetricsInterface, ServerConfigInterface,
|
||||
TierConfigInterface, TierStatsInterface,
|
||||
};
|
||||
use crate::config::{RustFSBufferConfig, get_global_buffer_config};
|
||||
use async_trait::async_trait;
|
||||
@@ -40,7 +41,7 @@ use rustfs_targets::{EventName, arn::TargetID};
|
||||
use rustfs_tls_runtime::{
|
||||
GlobalPublishedOutboundTlsState, TlsGeneration, load_global_outbound_tls_generation, load_global_outbound_tls_state,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, time::SystemTime};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// Default IAM interface adapter.
|
||||
@@ -182,6 +183,37 @@ impl ReplicationStatsInterface for ReplicationStatsHandle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Default boot time interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct BootTimeHandle;
|
||||
|
||||
impl BootTimeInterface for BootTimeHandle {
|
||||
fn get(&self) -> Option<SystemTime> {
|
||||
get_global_boot_time()
|
||||
}
|
||||
}
|
||||
|
||||
/// Default tier transition statistics interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct TierStatsHandle;
|
||||
|
||||
impl TierStatsInterface for TierStatsHandle {
|
||||
fn daily_all(&self) -> super::super::DailyAllTierStats {
|
||||
get_daily_all_tier_stats()
|
||||
}
|
||||
}
|
||||
|
||||
/// Default scanner metrics report interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct ScannerMetricsHandle;
|
||||
|
||||
#[async_trait]
|
||||
impl ScannerMetricsInterface for ScannerMetricsHandle {
|
||||
async fn report(&self) -> super::super::ScannerMetricsReport {
|
||||
collect_scanner_metrics_report().await
|
||||
}
|
||||
}
|
||||
|
||||
/// Default endpoints interface adapter.
|
||||
#[derive(Default)]
|
||||
pub struct EndpointsHandle;
|
||||
@@ -315,6 +347,18 @@ pub fn default_replication_stats_interface() -> Arc<dyn ReplicationStatsInterfac
|
||||
Arc::new(ReplicationStatsHandle)
|
||||
}
|
||||
|
||||
pub fn default_boot_time_interface() -> Arc<dyn BootTimeInterface> {
|
||||
Arc::new(BootTimeHandle)
|
||||
}
|
||||
|
||||
pub fn default_tier_stats_interface() -> Arc<dyn TierStatsInterface> {
|
||||
Arc::new(TierStatsHandle)
|
||||
}
|
||||
|
||||
pub fn default_scanner_metrics_interface() -> Arc<dyn ScannerMetricsInterface> {
|
||||
Arc::new(ScannerMetricsHandle)
|
||||
}
|
||||
|
||||
pub fn default_endpoints_interface() -> Arc<dyn EndpointsInterface> {
|
||||
Arc::new(EndpointsHandle)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::super::DailyAllTierStats;
|
||||
use super::super::EndpointServerPools;
|
||||
use super::super::ScannerMetricsReport;
|
||||
use super::super::TierConfigMgr;
|
||||
use super::super::metadata_sys::BucketMetadataSys;
|
||||
use super::super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, ReplicationStats};
|
||||
@@ -26,7 +28,7 @@ use rustfs_lock::LockClient;
|
||||
use rustfs_notify::{EventArgs, NotificationError};
|
||||
use rustfs_targets::{EventName, arn::TargetID};
|
||||
use rustfs_tls_runtime::{GlobalPublishedOutboundTlsState, TlsGeneration};
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, time::SystemTime};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// IAM interface for application-layer use-cases.
|
||||
@@ -94,6 +96,22 @@ pub trait ReplicationStatsInterface: Send + Sync {
|
||||
fn handle(&self) -> Option<Arc<ReplicationStats>>;
|
||||
}
|
||||
|
||||
/// Boot time interface for admin metric integration.
|
||||
pub trait BootTimeInterface: Send + Sync {
|
||||
fn get(&self) -> Option<SystemTime>;
|
||||
}
|
||||
|
||||
/// Tier transition statistics interface for admin metric integration.
|
||||
pub trait TierStatsInterface: Send + Sync {
|
||||
fn daily_all(&self) -> DailyAllTierStats;
|
||||
}
|
||||
|
||||
/// Scanner metrics report interface for admin status integration.
|
||||
#[async_trait]
|
||||
pub trait ScannerMetricsInterface: Send + Sync {
|
||||
async fn report(&self) -> ScannerMetricsReport;
|
||||
}
|
||||
|
||||
/// Endpoints interface for application-layer use-cases.
|
||||
pub trait EndpointsInterface: Send + Sync {
|
||||
fn handle(&self) -> Option<EndpointServerPools>;
|
||||
|
||||
@@ -678,6 +678,22 @@ pub(crate) fn get_global_replication_stats() -> Option<Arc<ReplicationStats>> {
|
||||
crate::storage::get_global_replication_stats()
|
||||
}
|
||||
|
||||
pub(crate) type DailyAllTierStats = crate::storage::DailyAllTierStats;
|
||||
|
||||
pub(crate) fn get_global_boot_time() -> Option<std::time::SystemTime> {
|
||||
crate::storage::get_global_boot_time()
|
||||
}
|
||||
|
||||
pub(crate) fn get_daily_all_tier_stats() -> DailyAllTierStats {
|
||||
crate::storage::get_daily_all_tier_stats()
|
||||
}
|
||||
|
||||
pub(crate) type ScannerMetricsReport = rustfs_common::metrics::ScannerMetricsReport;
|
||||
|
||||
pub(crate) async fn collect_scanner_metrics_report() -> ScannerMetricsReport {
|
||||
rustfs_common::metrics::global_metrics().report().await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn boxed_reader<R>(reader: R) -> DynReader
|
||||
where
|
||||
|
||||
@@ -213,6 +213,7 @@ pub(crate) type BucketVersioningSys = ecstore_bucket::versioning_sys::BucketVers
|
||||
pub(crate) type BucketBandwidthMonitor = ecstore_bucket::bandwidth::monitor::Monitor;
|
||||
pub(crate) type CheckPartsResp = ecstore_disk::CheckPartsResp;
|
||||
pub(crate) type CollectMetricsOpts = ecstore_metrics::CollectMetricsOpts;
|
||||
pub(crate) type DailyAllTierStats = ecstore_bucket::lifecycle::tier_last_day_stats::DailyAllTierStats;
|
||||
pub(crate) type DeleteOptions = ecstore_disk::DeleteOptions;
|
||||
pub(crate) type DiskError = ecstore_disk::error::DiskError;
|
||||
pub(crate) type DiskInfo = ecstore_disk::DiskInfo;
|
||||
@@ -305,6 +306,14 @@ pub(crate) fn get_global_replication_stats() -> Option<Arc<ReplicationStats>> {
|
||||
ecstore_bucket::replication::GLOBAL_REPLICATION_STATS.get().cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn get_global_boot_time() -> Option<std::time::SystemTime> {
|
||||
ecstore_global::GLOBAL_BOOT_TIME.get().cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn get_daily_all_tier_stats() -> DailyAllTierStats {
|
||||
ecstore_bucket::lifecycle::bucket_lifecycle_ops::GLOBAL_TransitionState.get_daily_all_tier_stats()
|
||||
}
|
||||
|
||||
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