From 143833ec451637ecff06077b2a25e784c860cb75 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Tue, 30 Jun 2026 14:01:19 +0800 Subject: [PATCH] test(architecture): guard rustfs owner statics (#4108) --- docs/architecture/global-state-inventory.md | 40 ++++++++++ scripts/check_architecture_migration_rules.sh | 73 +++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/docs/architecture/global-state-inventory.md b/docs/architecture/global-state-inventory.md index d75debae3..114e02188 100644 --- a/docs/architecture/global-state-inventory.md +++ b/docs/architecture/global-state-inventory.md @@ -79,6 +79,46 @@ of reaching across module boundaries. | `TIER_FREE_VERSION_RECOVERY_STARTED`, `TIER_DELETE_JOURNAL_RECOVERY_STARTED` | `crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs` | Cache or constant / owner-local static guard | Lifecycle recovery single-run guards stay local to lifecycle operations. | | `REMOTE_DELETE_INFLIGHT`, `REMOTE_DELETE_LIMITER`, `REMOTE_DELETE_BREAKER`, `REMOTE_TIER_DELETE_TEST_HOOK` | `crates/ecstore/src/bucket/lifecycle/tier_sweeper.rs` | Cache or constant / owner-local static guard | Remote tier delete concurrency, breaker, and test hook state stay local to the tier sweeper owner. | +## RustFS Owner-Local Static Inventory + +These RustFS-side lazy, atomic, and `OnceLock` statics are also part of the +issue #730 process-static audit. They are private implementation details for +their owner modules, not shared runtime ownership handles. This section excludes +allocator statics, public contract/error references, route handler constants, +and `APP_CONTEXT_SINGLETON`, which is classified in the runtime migration +inventory. Generic function-local names such as `CACHE`, `LOCK`, `INIT`, and +`ENABLED` are documented by owner row instead of name-regex guarded. + +| State | Owner boundary | Category | Migration stance | +|---|---|---|---| +| `KEYSTONE_AUTH`, `KEYSTONE_MAPPER`, `KEYSTONE_CONFIG` | `rustfs/src/auth_keystone.rs` | Process-global owner-local state | Keystone authentication provider, identity mapper, and config stay private to the Keystone auth owner. | +| `LICENSE_STATE`, `LICENSE_VERIFIER` | `rustfs/src/license.rs` | Process-global owner-local state | License state and verifier selection stay private to the license owner; callers use license helper functions. | +| `CPU_CONT_GUARD`, `PROFILING_CANCEL_TOKEN` | `rustfs/src/profiling.rs` | Process-global owner-local guard | CPU profiling guard and cancellation state stay private to the profiling owner. | +| `MEMORY_SYSTEM` | `rustfs/src/memory_observability.rs` | Process-global owner-local cache | Memory sampling keeps the `sysinfo::System` cache private to the memory observability owner. | +| `DIAL9_TELEMETRY_GUARD` | `rustfs/src/server/runtime.rs` | Process-global owner-local guard | Dial9 telemetry lifetime state stays private to runtime setup. | +| `DISPLAY_CONFIG_SNAPSHOT`, `GLOBAL_CONFIG_SNAPSHOT` | `rustfs/src/config/snapshot.rs` | Process-global owner-local state | Config snapshots stay private to the config snapshot owner. | +| `BUFFER_CONFIG_SINGLETON`, `BUFFER_PROFILE_ENABLED` | `rustfs/src/config/workload_profiles.rs` | Process-global owner-local state | Workload buffer profile configuration stays private to workload profile helpers. | +| `LEGACY_CREDENTIAL_WARNED_KEYS` | `rustfs/src/config/config_struct.rs` | Process-global owner-local cache | Legacy credential warning de-duplication stays private to config parsing. | +| `CONSOLE_CONFIG` | `rustfs/src/admin/console.rs` | Process-global owner-local state | Console bootstrap config stays private to the admin console owner. | +| `ACTIVE_HTTP_REQUESTS` | `rustfs/src/server/http.rs` | Process-global owner-local counter | HTTP request inflight accounting stays private to the HTTP server owner. | +| Function-local `CACHE` and `LOCK` statics | `rustfs/src/server/readiness.rs` | Cache or constant / owner-local cache | Readiness and cluster-health caches stay function-local to readiness probes. | +| `USE_STARSHARD_CACHE`, `BUCKET_CACHE_SMALL`, `BUCKET_CACHE_LARGE` | `rustfs/src/storage/ecfs_extend.rs` | Cache or constant / owner-local cache | Bucket validation cache backend selection and cache storage stay private to the ECFS extension owner. | +| `GLOBAL_SSE_DEK_PROVIDER`, `SSE_TEST_LOCK` | `rustfs/src/storage/sse.rs` | Owner-local cache / test state | SSE DEK provider cache and test serialization lock stay private to the SSE owner. | +| `AUTH_FS` | `rustfs/src/storage/access.rs` | Cache or constant / owner-local cache | Authorization tag-condition lookup keeps its filesystem helper private to the access owner. | +| `LOCK_STATS` | `rustfs/src/storage/lock_optimizer.rs` | Process-global owner-local metrics | Lock optimization statistics stay private behind lock optimizer helper APIs. | +| `DEADLOCK_DETECTOR` | `rustfs/src/storage/deadlock_detector.rs` | Process-global owner-local state | Deadlock detector lifecycle state stays private to the storage deadlock detector owner. | +| `CONCURRENCY_MANAGER`, `ACTIVE_GET_REQUESTS`, `ACTIVE_PUT_REQUESTS`, `IO_PRIORITY_METRICS` | `rustfs/src/storage/concurrency/*` | Process-global owner-local scheduler state | Storage concurrency manager, counters, and metrics remain inside the storage concurrency owner boundary. | +| `GET_OBJECT_BUFFER_THRESHOLD_WARNED`, `GET_READER_STREAM_BUFFER_SIZE_OVERRIDE`, function-local `ENABLED`, `OBJECT_SEEK_SUPPORT_THRESHOLD`, `OBJECT_SEEK_SUPPORT_CONCURRENCY_THRESHOLDS` | `rustfs/src/app/object_usecase.rs` | Cache or constant / owner-local cache | Object GET/seek tuning caches and warning guards stay private to object usecase helpers. | +| `SUPPORTED_HEADERS` | `rustfs/src/storage/options.rs` | Cache or constant / owner-local constant | Supported-header lookup state stays private to storage option parsing. | +| `AUDIT_TARGET_SPECS`, `NOTIFICATION_TARGET_SPECS` | `rustfs/src/admin/handlers/audit.rs`, `rustfs/src/admin/handlers/event.rs`, `rustfs/src/admin/handlers/plugins_instances.rs` | Cache or constant / owner-local constant | Admin target descriptor tables stay private to their handler owners. | +| `SITE_REPLICATION_PEER_CLIENT`, `SITE_REPLICATION_STATE_LOCK` | `rustfs/src/admin/handlers/site_replication.rs` | Process-global owner-local cache / guard | Site-replication peer client cache and state lock stay private to site-replication handlers. | +| `AUDIT_MODULE_ENABLED`, `NOTIFY_MODULE_ENABLED`, `PERSISTED_NOTIFY_MODULE_ENABLED`, `PERSISTED_AUDIT_MODULE_ENABLED`, `PERSISTED_MODULE_SWITCH_CONFIGURED` | `rustfs/src/server/audit.rs`, `rustfs/src/server/event.rs`, `rustfs/src/server/module_switch.rs` | Process-global owner-local toggles | Audit/notify module snapshots stay private to the server module switch owners. | +| `DELETE_TAIL_TOTAL`, `DELETE_CLEANUP_TOTAL`, `DELETE_REPLICATION_TOTAL`, `DELETE_NOTIFY_TOTAL` | `rustfs/src/delete_tail_activity.rs` | Process-global owner-local counters | Delete-tail activity counters stay private behind delete-tail activity helpers. | +| `EMBEDDED_SERVER_STARTED` | `rustfs/src/startup_lifecycle.rs` | Process-global owner-local guard | Embedded startup single-start protection stays private to startup lifecycle. | +| `TEST_OUTBOUND_TLS_GENERATION` | `rustfs/src/admin/runtime_sources.rs` | Test or fixture state | Outbound TLS generation test hook state stays private to admin runtime-source tests. | +| `TEST_REMAINING_FAILURES` | `rustfs/src/startup_iam.rs` | Test or fixture state | IAM startup retry injection state stays private to debug/test startup code. | +| `CAPACITY_DIRTY_SCOPE_ENV`, `CAPACITY_DIRTY_SCOPE_INIT`, `GLOBAL_ENV`, function-local `INIT` | `rustfs/src/app/*_test.rs` | Test or fixture state | App integration test fixture state stays private to the owning test modules. | + ## First Code-Bearing Candidate `GLOBAL_EXPIRY_STATE` is the safest first runtime migration candidate: diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index bf91541d0..b85ce9031 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -75,6 +75,10 @@ require_source_contains "docs/architecture/global-state-crate-split-plan.md" "gl require_source_contains "docs/architecture/global-state-inventory.md" "## Global State Classification" "global state inventory classification section" require_source_contains "docs/architecture/global-state-inventory.md" "## Runtime Migration Inventory" "global state inventory migration section" require_source_contains "docs/architecture/global-state-inventory.md" "GLOBAL_EXPIRY_STATE" "global state inventory first candidate" +require_source_contains "docs/architecture/global-state-inventory.md" "## RustFS Owner-Local Static Inventory" "global state inventory RustFS owner-local static section" +require_source_contains "docs/architecture/global-state-inventory.md" "KEYSTONE_AUTH" "global state inventory RustFS auth static inventory" +require_source_contains "docs/architecture/global-state-inventory.md" "DEADLOCK_DETECTOR" "global state inventory RustFS storage static inventory" +require_source_contains "docs/architecture/global-state-inventory.md" "CONCURRENCY_MANAGER" "global state inventory RustFS concurrency static inventory" require_source_contains "docs/architecture/obs-ecstore-dependency-inventory.md" "## Dependency Inventory" "observability ECStore dependency inventory section" require_source_contains "docs/architecture/obs-ecstore-dependency-inventory.md" "## Extraction Plan" "observability ECStore extraction plan section" require_source_contains "docs/architecture/obs-ecstore-dependency-inventory.md" "crates/obs/src/metrics/storage_api.rs" "observability ECStore storage_api boundary" @@ -213,6 +217,11 @@ ECSTORE_SET_DISK_CACHE_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_set_disk_cache_bypas ECSTORE_DRIVE_TIMEOUT_CACHE_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_drive_timeout_cache_bypass_hits.txt" ECSTORE_LIFECYCLE_RECOVERY_GUARD_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_lifecycle_recovery_guard_bypass_hits.txt" ECSTORE_REMOTE_TIER_DELETE_STATE_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_remote_tier_delete_state_bypass_hits.txt" +RUSTFS_OWNER_LOCAL_STATIC_PUBLIC_HITS_FILE="${TMP_DIR}/rustfs_owner_local_static_public_hits.txt" +RUSTFS_OWNER_LOCAL_STATIC_REEXPORT_HITS_FILE="${TMP_DIR}/rustfs_owner_local_static_reexport_hits.txt" +RUSTFS_ADMIN_TARGET_SPEC_STATIC_PUBLIC_HITS_FILE="${TMP_DIR}/rustfs_admin_target_spec_static_public_hits.txt" +RUSTFS_ADMIN_TARGET_SPEC_STATIC_REEXPORT_HITS_FILE="${TMP_DIR}/rustfs_admin_target_spec_static_reexport_hits.txt" +RUSTFS_STORAGE_CONCURRENCY_STATIC_BYPASS_HITS_FILE="${TMP_DIR}/rustfs_storage_concurrency_static_bypass_hits.txt" GLOBAL_BUCKET_MONITOR_BYPASS_HITS_FILE="${TMP_DIR}/global_bucket_monitor_bypass_hits.txt" GLOBAL_ENDPOINTS_BYPASS_HITS_FILE="${TMP_DIR}/global_endpoints_bypass_hits.txt" GLOBAL_IS_ERASURE_BYPASS_HITS_FILE="${TMP_DIR}/global_is_erasure_bypass_hits.txt" @@ -2714,6 +2723,70 @@ if [[ -s "$ECSTORE_REMOTE_TIER_DELETE_STATE_BYPASS_HITS_FILE" ]]; then report_failure "remote tier delete state access must stay behind ECStore tier sweeper owner helpers: $(paste -sd '; ' "$ECSTORE_REMOTE_TIER_DELETE_STATE_BYPASS_HITS_FILE")" fi +RUSTFS_OWNER_LOCAL_STATIC_NAMES='(KEYSTONE_AUTH|KEYSTONE_MAPPER|KEYSTONE_CONFIG|LICENSE_STATE|LICENSE_VERIFIER|CPU_CONT_GUARD|PROFILING_CANCEL_TOKEN|MEMORY_SYSTEM|DIAL9_TELEMETRY_GUARD|DISPLAY_CONFIG_SNAPSHOT|GLOBAL_CONFIG_SNAPSHOT|BUFFER_CONFIG_SINGLETON|BUFFER_PROFILE_ENABLED|LEGACY_CREDENTIAL_WARNED_KEYS|CONSOLE_CONFIG|ACTIVE_HTTP_REQUESTS|USE_STARSHARD_CACHE|BUCKET_CACHE_SMALL|BUCKET_CACHE_LARGE|GLOBAL_SSE_DEK_PROVIDER|SSE_TEST_LOCK|AUTH_FS|LOCK_STATS|DEADLOCK_DETECTOR|GET_OBJECT_BUFFER_THRESHOLD_WARNED|GET_READER_STREAM_BUFFER_SIZE_OVERRIDE|OBJECT_SEEK_SUPPORT_THRESHOLD|OBJECT_SEEK_SUPPORT_CONCURRENCY_THRESHOLDS|SUPPORTED_HEADERS|SITE_REPLICATION_PEER_CLIENT|SITE_REPLICATION_STATE_LOCK|AUDIT_MODULE_ENABLED|NOTIFY_MODULE_ENABLED|PERSISTED_NOTIFY_MODULE_ENABLED|PERSISTED_AUDIT_MODULE_ENABLED|PERSISTED_MODULE_SWITCH_CONFIGURED|DELETE_TAIL_TOTAL|DELETE_CLEANUP_TOTAL|DELETE_REPLICATION_TOTAL|DELETE_NOTIFY_TOTAL|EMBEDDED_SERVER_STARTED|TEST_OUTBOUND_TLS_GENERATION|TEST_REMAINING_FAILURES|CAPACITY_DIRTY_SCOPE_ENV|CAPACITY_DIRTY_SCOPE_INIT|GLOBAL_ENV)' + +( + cd "$ROOT_DIR" + rg -n --with-filename \ + "^[[:space:]]*pub[[:space:]]*(?:\\([^)]*\\)[[:space:]]*)?static(?:[[:space:]]+mut)?[[:space:]]+${RUSTFS_OWNER_LOCAL_STATIC_NAMES}[[:space:]]*:" \ + rustfs/src \ + --glob '*.rs' || true +) >"$RUSTFS_OWNER_LOCAL_STATIC_PUBLIC_HITS_FILE" + +if [[ -s "$RUSTFS_OWNER_LOCAL_STATIC_PUBLIC_HITS_FILE" ]]; then + report_failure "RustFS owner-local statics must remain private to their owner modules: $(paste -sd '; ' "$RUSTFS_OWNER_LOCAL_STATIC_PUBLIC_HITS_FILE")" +fi + +( + cd "$ROOT_DIR" + rg -n -U --with-filename \ + "^[[:space:]]*pub[[:space:]]*(?:\\([^)]*\\)[[:space:]]*)?use[[:space:]][^;]*\\b${RUSTFS_OWNER_LOCAL_STATIC_NAMES}\\b" \ + rustfs/src \ + --glob '*.rs' || true +) >"$RUSTFS_OWNER_LOCAL_STATIC_REEXPORT_HITS_FILE" + +if [[ -s "$RUSTFS_OWNER_LOCAL_STATIC_REEXPORT_HITS_FILE" ]]; then + report_failure "RustFS owner-local statics must not be re-exported across owner boundaries: $(paste -sd '; ' "$RUSTFS_OWNER_LOCAL_STATIC_REEXPORT_HITS_FILE")" +fi + +( + cd "$ROOT_DIR" + rg -n --with-filename \ + '^[[:space:]]*pub[[:space:]]*(?:\([^)]*\)[[:space:]]*)?static(?:[[:space:]]+mut)?[[:space:]]+(AUDIT_TARGET_SPECS|NOTIFICATION_TARGET_SPECS)[[:space:]]*:' \ + rustfs/src/admin/handlers/audit.rs \ + rustfs/src/admin/handlers/event.rs \ + rustfs/src/admin/handlers/plugins_instances.rs || true +) >"$RUSTFS_ADMIN_TARGET_SPEC_STATIC_PUBLIC_HITS_FILE" + +if [[ -s "$RUSTFS_ADMIN_TARGET_SPEC_STATIC_PUBLIC_HITS_FILE" ]]; then + report_failure "RustFS admin target spec statics must remain private to their handler owners: $(paste -sd '; ' "$RUSTFS_ADMIN_TARGET_SPEC_STATIC_PUBLIC_HITS_FILE")" +fi + +( + cd "$ROOT_DIR" + rg -n -U --with-filename \ + '^[[:space:]]*pub[[:space:]]*(?:\([^)]*\)[[:space:]]*)?use[[:space:]][^;]*\b(AUDIT_TARGET_SPECS|NOTIFICATION_TARGET_SPECS)\b' \ + rustfs/src \ + --glob '*.rs' || true +) >"$RUSTFS_ADMIN_TARGET_SPEC_STATIC_REEXPORT_HITS_FILE" + +if [[ -s "$RUSTFS_ADMIN_TARGET_SPEC_STATIC_REEXPORT_HITS_FILE" ]]; then + report_failure "RustFS admin target spec statics must not be re-exported across handler boundaries: $(paste -sd '; ' "$RUSTFS_ADMIN_TARGET_SPEC_STATIC_REEXPORT_HITS_FILE")" +fi + +( + cd "$ROOT_DIR" + rg -n --with-filename \ + '\b(CONCURRENCY_MANAGER|ACTIVE_GET_REQUESTS|ACTIVE_PUT_REQUESTS|IO_PRIORITY_METRICS)\b' \ + rustfs/src \ + --glob '*.rs' | + rg -v '^rustfs/src/storage/concurrency/' || true +) >"$RUSTFS_STORAGE_CONCURRENCY_STATIC_BYPASS_HITS_FILE" + +if [[ -s "$RUSTFS_STORAGE_CONCURRENCY_STATIC_BYPASS_HITS_FILE" ]]; then + report_failure "RustFS storage concurrency statics must stay inside the storage concurrency owner boundary: $(paste -sd '; ' "$RUSTFS_STORAGE_CONCURRENCY_STATIC_BYPASS_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --with-filename '\bGLOBAL_BUCKET_MONITOR\b' \