refactor(ecstore): route lifecycle metadata reads (#4111)

This commit is contained in:
Zhengchao An
2026-06-30 15:22:12 +08:00
committed by GitHub
parent 4538919efa
commit b0dbf35cd4
5 changed files with 60 additions and 12 deletions
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::{object_lock_boundary, runtime_boundary as runtime_sources};
use super::{metadata_boundary, object_lock_boundary, runtime_boundary as runtime_sources};
use crate::bucket::lifecycle::bucket_lifecycle_audit::{
LcAuditEvent, LcEventSrc, emit_non_transitioned_expiration_event, emit_transition_complete_event,
emit_transition_failed_event, emit_transitioned_expiration_event,
@@ -26,7 +26,7 @@ use crate::bucket::lifecycle::tier_delete_journal::{process_tier_delete_journal_
use crate::bucket::lifecycle::tier_free_version_recovery::{DEFAULT_FREE_VERSION_RECOVERY_LIMIT, recover_tier_free_versions};
use crate::bucket::lifecycle::tier_last_day_stats::{DailyAllTierStats, LastDayTierStats};
use crate::bucket::lifecycle::tier_sweeper::{Jentry, delete_object_from_remote_tier_idempotent};
use crate::bucket::{metadata_sys, metadata_sys::get_lifecycle_config, versioning_sys::BucketVersioningSys};
use crate::bucket::versioning_sys::BucketVersioningSys;
use crate::client::object_api_utils::new_getobjectreader;
use crate::disk::error::DiskError;
use crate::disk::{DeleteOptions, Disk, DiskAPI, RUSTFS_META_MULTIPART_BUCKET, STORAGE_FORMAT_FILE};
@@ -211,7 +211,7 @@ impl LifecycleSys {
}
pub async fn get(&self, bucket: &str) -> Option<BucketLifecycleConfiguration> {
match get_lifecycle_config(bucket).await {
match metadata_boundary::get_lifecycle_config(bucket).await {
Ok((lc, _)) => Some(lc),
Err(Error::ConfigNotFound) => None,
Err(err) => {
@@ -1506,7 +1506,7 @@ async fn stale_upload_lifecycle_due(
let bucket = metadata.get(RUSTFS_MULTIPART_BUCKET_KEY)?;
let object = metadata.get(RUSTFS_MULTIPART_OBJECT_KEY)?;
let lifecycle = match metadata_sys::get_lifecycle_config(bucket).await {
let lifecycle = match metadata_boundary::get_lifecycle_config(bucket).await {
Ok((lifecycle, _)) => lifecycle,
Err(_) => return None,
};
@@ -1941,11 +1941,11 @@ pub async fn enqueue_immediate_expiry(oi: &ObjectInfo, src: LcEventSrc) {
object_infos.push(oi.clone());
}
let lock_config = match metadata_sys::get_object_lock_config(&oi.bucket).await {
let lock_config = match metadata_boundary::get_object_lock_config(&oi.bucket).await {
Ok((cfg, _)) => Some(Arc::new(cfg)),
Err(_) => None,
};
let replication = match metadata_sys::get_replication_config(&oi.bucket).await {
let replication = match metadata_boundary::get_replication_config(&oi.bucket).await {
Ok((cfg, _)) if !cfg.rules.is_empty() => Some(Arc::new(replication_sink::new_replication_config(cfg))),
_ => None,
};
@@ -2056,14 +2056,14 @@ async fn apply_existing_object_expiry(api: Arc<ECStore>, object: &ObjectInfo, ev
}
pub async fn enqueue_expiry_for_existing_objects(api: Arc<ECStore>, bucket: &str) -> Result<(), Error> {
let Ok((lc, _)) = metadata_sys::get_lifecycle_config(bucket).await else {
let Ok((lc, _)) = metadata_boundary::get_lifecycle_config(bucket).await else {
return Ok(());
};
let lock_retention = metadata_sys::get_object_lock_config(bucket)
let lock_retention = metadata_boundary::get_object_lock_config(bucket)
.await
.ok()
.and_then(|(cfg, _)| cfg.rule.and_then(|rule| rule.default_retention));
let replication_config = metadata_sys::get_replication_config(bucket).await.ok();
let replication_config = metadata_boundary::get_replication_config(bucket).await.ok();
let mut marker = None;
let mut version_marker = None;
let src = LcEventSrc::Scanner;
@@ -0,0 +1,31 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use s3s::dto::{BucketLifecycleConfiguration, ObjectLockConfiguration, ReplicationConfiguration};
use time::OffsetDateTime;
use crate::bucket::metadata_sys;
use crate::error::Result;
pub(crate) async fn get_lifecycle_config(bucket: &str) -> Result<(BucketLifecycleConfiguration, OffsetDateTime)> {
metadata_sys::get_lifecycle_config(bucket).await
}
pub(crate) async fn get_object_lock_config(bucket: &str) -> Result<(ObjectLockConfiguration, OffsetDateTime)> {
metadata_sys::get_object_lock_config(bucket).await
}
pub(crate) async fn get_replication_config(bucket: &str) -> Result<(ReplicationConfiguration, OffsetDateTime)> {
metadata_sys::get_replication_config(bucket).await
}
@@ -17,6 +17,7 @@ pub mod bucket_lifecycle_ops;
mod config_boundary;
pub mod core;
pub mod evaluator;
mod metadata_boundary;
mod object_lock_boundary;
pub use self::core as lifecycle;
mod replication_sink;
@@ -57,10 +57,12 @@ Current coupling:
- lifecycle workers and transition state read ECStore runtime sources for
object-store handles, expiry state, transition state, tier config, deployment
IDs, and local node names;
- stale multipart cleanup depends on `SetDisks` internals and bucket metadata;
- stale multipart cleanup depends on `SetDisks` internals and bucket metadata
through the lifecycle metadata boundary;
- lifecycle expiry schedules bucket replication delete work directly;
- lifecycle evaluation shares S3 DTOs, object metadata, object lock, replication
config, scanner metrics, notification/audit side effects, and tier services.
config reads through lifecycle-local boundaries, scanner metrics,
notification/audit side effects, and tier services.
Required contracts before crate movement:
@@ -68,7 +70,8 @@ Required contracts before crate movement:
cleanup, and version-aware metadata operations needed by lifecycle workers.
- `LifecycleMetadataStore`: lifecycle, object-lock, replication, bucket
versioning, and stale multipart metadata lookups without importing ECStore
implementation modules.
implementation modules. Current lifecycle config reads are concentrated in
`crates/ecstore/src/bucket/lifecycle/metadata_boundary.rs`.
- `LifecycleRuntime`: expiry state, transition state, tier config, deployment
ID, local node name, queue metrics, cancellation, and worker sizing.
- `LifecycleReplicationSink`: schedule lifecycle-originated replication deletes
@@ -132,6 +132,7 @@ STORE_API_LIFECYCLE_HELPER_DEFINITION_HITS_FILE="${TMP_DIR}/store_api_lifecycle_
STORE_API_LIFECYCLE_HELPER_OLD_CONSUMER_HITS_FILE="${TMP_DIR}/store_api_lifecycle_helper_old_consumer_hits.txt"
LIFECYCLE_AUDIT_SINK_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_audit_sink_bypass_hits.txt"
LIFECYCLE_CONFIG_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_config_boundary_bypass_hits.txt"
LIFECYCLE_METADATA_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_metadata_boundary_bypass_hits.txt"
LIFECYCLE_TAGGING_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_tagging_boundary_bypass_hits.txt"
LIFECYCLE_OBJECT_LOCK_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_object_lock_boundary_bypass_hits.txt"
LIFECYCLE_REPLICATION_SINK_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_replication_sink_bypass_hits.txt"
@@ -854,6 +855,18 @@ if [[ -s "$LIFECYCLE_CONFIG_BOUNDARY_BYPASS_HITS_FILE" ]]; then
report_failure "lifecycle config persistence access must stay behind lifecycle config_boundary: $(paste -sd '; ' "$LIFECYCLE_CONFIG_BOUNDARY_BYPASS_HITS_FILE")"
fi
(
cd "$ROOT_DIR"
rg -n --with-filename 'metadata_sys::get_(lifecycle|object_lock|replication)_config|use crate::bucket::metadata_sys::get_(lifecycle|object_lock|replication)_config' \
crates/ecstore/src/bucket/lifecycle \
--glob '*.rs' |
rg -v '^crates/ecstore/src/bucket/lifecycle/metadata_boundary\.rs:' || true
) >"$LIFECYCLE_METADATA_BOUNDARY_BYPASS_HITS_FILE"
if [[ -s "$LIFECYCLE_METADATA_BOUNDARY_BYPASS_HITS_FILE" ]]; then
report_failure "lifecycle metadata config reads must stay behind lifecycle metadata_boundary: $(paste -sd '; ' "$LIFECYCLE_METADATA_BOUNDARY_BYPASS_HITS_FILE")"
fi
(
cd "$ROOT_DIR"
rg -n --with-filename 'crate::bucket::tagging::decode_tags_to_map|use crate::bucket::tagging' \