diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index 86b1d2fd4..d5dfd589f 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,7 +5,7 @@ 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-runtime-notification-config-fallback-removal` +- Branch: `overtrue/arch-runtime-optional-handle-fallback-removal` - 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/API-167/API-168/API-169/API-170/API-171/API-172/API-173/API-174/API-175/API-176/API-177/API-178/API-179/API-180/API-181/API-182/API-183/API-184/API-185/API-186/API-187/API-188/API-189/API-190/API-191/API-192/API-193/API-194/API-195/API-196/API-197/API-198/API-199/API-200/API-201/API-202/API-203/API-204/API-205/API-206/API-207/API-208/API-209/API-210/API-211/API-212/API-213/API-214/API-215/API-216/API-217/API-218/API-219/API-220/API-221/API-222/API-223/API-224/API-225/API-226/API-227/API-228/API-229/API-230/API-231/API-232/API-233/API-234/API-235/API-236/API-237/API-238/API-239/API-240/API-241/API-242/API-243/API-244/API-245/API-246/API-247/API-248/API-249/API-250/API-251/API-252/API-253/API-254/CTX-002`. - Current baseline also includes API-255 from PR #3923, API-256 from PR #3925, CFG-009 from PR #3927, C-007/C-009 from PR #3935, C-008/C-010 @@ -16,23 +16,23 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block GLOB-007 admin object-store/notification/server-config consumer batch from PR #3943, the GLOB-007 admin runtime helper alias batch from PR #3944, the GLOB-007 storage/server runtime facade consumer batch from PR #3946, the - GLOB-007 app runtime facade consumer batch from PR #3947, the pending - GLOB-007 core runtime facade consumer batch from PR #3948, and the - GLOB-007 runtime facade alias sweep merged into that base branch from - PR #3949, and the GLOB-007 object-store fallback removal from PR #3950, - which is merged into that pending base branch. -- Current phase PR: GLOB-007 notification-system/server-config fallback removal. -- Based on: `overtrue/arch-global-core-runtime-consumer-batch` after PR #3950 - was merged into that branch while PR #3948 is pending. + GLOB-007 app runtime facade consumer batch from PR #3947, the GLOB-007 core + runtime facade consumer batch from PR #3948, the GLOB-007 runtime facade + alias sweep from PR #3949, the GLOB-007 object-store fallback removal from + PR #3950, and the GLOB-007 notification-system/server-config fallback + removal from PR #3951. +- Current phase PR: GLOB-007 optional runtime handle fallback removal. +- Based on: `origin/main` after PR #3951 merged. - PR type for this branch: `ci-gate`. -- Runtime behavior changes: notification-system and server-config read paths - now require AppContext instead of falling back to legacy globals; server-config - publish keeps the no-context startup write path. -- Rust code changes: remove the legacy global notification-system and - server-config read fallbacks from the AppContext resolver family. +- Runtime behavior changes: optional runtime reads for token signing key, + bucket metadata, endpoint pools, bucket monitor, replication handles, boot + time, deployment ID, lock clients, and region now require AppContext instead + of falling back to legacy globals. +- Rust code changes: remove the legacy global fallbacks from those optional + AppContext resolver families. - CI/script changes: none intended. -- Docs changes: update this progress ledger for the notification-system and - server-config fallback removal. +- Docs changes: update this progress ledger for the optional handle fallback + removal. ## Phase 0 Tasks @@ -2816,6 +2816,10 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block - Current slice: remove the legacy global notification-system and server-config read fallbacks from the AppContext resolver family while preserving the server-config publish path used during startup. + - Current slice: remove the legacy global fallbacks from optional runtime + handle/read resolvers for token signing key, bucket metadata, endpoints, + bucket monitor, replication handles, boot time, deployment ID, lock + clients, and region. - Remaining work: remove the next fallback family per PR only after scans prove no production caller depends on it. - Verification: focused RustFS compile and admin test-target compile, @@ -6084,6 +6088,9 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| +| Quality/architecture | pass | GLOB-007 removes a broad optional-handle resolver fallback batch, keeping absent AppContext from consulting legacy globals for token signing key, bucket metadata, endpoints, bucket monitor, replication, boot, deployment, lock, and region reads. | +| Migration preservation | pass | Action credentials, concrete default-returning runtime families, startup publishers, KMS/TLS/IAM readiness initialization, scanner metrics, S3 Select, local node name, tier config, expiry state, performance metrics, and buffer config fallbacks are intentionally left unchanged for later slices. | +| Testing/verification | pass | Focused RustFS compile/test, formatting, architecture guard, optional-handle fallback residual scan, diff hygiene, diff-added Rust risk scan, and full `make pre-pr` are required before PR. | | Quality/architecture | pass | GLOB-007 removes the notification-system and server-config resolver read fallbacks, keeping no-context reads from consulting legacy globals while preserving explicit AppContext interfaces. | | Migration preservation | pass | Server-config publishing keeps the no-context startup write path; notification-system and server-config consumers already route through current runtime facades, so initialized AppContext behavior remains unchanged. | | Testing/verification | pass | Focused RustFS compile, formatting, architecture guard, notification/server-config fallback residual scan, diff hygiene, diff-added Rust risk scan, and full `make pre-pr` passed before PR. | @@ -6468,6 +6475,20 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block Passed before push: +- Issue #660 GLOB-007 optional runtime handle fallback removal: + - Branch freshness check: rebased onto `origin/main` after PR #3951 merged. + - `cargo test -p rustfs --lib app::context::tests::resolver_helpers_are_context_first_and_fallback_when_context_is_absent`: + passed. + - `cargo check -p rustfs --lib`: passed. + - `cargo fmt --all`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - Optional-handle fallback residual scan: passed. + - Diff-added Rust risk scan: passed. + - Three-expert review: passed. + - `make pre-pr`: passed (`nextest`: 6917 passed, 112 skipped; doctests passed). + - Issue #660 GLOB-007 notification-system/server-config fallback removal: - Branch freshness check: prepared from `overtrue/arch-runtime-object-store-fallback-removal`, then based on diff --git a/rustfs/src/app/context.rs b/rustfs/src/app/context.rs index 0f923e1ef..cdf365a3c 100644 --- a/rustfs/src/app/context.rs +++ b/rustfs/src/app/context.rs @@ -102,12 +102,12 @@ pub fn resolve_ready_iam_handle() -> rustfs_iam::error::Result Option { - resolve_token_signing_key_with(get_global_app_context(), runtime_sources::token_signing_key) + resolve_token_signing_key_with(get_global_app_context(), || None) } /// Resolve bucket metadata handle using AppContext-first precedence. pub fn resolve_bucket_metadata_handle() -> Option>> { - resolve_bucket_metadata_handle_with(get_global_app_context(), || default_bucket_metadata_interface().handle()) + resolve_bucket_metadata_handle_with(get_global_app_context(), || None) } /// Resolve object store handle using AppContext-first precedence. @@ -146,27 +146,27 @@ pub fn resolve_notification_system_for_context(context: Option<&AppContext>) -> /// Resolve endpoints using AppContext-first precedence. pub fn resolve_endpoints_handle() -> Option { - resolve_endpoints_handle_with(get_global_app_context(), || default_endpoints_interface().handle()) + resolve_endpoints_handle_with(get_global_app_context(), || None) } /// Resolve bucket bandwidth monitor using AppContext-first precedence. pub fn resolve_bucket_monitor_handle() -> Option> { - resolve_bucket_monitor_handle_with(get_global_app_context(), || default_bucket_monitor_interface().handle()) + resolve_bucket_monitor_handle_with(get_global_app_context(), || None) } /// Resolve replication pool handle using AppContext-first precedence. pub fn resolve_replication_pool_handle() -> Option> { - resolve_replication_pool_handle_with(get_global_app_context(), || default_replication_pool_interface().handle()) + resolve_replication_pool_handle_with(get_global_app_context(), || None) } /// Resolve replication statistics handle using AppContext-first precedence. pub fn resolve_replication_stats_handle() -> Option> { - resolve_replication_stats_handle_with(get_global_app_context(), || default_replication_stats_interface().handle()) + resolve_replication_stats_handle_with(get_global_app_context(), || None) } /// Resolve boot time using AppContext-first precedence. pub fn resolve_boot_time() -> Option { - resolve_boot_time_with(get_global_app_context(), || default_boot_time_interface().get()) + resolve_boot_time_with(get_global_app_context(), || None) } /// Resolve daily tier transition statistics using AppContext-first precedence. @@ -182,7 +182,7 @@ pub async fn resolve_scanner_metrics_report() -> ScannerMetricsReport { /// Resolve deployment identity using AppContext-first precedence. pub fn resolve_deployment_id() -> Option { - resolve_deployment_id_with(get_global_app_context(), || default_deployment_id_interface().get()) + resolve_deployment_id_with(get_global_app_context(), || None) } /// Resolve runtime port using AppContext-first precedence. @@ -192,12 +192,12 @@ pub fn resolve_runtime_port() -> u16 { /// Resolve lock client using AppContext-first precedence. pub fn resolve_lock_client() -> Option> { - resolve_lock_client_with(get_global_app_context(), || default_lock_client_interface().handle()) + resolve_lock_client_with(get_global_app_context(), || None) } /// Resolve lock clients using AppContext-first precedence. pub fn resolve_lock_clients_handle() -> Option>> { - resolve_lock_clients_handle_with(get_global_app_context(), || default_lock_clients_interface().handle()) + resolve_lock_clients_handle_with(get_global_app_context(), || None) } /// Resolve performance metrics using AppContext-first precedence. @@ -233,7 +233,7 @@ pub fn resolve_action_credentials() -> Option { /// Resolve region using AppContext-first precedence. pub fn resolve_region() -> Option { - resolve_region_with(get_global_app_context(), || default_region_interface().get()) + resolve_region_with(get_global_app_context(), || None) } /// Resolve tier config handle using AppContext-first precedence. @@ -355,19 +355,18 @@ fn resolve_ready_iam_handle_with( fallback() } -fn resolve_token_signing_key_with(context: Option>, fallback: impl FnOnce() -> Option) -> Option { - context - .and_then(|context| context.iam().token_signing_key()) - .or_else(fallback) +fn resolve_token_signing_key_with( + context: Option>, + _fallback: impl FnOnce() -> Option, +) -> Option { + context.and_then(|context| context.iam().token_signing_key()) } fn resolve_bucket_metadata_handle_with( context: Option>, - fallback: impl FnOnce() -> Option>>, + _fallback: impl FnOnce() -> Option>>, ) -> Option>> { - context - .and_then(|context| context.bucket_metadata().handle()) - .or_else(fallback) + context.and_then(|context| context.bucket_metadata().handle()) } fn resolve_notification_system_with( @@ -379,33 +378,30 @@ fn resolve_notification_system_with( fn resolve_bucket_monitor_handle_with( context: Option>, - fallback: impl FnOnce() -> Option>, + _fallback: impl FnOnce() -> Option>, ) -> Option> { - context - .and_then(|context| context.bucket_monitor().handle()) - .or_else(fallback) + context.and_then(|context| context.bucket_monitor().handle()) } fn resolve_replication_pool_handle_with( context: Option>, - fallback: impl FnOnce() -> Option>, + _fallback: impl FnOnce() -> Option>, ) -> Option> { - context - .and_then(|context| context.replication_pool().handle()) - .or_else(fallback) + context.and_then(|context| context.replication_pool().handle()) } fn resolve_replication_stats_handle_with( context: Option>, - fallback: impl FnOnce() -> Option>, + _fallback: impl FnOnce() -> Option>, ) -> Option> { - context - .and_then(|context| context.replication_stats().handle()) - .or_else(fallback) + context.and_then(|context| context.replication_stats().handle()) } -fn resolve_boot_time_with(context: Option>, fallback: impl FnOnce() -> Option) -> Option { - context.and_then(|context| context.boot_time().get()).or_else(fallback) +fn resolve_boot_time_with( + context: Option>, + _fallback: impl FnOnce() -> Option, +) -> Option { + context.and_then(|context| context.boot_time().get()) } fn resolve_daily_tier_stats_with( @@ -437,13 +433,13 @@ fn resolve_object_store_handle_with( fn resolve_endpoints_handle_with( context: Option>, - fallback: impl FnOnce() -> Option, + _fallback: impl FnOnce() -> Option, ) -> Option { - context.and_then(|context| context.endpoints().handle()).or_else(fallback) + context.and_then(|context| context.endpoints().handle()) } -fn resolve_deployment_id_with(context: Option>, fallback: impl FnOnce() -> Option) -> Option { - context.and_then(|context| context.deployment_id().get()).or_else(fallback) +fn resolve_deployment_id_with(context: Option>, _fallback: impl FnOnce() -> Option) -> Option { + context.and_then(|context| context.deployment_id().get()) } fn resolve_runtime_port_with(context: Option>, fallback: impl FnOnce() -> u16) -> u16 { @@ -452,16 +448,16 @@ fn resolve_runtime_port_with(context: Option>, fallback: impl Fn fn resolve_lock_client_with( context: Option>, - fallback: impl FnOnce() -> Option>, + _fallback: impl FnOnce() -> Option>, ) -> Option> { - context.and_then(|context| context.lock_client().handle()).or_else(fallback) + context.and_then(|context| context.lock_client().handle()) } fn resolve_lock_clients_handle_with( context: Option>, - fallback: impl FnOnce() -> Option>>, + _fallback: impl FnOnce() -> Option>>, ) -> Option>> { - context.and_then(|context| context.lock_clients().handle()).or_else(fallback) + context.and_then(|context| context.lock_clients().handle()) } fn resolve_performance_metrics_with( @@ -518,9 +514,9 @@ fn resolve_action_credentials_with( fn resolve_region_with( context: Option>, - fallback: impl FnOnce() -> Option, + _fallback: impl FnOnce() -> Option, ) -> Option { - context.map(|context| context.region().get()).unwrap_or_else(fallback) + context.and_then(|context| context.region().get()) } fn resolve_tier_config_handle_with( @@ -1306,21 +1302,14 @@ mod tests { assert!(!resolve_iam_ready_with(None, || false)); assert!(resolve_iam_handle_with(None, || None).is_none()); assert!(resolve_oidc_handle_with(None).is_none()); + assert!(resolve_token_signing_key_with(None, || Some(fallback_token_signing_key.clone())).is_none()); assert!(!publish_oidc_handle_with(None, context_oidc)); - assert!(Arc::ptr_eq( - &resolve_bucket_metadata_handle_with(None, || Some(bucket_metadata.clone())).expect("fallback bucket metadata"), - &bucket_metadata - )); + assert!(resolve_bucket_metadata_handle_with(None, || Some(bucket_metadata.clone())).is_none()); + assert!(resolve_bucket_monitor_handle_with(None, || default_bucket_monitor_interface().handle()).is_none()); + assert!(resolve_replication_pool_handle_with(None, || default_replication_pool_interface().handle()).is_none()); assert!(resolve_object_store_handle_with(None, || Some(object_store.clone())).is_none()); - assert!(Arc::ptr_eq( - &resolve_replication_stats_handle_with(None, || Some(fallback_replication_stats.clone())) - .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_replication_stats_handle_with(None, || Some(fallback_replication_stats.clone())).is_none()); + assert!(resolve_boot_time_with(None, || Some(fallback_boot_time)).is_none()); 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() }) @@ -1328,29 +1317,11 @@ mod tests { .current_cycle, fallback_scanner_metrics.current_cycle ); - assert_eq!( - resolve_endpoints_handle_with(None, || Some(endpoints.clone())) - .expect("fallback endpoints") - .as_ref()[0] - .drives_per_set, - endpoints.as_ref()[0].drives_per_set - ); - assert_eq!( - resolve_deployment_id_with(None, || Some(fallback_deployment_id.clone())).expect("fallback deployment id"), - fallback_deployment_id - ); + assert!(resolve_endpoints_handle_with(None, || Some(endpoints.clone())).is_none()); + assert!(resolve_deployment_id_with(None, || Some(fallback_deployment_id.clone())).is_none()); assert_eq!(resolve_runtime_port_with(None, || fallback_runtime_port), fallback_runtime_port); - assert!(Arc::ptr_eq( - &resolve_lock_client_with(None, || Some(fallback_lock_client.clone())).expect("fallback lock client"), - &fallback_lock_client - )); - assert!(Arc::ptr_eq( - resolve_lock_clients_handle_with(None, || Some(fallback_lock_clients.clone())) - .expect("fallback lock clients") - .get("fallback-node:9000") - .expect("fallback lock client entry"), - &fallback_lock_client - )); + assert!(resolve_lock_client_with(None, || Some(fallback_lock_client.clone())).is_none()); + assert!(resolve_lock_clients_handle_with(None, || Some(fallback_lock_clients.clone())).is_none()); assert!(Arc::ptr_eq( &resolve_performance_metrics_with(None, || fallback_performance_metrics.clone()), &fallback_performance_metrics @@ -1377,10 +1348,7 @@ mod tests { .access_key, fallback_credentials.access_key ); - assert_eq!( - resolve_region_with(None, || Some(fallback_region.clone())).expect("fallback region"), - fallback_region - ); + assert!(resolve_region_with(None, || Some(fallback_region.clone())).is_none()); 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()),