refactor: migrate consumers off rustfs-common heal/scanner shims (#6623)

* refactor(ecstore): import heal/scanner contracts crates directly (backlog#1843)

* refactor(heal): import heal/scanner contracts crates directly (backlog#1843)

* refactor(lifecycle): import heal/scanner contracts crates directly (backlog#1843)

* refactor(obs): import heal/scanner contracts crates directly (backlog#1843)

* refactor(protos): import heal/scanner contracts crates directly (backlog#1843)

* refactor(scanner): import heal/scanner contracts crates directly (backlog#1843)

* refactor(rustfs): import heal/scanner contracts crates directly (backlog#1843)
This commit is contained in:
Zhengchao An
2026-08-26 21:13:18 +08:00
committed by GitHub
parent 2ada8a5cfb
commit a96dd7d289
72 changed files with 263 additions and 206 deletions
+2
View File
@@ -213,6 +213,8 @@ hotpath.workspace = true
rustfs-heal = { workspace = true }
rustfs-audit = { workspace = true }
rustfs-common = { workspace = true }
rustfs-heal-contracts = { workspace = true }
rustfs-scanner-contracts = { workspace = true }
rustfs-config = { workspace = true, features = ["notify", "server-config-model"] }
rustfs-crypto = { workspace = true }
rustfs-credentials = { workspace = true }
+25 -19
View File
@@ -28,11 +28,11 @@ use futures_util::future::join_all;
use http::{HeaderMap, HeaderValue, Uri};
use hyper::{Method, StatusCode};
use matchit::Params;
use rustfs_common::heal_channel::{
HealAdmissionReceipt, HealChannelPriority, HealChannelRequest, HealOpts, HealRequestSource, HealScanMode,
};
use rustfs_config::MAX_HEAL_REQUEST_SIZE;
use rustfs_heal::heal::utils::format_set_disk_id;
use rustfs_heal_contracts::heal_channel::{
HealAdmissionReceipt, HealChannelPriority, HealChannelRequest, HealOpts, HealRequestSource, HealScanMode,
};
use rustfs_policy::policy::action::{Action, AdminAction};
use rustfs_scanner::scanner::{BackgroundHealInfo, read_background_heal_info};
use rustfs_utils::path::path_join;
@@ -960,8 +960,8 @@ async fn submit_cluster_heal_start(
}
}
fn reject_heal_admission(result: rustfs_common::heal_channel::HealAdmissionResult) -> s3s::S3Error {
use rustfs_common::heal_channel::{HealAdmissionDropReason, HealAdmissionResult};
fn reject_heal_admission(result: rustfs_heal_contracts::heal_channel::HealAdmissionResult) -> s3s::S3Error {
use rustfs_heal_contracts::heal_channel::{HealAdmissionDropReason, HealAdmissionResult};
match result {
HealAdmissionResult::Full | HealAdmissionResult::Dropped(HealAdmissionDropReason::QueueFull) => s3_error!(
@@ -996,10 +996,10 @@ async fn submit_cluster_heal_channel_command(
envelope: rustfs_protos::heal_control::Envelope,
request_id: &str,
response_id: String,
) -> S3Result<rustfs_common::heal_channel::HealChannelResponse> {
) -> S3Result<rustfs_heal_contracts::heal_channel::HealChannelResponse> {
match route_cluster_heal_control(&context, &route, envelope, request_id, false).await? {
rustfs_protos::heal_control::Outcome::Channel { success, data, error } => {
Ok(rustfs_common::heal_channel::HealChannelResponse {
Ok(rustfs_heal_contracts::heal_channel::HealChannelResponse {
request_id: response_id,
success,
data,
@@ -1087,7 +1087,7 @@ fn build_heal_channel_request(hip: &HealInitParams) -> HealChannelRequest {
} else {
hip.hs.recursive
};
let mut heal_request = rustfs_common::heal_channel::create_heal_request(
let mut heal_request = rustfs_heal_contracts::heal_channel::create_heal_request(
hip.bucket.clone(),
if hip.obj_prefix.is_empty() {
None
@@ -1115,7 +1115,7 @@ fn build_heal_channel_request(hip: &HealInitParams) -> HealChannelRequest {
}
fn heal_channel_response_status(
response: &rustfs_common::heal_channel::HealChannelResponse,
response: &rustfs_heal_contracts::heal_channel::HealChannelResponse,
) -> (String, Vec<rustfs_madmin::heal_commands::HealResultItem>, bool, Option<serde_json::Value>) {
let Some(data) = response.data.as_deref() else {
return ("running".to_string(), Vec::new(), false, None);
@@ -1136,19 +1136,21 @@ fn heal_channel_response_status(
}
#[cfg(test)]
fn heal_channel_response_summary(response: &rustfs_common::heal_channel::HealChannelResponse) -> String {
fn heal_channel_response_summary(response: &rustfs_heal_contracts::heal_channel::HealChannelResponse) -> String {
heal_channel_response_status(response).0
}
#[cfg(test)]
fn heal_channel_response_items(
response: &rustfs_common::heal_channel::HealChannelResponse,
response: &rustfs_heal_contracts::heal_channel::HealChannelResponse,
) -> Vec<rustfs_madmin::heal_commands::HealResultItem> {
heal_channel_response_status(response).1
}
#[cfg(test)]
fn heal_channel_response_progress(response: &rustfs_common::heal_channel::HealChannelResponse) -> Option<serde_json::Value> {
fn heal_channel_response_progress(
response: &rustfs_heal_contracts::heal_channel::HealChannelResponse,
) -> Option<serde_json::Value> {
heal_channel_response_status(response).3
}
@@ -1524,7 +1526,7 @@ mod tests {
use http::StatusCode;
use http::Uri;
use matchit::Router;
use rustfs_common::heal_channel::{
use rustfs_heal_contracts::heal_channel::{
HealAdmissionDropReason, HealAdmissionResult, HealChannelPriority, HealOpts, HealRequestSource, HealScanMode,
};
use rustfs_scanner::scanner::BackgroundHealInfo;
@@ -1718,7 +1720,7 @@ mod tests {
dry_run: false,
remove: true,
recreate: false,
scan_mode: rustfs_common::heal_channel::HealScanMode::Normal,
scan_mode: rustfs_heal_contracts::heal_channel::HealScanMode::Normal,
update_parity: false,
no_lock: true,
pool: Some(1),
@@ -2640,11 +2642,15 @@ mod tests {
#[test]
fn test_heal_channel_response_summary_defaults_to_running() {
let response = rustfs_common::heal_channel::create_heal_response("token".to_string(), true, None, None);
let response = rustfs_heal_contracts::heal_channel::create_heal_response("token".to_string(), true, None, None);
assert_eq!(heal_channel_response_summary(&response), "running");
let response =
rustfs_common::heal_channel::create_heal_response("token".to_string(), true, Some(b"finished".to_vec()), None);
let response = rustfs_heal_contracts::heal_channel::create_heal_response(
"token".to_string(),
true,
Some(b"finished".to_vec()),
None,
);
assert_eq!(heal_channel_response_summary(&response), "finished");
}
@@ -2668,7 +2674,7 @@ mod tests {
"objectSize": 1024
}]
});
let response = rustfs_common::heal_channel::create_heal_response(
let response = rustfs_heal_contracts::heal_channel::create_heal_response(
"token".to_string(),
true,
Some(serde_json::to_vec(&payload).expect("payload should serialize")),
@@ -2695,7 +2701,7 @@ mod tests {
"items": [],
"progress": progress
});
let response = rustfs_common::heal_channel::create_heal_response(
let response = rustfs_heal_contracts::heal_channel::create_heal_response(
"token".to_string(),
true,
Some(serde_json::to_vec(&payload).expect("payload should serialize")),
+3 -1
View File
@@ -24,10 +24,12 @@ use chrono::Utc;
use http::{HeaderMap, HeaderValue};
use hyper::{Method, StatusCode};
use matchit::Params;
use rustfs_common::metrics::{ScannerLifecycleExpirySnapshot, ScannerMaintenanceControlSnapshot, ScannerMetricsReport};
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::Credentials;
use rustfs_policy::policy::action::{Action, AdminAction};
use rustfs_scanner_contracts::metrics::{
ScannerLifecycleExpirySnapshot, ScannerMaintenanceControlSnapshot, ScannerMetricsReport,
};
use s3s::header::CONTENT_TYPE;
use s3s::{Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result, s3_error};
use serde::{Deserialize, Serialize};
+1 -1
View File
@@ -124,7 +124,7 @@ pub(crate) mod runtime_sources {
pub(crate) type DailyAllTierStats = super::DailyAllTierStats;
pub(crate) type ECStore = super::ECStore;
pub(crate) type NotificationSys = super::NotificationSys;
pub(crate) type ScannerMetricsReport = rustfs_common::metrics::ScannerMetricsReport;
pub(crate) type ScannerMetricsReport = rustfs_scanner_contracts::metrics::ScannerMetricsReport;
pub(crate) type StorageClassConfig = crate::storage::storage_api::ecstore_config::storageclass::Config;
pub(crate) type TierConfigMgr = crate::storage::storage_api::TierConfigMgr;
}
+1 -1
View File
@@ -17,7 +17,7 @@ use super::storage_api::test::contract::bucket::{BucketOperations, BucketOptions
use super::storage_api::test::contract::heal::HealOperations as _;
use super::storage_api::test::contract::object::ObjectIO as _;
use super::storage_api::test::{ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints};
use rustfs_common::heal_channel::{HealOpts, HealScanMode};
use rustfs_heal_contracts::heal_channel::{HealOpts, HealScanMode};
use rustfs_object_capacity::capacity_manager::{HybridStrategyConfig, create_isolated_manager};
use serial_test::serial;
use std::{
+2 -2
View File
@@ -137,7 +137,7 @@ pub(crate) mod runtime {
pub(crate) type NotificationSys = crate::storage::storage_api::NotificationSys;
pub(crate) type ObjectStoreResolver = crate::storage::storage_api::ObjectStoreResolver;
pub(crate) type ReplicationStats = crate::storage::storage_api::ReplicationStats;
pub(crate) type ScannerMetricsReport = rustfs_common::metrics::ScannerMetricsReport;
pub(crate) type ScannerMetricsReport = rustfs_scanner_contracts::metrics::ScannerMetricsReport;
pub(crate) type StorageClassConfig = crate::storage::storage_api::ecstore_config::storageclass::Config;
pub(crate) type TierConfigMgr = crate::storage::storage_api::TierConfigMgr;
pub(crate) type TransitionState = crate::storage::storage_api::TransitionState;
@@ -213,7 +213,7 @@ pub(crate) mod runtime {
}
pub(crate) async fn collect_scanner_metrics_report() -> ScannerMetricsReport {
rustfs_common::metrics::global_metrics().report().await
rustfs_scanner_contracts::metrics::global_metrics().report().await
}
#[cfg(test)]
+1 -1
View File
@@ -23,9 +23,9 @@ use crate::storage_api::cluster::control_plane::{
ClusterPeerHealthSnapshot, ClusterPoolStateSnapshot, ClusterRpcBoundarySnapshot,
};
use crate::workload_admission::workload_admission_registry_snapshot;
use rustfs_common::metrics::{ScannerMetricsReport, global_metrics};
use rustfs_concurrency::{AdmissionState, WorkloadAdmissionRegistrySnapshot};
use rustfs_io_metrics::internode_metrics::{InternodeMetricsSnapshot, global_internode_metrics};
use rustfs_scanner_contracts::metrics::{ScannerMetricsReport, global_metrics};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClusterReadOnlySnapshot {
+1 -1
View File
@@ -55,7 +55,7 @@ pub(crate) async fn publish_server_addr(addr: &str) {
}
pub(crate) async fn publish_init_time_now() {
rustfs_common::set_global_init_time_now().await;
rustfs_scanner_contracts::set_global_init_time_now().await;
}
pub(crate) fn init_kms_service_manager() -> Arc<KmsServiceManager> {
+15 -10
View File
@@ -195,8 +195,8 @@ fn heal_control_remaining(expires_at_unix_ms: i64, now_unix_ms: i64) -> Result<D
Ok(Duration::from_millis(remaining_ms))
}
fn validate_admin_heal_control_start(request: &rustfs_common::heal_channel::HealChannelRequest) -> Result<(), Status> {
if request.source != rustfs_common::heal_channel::HealRequestSource::Admin {
fn validate_admin_heal_control_start(request: &rustfs_heal_contracts::heal_channel::HealChannelRequest) -> Result<(), Status> {
if request.source != rustfs_heal_contracts::heal_channel::HealRequestSource::Admin {
return Err(Status::permission_denied("heal control start source must be admin"));
}
if request.pool_index.is_some() != request.set_index.is_some() {
@@ -2542,7 +2542,7 @@ mod tests {
_bucket: &str,
_object: &str,
_version_id: Option<&str>,
_opts: &rustfs_common::heal_channel::HealOpts,
_opts: &rustfs_heal_contracts::heal_channel::HealOpts,
) -> rustfs_heal::Result<(rustfs_madmin::heal_commands::HealResultItem, Option<rustfs_heal::Error>)> {
Ok((rustfs_madmin::heal_commands::HealResultItem::default(), None))
}
@@ -2550,7 +2550,7 @@ mod tests {
async fn heal_bucket(
&self,
_bucket: &str,
_opts: &rustfs_common::heal_channel::HealOpts,
_opts: &rustfs_heal_contracts::heal_channel::HealOpts,
) -> rustfs_heal::Result<rustfs_madmin::heal_commands::HealResultItem> {
Ok(rustfs_madmin::heal_commands::HealResultItem::default())
}
@@ -2618,10 +2618,14 @@ mod tests {
let now = i64::try_from(now).expect("test clock should fit in i64");
let metadata = || rustfs_protos::heal_control::RequestMetadata::new(rand::random(), now, now + 30_000, coordinator_epoch);
let start = |request_id: String| {
let mut request =
rustfs_common::heal_channel::create_heal_request("bucket".to_string(), Some("prefix".to_string()), false, None);
let mut request = rustfs_heal_contracts::heal_channel::create_heal_request(
"bucket".to_string(),
Some("prefix".to_string()),
false,
None,
);
request.id = request_id;
request.source = rustfs_common::heal_channel::HealRequestSource::Admin;
request.source = rustfs_heal_contracts::heal_channel::HealRequestSource::Admin;
request
};
@@ -3618,7 +3622,7 @@ mod tests {
request
}
let expired_request = rustfs_common::heal_channel::create_heal_request("bucket".to_string(), None, false, None);
let expired_request = rustfs_heal_contracts::heal_channel::create_heal_request("bucket".to_string(), None, false, None);
let expired = rustfs_protos::heal_control::Envelope::start(
expired_request,
rustfs_protos::heal_control::RequestMetadata::new([1; 16], 1, 2, coordinator_epoch),
@@ -3631,8 +3635,9 @@ mod tests {
.expect_err("expired commands must fail before admission");
assert_eq!(expired.code(), tonic::Code::FailedPrecondition);
let mut non_admin_request = rustfs_common::heal_channel::create_heal_request("bucket".to_string(), None, false, None);
non_admin_request.source = rustfs_common::heal_channel::HealRequestSource::Scanner;
let mut non_admin_request =
rustfs_heal_contracts::heal_channel::create_heal_request("bucket".to_string(), None, false, None);
non_admin_request.source = rustfs_heal_contracts::heal_channel::HealRequestSource::Scanner;
let now = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000;
let now = i64::try_from(now).expect("test clock should fit in i64");
let non_admin = rustfs_protos::heal_control::Envelope::start(
+2 -2
View File
@@ -16,8 +16,8 @@ use crate::module_switches::{heal_enabled_from_env, scanner_enabled_from_env};
use crate::storage::storage_api::runtime_sources_consumer::EndpointServerPools;
use jiff::Timestamp;
use rmp_serde::Deserializer;
use rustfs_common::heal_channel::HealScanMode;
use rustfs_heal::HealOperationsSnapshot;
use rustfs_heal_contracts::heal_channel::HealScanMode;
use rustfs_scanner::scanner::BackgroundHealInfo;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
@@ -770,7 +770,7 @@ mod tests {
BackgroundHealInfo {
bitrot_start_time: Some(started_at),
bitrot_start_cycle: 9,
current_scan_mode: rustfs_common::heal_channel::HealScanMode::Deep,
current_scan_mode: rustfs_heal_contracts::heal_channel::HealScanMode::Deep,
},
HealOperationsSnapshot::default(),
None,
+2 -2
View File
@@ -1545,7 +1545,7 @@ pub(crate) trait StoragePeerS3ClientExt {
async fn heal_bucket_with_fence(
&self,
bucket: &str,
opts: &rustfs_common::heal_channel::HealOpts,
opts: &rustfs_heal_contracts::heal_channel::HealOpts,
fenced_pools: &[usize],
) -> DiskResult<rustfs_madmin::heal_commands::HealResultItem>;
async fn make_bucket(&self, bucket: &str, opts: &contract::bucket::MakeBucketOptions) -> DiskResult<()>;
@@ -1562,7 +1562,7 @@ impl StoragePeerS3ClientExt for LocalPeerS3Client {
async fn heal_bucket_with_fence(
&self,
bucket: &str,
opts: &rustfs_common::heal_channel::HealOpts,
opts: &rustfs_heal_contracts::heal_channel::HealOpts,
fenced_pools: &[usize],
) -> DiskResult<rustfs_madmin::heal_commands::HealResultItem> {
ecstore_rpc::PeerS3Client::heal_bucket_with_fence(self, bucket, opts, fenced_pools).await