From fab78f840230babeec7a4db940cf20e7dcd629e5 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Tue, 30 Jun 2026 02:09:52 +0800 Subject: [PATCH] refactor(scanner): use expiry runtime boundary (#4079) --- crates/scanner/src/lib.rs | 6 +++--- crates/scanner/src/storage_api.rs | 8 ++++---- docs/architecture/global-state-inventory.md | 2 +- scripts/check_architecture_migration_rules.sh | 13 +++++++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/scanner/src/lib.rs b/crates/scanner/src/lib.rs index a10958c0b..a0346d020 100644 --- a/crates/scanner/src/lib.rs +++ b/crates/scanner/src/lib.rs @@ -32,7 +32,7 @@ use storage_api::owner::{ EcstoreListPathRawOptions, EcstoreObjectOpts, EcstoreReplicationConfig, EcstoreReplicationConfigurationExt, EcstoreReplicationHealQueueResult, EcstoreReplicationQueueAdmission, EcstoreResultType, EcstoreScanGuard, EcstoreSetDisks, EcstoreStorageError, EcstoreStore, EcstoreTierConfig, EcstoreVersioningApi, HTTPRangeSpec, ObjectIO, ObjectOperations, - ObjectToDelete, ecstore_apply_expiry_rule, ecstore_apply_transition_rule, ecstore_get_global_expiry_state, + ObjectToDelete, ecstore_apply_expiry_rule, ecstore_apply_transition_rule, ecstore_expiry_state_handle, ecstore_get_global_tier_config_mgr, ecstore_get_lifecycle_config, ecstore_get_object_lock_config, ecstore_get_replication_config, ecstore_is_erasure, ecstore_is_erasure_sd, ecstore_is_reserved_or_invalid_bucket, ecstore_list_path_raw, ecstore_path2_bucket_object, ecstore_path2_bucket_object_with_base_path, @@ -288,7 +288,7 @@ pub(crate) async fn list_runtime_tiers() -> Vec { } pub(crate) async fn enqueue_runtime_free_version(oi: ScannerObjectInfo) { - ecstore_get_global_expiry_state().write().await.enqueue_free_version(oi).await; + ecstore_expiry_state_handle().write().await.enqueue_free_version(oi).await; } pub(crate) async fn enqueue_runtime_newer_noncurrent( @@ -297,7 +297,7 @@ pub(crate) async fn enqueue_runtime_newer_noncurrent( event: Event, src: &LcEventSrc, ) -> bool { - ecstore_get_global_expiry_state() + ecstore_expiry_state_handle() .write() .await .enqueue_by_newer_noncurrent(bucket, to_delete_objs, event, src) diff --git a/crates/scanner/src/storage_api.rs b/crates/scanner/src/storage_api.rs index 043fa9f91..e83a47a16 100644 --- a/crates/scanner/src/storage_api.rs +++ b/crates/scanner/src/storage_api.rs @@ -16,7 +16,6 @@ pub(crate) use rustfs_ecstore::api::bucket::bucket_target_sys::BucketTargetSys a pub(crate) use rustfs_ecstore::api::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc as EcstoreLcEventSrc; pub(crate) use rustfs_ecstore::api::bucket::lifecycle::bucket_lifecycle_ops::{ apply_expiry_rule as ecstore_apply_expiry_rule, apply_transition_rule as ecstore_apply_transition_rule, - get_global_expiry_state as ecstore_get_global_expiry_state, }; pub(crate) use rustfs_ecstore::api::bucket::lifecycle::evaluator::Evaluator as EcstoreEvaluator; pub(crate) use rustfs_ecstore::api::bucket::lifecycle::lifecycle::{ @@ -66,8 +65,9 @@ pub(crate) use rustfs_ecstore::api::error::{ Error as EcstoreErrorType, Result as EcstoreResultType, StorageError as EcstoreStorageError, }; pub(crate) use rustfs_ecstore::api::runtime::{ - global_tier_config_mgr as ecstore_get_global_tier_config_mgr, object_store_handle as ecstore_resolve_object_store_handle, - setup_is_erasure as ecstore_is_erasure, setup_is_erasure_sd as ecstore_is_erasure_sd, + expiry_state_handle as ecstore_expiry_state_handle, global_tier_config_mgr as ecstore_get_global_tier_config_mgr, + object_store_handle as ecstore_resolve_object_store_handle, setup_is_erasure as ecstore_is_erasure, + setup_is_erasure_sd as ecstore_is_erasure_sd, }; pub(crate) use rustfs_ecstore::api::set_disk::SetDisks as EcstoreSetDisks; pub(crate) use rustfs_ecstore::api::storage::ECStore as EcstoreStore; @@ -85,7 +85,7 @@ pub(crate) mod owner { EcstoreLifecycle, EcstoreListPathRawOptions, EcstoreObjectOpts, EcstoreReplicationConfig, EcstoreReplicationConfigurationExt, EcstoreReplicationHealQueueResult, EcstoreReplicationQueueAdmission, EcstoreResultType, EcstoreScanGuard, EcstoreSetDisks, EcstoreStorageError, EcstoreStore, EcstoreTierConfig, - EcstoreVersioningApi, ecstore_apply_expiry_rule, ecstore_apply_transition_rule, ecstore_get_global_expiry_state, + EcstoreVersioningApi, ecstore_apply_expiry_rule, ecstore_apply_transition_rule, ecstore_expiry_state_handle, ecstore_get_global_tier_config_mgr, ecstore_get_lifecycle_config, ecstore_get_object_lock_config, ecstore_get_replication_config, ecstore_is_erasure, ecstore_is_erasure_sd, ecstore_is_reserved_or_invalid_bucket, ecstore_list_path_raw, ecstore_path2_bucket_object, ecstore_path2_bucket_object_with_base_path, diff --git a/docs/architecture/global-state-inventory.md b/docs/architecture/global-state-inventory.md index 9a44644a6..d76301eb8 100644 --- a/docs/architecture/global-state-inventory.md +++ b/docs/architecture/global-state-inventory.md @@ -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_IsErasure`, `GLOBAL_IsDistErasure`, `GLOBAL_IsErasureSD`, `GLOBAL_RootDiskThreshold` | `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_ExpiryState`, `GLOBAL_TransitionState`, `GLOBAL_LifecycleSys` | `crates/ecstore/src/bucket/lifecycle/*`, `crates/ecstore/src/runtime/global.rs`, and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | `GLOBAL_LifecycleSys` access now stays behind ECStore runtime-source helpers; `GLOBAL_ExpiryState` remains the first code-bearing ownership candidate because AppContext already has an `ExpiryStateInterface`, resolver, and tests. | +| `GLOBAL_ExpiryState`, `GLOBAL_TransitionState`, `GLOBAL_LifecycleSys` | `crates/ecstore/src/bucket/lifecycle/*`, `crates/ecstore/src/runtime/global.rs`, and `crates/ecstore/src/runtime/sources.rs` | Runtime migration target | `GLOBAL_LifecycleSys` access now stays behind ECStore runtime-source helpers; scanner expiry-state access now uses the ECStore runtime `expiry_state_handle` boundary; `GLOBAL_ExpiryState` remains the first code-bearing ownership candidate because AppContext already has an `ExpiryStateInterface`, resolver, and tests. | | `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_TierConfigMgr`, `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_EventNotifier`, `GLOBAL_NotificationSys` | `crates/ecstore/src/runtime/global.rs`, `crates/ecstore/src/runtime/sources.rs`, and `crates/ecstore/src/services/*` | Runtime migration target | `GLOBAL_EventNotifier` access now stays behind ECStore runtime-source helpers; move remaining notification ownership only through notify/runtime-source boundaries. | diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 427cc9047..d1ce811ac 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -252,6 +252,7 @@ STANDALONE_CRATE_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/standalone SCANNER_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/scanner_bucket_storage_compat_module_hits.txt" SCANNER_STORAGE_API_SOURCE_BYPASS_HITS_FILE="${TMP_DIR}/scanner_storage_api_source_bypass_hits.txt" SCANNER_STORAGE_API_TEST_BYPASS_HITS_FILE="${TMP_DIR}/scanner_storage_api_test_bypass_hits.txt" +SCANNER_EXPIRY_STATE_BYPASS_HITS_FILE="${TMP_DIR}/scanner_expiry_state_bypass_hits.txt" HEAL_STORAGE_API_SOURCE_BYPASS_HITS_FILE="${TMP_DIR}/heal_storage_api_source_bypass_hits.txt" HEAL_STORAGE_API_TEST_BYPASS_HITS_FILE="${TMP_DIR}/heal_storage_api_test_bypass_hits.txt" OBS_STORAGE_API_SOURCE_BYPASS_HITS_FILE="${TMP_DIR}/obs_storage_api_source_bypass_hits.txt" @@ -3141,6 +3142,18 @@ if [[ -s "$SCANNER_STORAGE_API_SOURCE_BYPASS_HITS_FILE" ]]; then report_failure "scanner source files must route ECStore and storage-api symbols through scanner::storage_api: $(paste -sd '; ' "$SCANNER_STORAGE_API_SOURCE_BYPASS_HITS_FILE")" fi +( + cd "$ROOT_DIR" + rg -n --with-filename '\b(?:get_global_expiry_state|ecstore_get_global_expiry_state)\b' \ + crates/scanner/src \ + crates/scanner/tests \ + --glob '*.rs' || true +) >"$SCANNER_EXPIRY_STATE_BYPASS_HITS_FILE" + +if [[ -s "$SCANNER_EXPIRY_STATE_BYPASS_HITS_FILE" ]]; then + report_failure "scanner expiry-state access must use the ECStore runtime expiry_state_handle boundary: $(paste -sd '; ' "$SCANNER_EXPIRY_STATE_BYPASS_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --with-filename 'rustfs_ecstore::api::|rustfs_storage_api' \