Files
rustfs/crates/ecstore/src/services/event_notification.rs
T
Zhengchao An d6c62b9601 chore(ecstore): drop the services dead_code blanket (#6103)
Removing the blanket exposes twenty-five items across tier, notification and rebalance. Only eight are deleted — the lowest ratio of this burn-down so far, and the reason is that these subsystems carry heavy test coverage, so the blanket was mostly hiding test-only seams rather than dead weight.

Deleted:

- crates/ecstore/src/services/tier/warm_backend_s3sdk.rs entirely (200 lines). Its WarmBackendS3 is never constructed; the type of the same name in warm_backend_s3.rs is the live one, wrapped by the Azure backend. Two implementations of one S3 warm backend, one of them never wired.
- TierConfigMgr::begin_publish_transition and publish_candidate_inner, thin wrappers whose _with_allowed_mutation_blocks siblings carry every real caller, plus retire_driver.
- The GCS backend's MAX_MULTIPART_PUT_OBJECT_SIZE, MAX_PARTS_COUNT and MIN_PART_SIZE, and its write-only storage_class field.
- mark_started_rebalance_pools_stopped and the RStats alias.

Two deletions were withdrawn after a per-name grep, both because of an inference rather than a check:

AsyncBatchProcessor::new was deleted on the strength of grepping only BATCH_PROCESSOR_OPERATION_CUSTOM, whose two hits are its definition and its use inside new. That looked like a self-contained dead pair; new in fact has seven test callers. The warning listed both items, and only one of them was actually checked.

Deleting the two dead publish wrappers then revealed a second layer — publish_candidate_owned, remove_and_save_with, clear_and_save_with, save_tiering_config_if_current. These are not dead: publish_candidate, their caller, is #[cfg(test)], so a callee that lives in the main body has no caller in the lib build and a live one in the test build. rustc reports the roots of a dead subgraph, and the next layer down can have a different character, so each layer needs its own grep.

Kept with allows: the tier mutation-intent record helpers (asserted by store::init tests), affected_targets, tier_object_blocks_target_rebind, the rebalance snapshot and retry-wait helpers, notification_sys's tier_config_reload_worker_active and call_peer_with_timeout, and active_operation_lease_count, whose only caller sits behind #[cfg(feature = "test-util")].

Also kept, with a module note rather than removal: the ecstore-side EventNotifier. All four of its methods are unreachable and init_bucket_targets logs that it is a no-op in this build; the working stack is rustfs-notify, whose own EventNotifier drives bucket configuration. Removing it means also retiring the InstanceContext slot that holds it (backlog#939 Phase 5), which belongs in its own PR.

Worth a separate issue: MAX_MULTIPART_PUT_OBJECT_SIZE, MAX_PARTS_COUNT and MIN_PART_SIZE are declared independently in eight warm-backend files plus client/constants.rs. Only the GCS copies were dead; the other seven backends each use their own.

Verification, four lanes warning-free: default, --tests, --features rio-v2 --tests, --features test-util --tests. cargo nextest run -p rustfs-ecstore 4041 passed; clippy --lib --tests -D warnings clean; make pre-commit exit 0.

Ref rustfs/backlog#1823 (step 2).
2026-08-14 21:56:11 +08:00

143 lines
4.4 KiB
Rust

#![allow(unused_imports)]
// 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.
#![allow(unused_variables)]
use crate::bucket::metadata::BucketMetadata;
// use crate::event::name::EventName;
use crate::event::targetlist::TargetList;
use crate::object_api::ObjectInfo;
use crate::store::ECStore;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::OnceLock;
use std::sync::atomic::Ordering;
use tokio::sync::RwLock;
use tracing::warn;
/// Dead ecstore-side notification skeleton.
///
/// The working notification stack is `rustfs-notify`, whose own `EventNotifier`
/// is the one bucket configuration actually drives. Nothing calls the methods
/// below; `init_bucket_targets` even logs that it is a no-op in this build.
/// Removing it means also retiring the `InstanceContext` slot that holds it
/// (backlog#939 Phase 5), so it is left explicit here rather than half-removed.
#[allow(
dead_code,
reason = "ecstore-side notification skeleton superseded by rustfs-notify; see module note (backlog#1823)"
)]
pub struct EventNotifier {
target_list: TargetList,
//bucket_rules_map: HashMap<String , HashMap<EventName, Rules>>,
}
#[allow(
dead_code,
reason = "ecstore-side notification skeleton superseded by rustfs-notify; see module note (backlog#1823)"
)]
impl EventNotifier {
pub fn new() -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(Self {
target_list: TargetList::new(),
//bucket_rules_map: HashMap::new(),
}))
}
fn get_arn_list(&self) -> Vec<String> {
warn!(
event_count = self.target_list.total_events.load(Ordering::Relaxed),
"event notifier arn list requested but not implemented in this build"
);
Vec::new()
}
fn set(&self, bucket: &str, meta: BucketMetadata) {
warn!(bucket = bucket, "event notifier set() called but currently no-op in this build");
}
fn init_bucket_targets(&self, _api: ECStore) -> Result<(), std::io::Error> {
warn!("init_bucket_targets called but currently no-op in this build");
Ok(())
}
fn send(&self, args: EventArgs) {
warn!(
event_name = args.event_name,
bucket = args.bucket_name,
"event send() called but notifier is not fully implemented in this build"
);
}
}
#[derive(Debug, Default)]
pub struct EventArgs {
pub event_name: String,
pub bucket_name: String,
pub object: ObjectInfo,
pub req_params: HashMap<String, String>,
pub resp_elements: HashMap<String, String>,
pub host: String,
pub user_agent: String,
}
impl EventArgs {}
type EventDispatchHook = Arc<dyn Fn(EventArgs) + Send + Sync + 'static>;
static EVENT_DISPATCH_HOOK: OnceLock<EventDispatchHook> = OnceLock::new();
pub fn register_event_dispatch_hook<F>(hook: F) -> bool
where
F: Fn(EventArgs) + Send + Sync + 'static,
{
EVENT_DISPATCH_HOOK.set(Arc::new(hook)).is_ok()
}
pub fn send_event(args: EventArgs) {
if let Some(hook) = EVENT_DISPATCH_HOOK.get() {
hook(args);
return;
}
warn!(
event_name = args.event_name,
bucket = args.bucket_name,
"event send() dropped because no event dispatch hook is registered"
);
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicUsize, Ordering};
static DISPATCH_COUNT: AtomicUsize = AtomicUsize::new(0);
#[test]
fn send_event_dispatches_to_registered_hook() {
let _ = register_event_dispatch_hook(|_args| {
DISPATCH_COUNT.fetch_add(1, Ordering::Relaxed);
});
let before = DISPATCH_COUNT.load(Ordering::Relaxed);
send_event(EventArgs {
event_name: "s3:ObjectCreated:Put".to_string(),
bucket_name: "demo".to_string(),
..Default::default()
});
assert_eq!(DISPATCH_COUNT.load(Ordering::Relaxed), before + 1);
}
}