mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 16:46:55 +00:00
refactor: batch cluster lock and health readiness (#3936)
This commit is contained in:
@@ -48,3 +48,8 @@ pub const DEFAULT_HEALTH_COMPAT_BUSY_MAX_ACTIVE_REQUESTS: usize = 0;
|
||||
/// in running state if a global KMS manager exists.
|
||||
pub const ENV_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE: &str = "RUSTFS_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE";
|
||||
pub const DEFAULT_HEALTH_COMPAT_KMS_READY_CHECK_ENABLE: bool = false;
|
||||
|
||||
/// Enable peer-health readiness impact.
|
||||
/// When disabled, peer-health state is reported but does not affect readiness.
|
||||
pub const ENV_HEALTH_PEER_READY_CHECK_ENABLE: &str = "RUSTFS_HEALTH_PEER_READY_CHECK_ENABLE";
|
||||
pub const DEFAULT_HEALTH_PEER_READY_CHECK_ENABLE: bool = false;
|
||||
|
||||
@@ -46,7 +46,6 @@ use rustfs_common::heal_channel::HealOpts;
|
||||
use rustfs_common::heal_channel::{DriveState, HealItemType};
|
||||
use rustfs_filemeta::FileInfo;
|
||||
use rustfs_lock::NamespaceLockWrapper;
|
||||
use rustfs_lock::client::LockClient;
|
||||
use rustfs_madmin::heal_commands::{HealDriveInfo, HealResultItem};
|
||||
use rustfs_utils::{crc_hash, path::path_join_buf, sip_hash};
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
@@ -102,28 +101,17 @@ impl Sets {
|
||||
|
||||
let mut disk_set = Vec::with_capacity(set_count);
|
||||
|
||||
// Get lock clients from global storage
|
||||
let lock_clients = runtime_sources::global_lock_clients();
|
||||
let lock_registry = runtime_sources::lock_registry();
|
||||
|
||||
for i in 0..set_count {
|
||||
let mut set_drive = Vec::with_capacity(set_drive_count);
|
||||
let mut set_endpoints = Vec::with_capacity(set_drive_count);
|
||||
let mut set_lock_clients: HashMap<String, Arc<dyn LockClient>> = HashMap::new();
|
||||
for j in 0..set_drive_count {
|
||||
let idx = i * set_drive_count + j;
|
||||
let mut disk = disks[idx].clone();
|
||||
|
||||
let endpoint = endpoints.endpoints.as_ref()[idx].clone();
|
||||
|
||||
if let Some(lock_clients_map) = lock_clients {
|
||||
let host_port = endpoint.host_port();
|
||||
if let Some(lock_client) = lock_clients_map.get(&host_port)
|
||||
&& !set_lock_clients.contains_key(&host_port)
|
||||
{
|
||||
set_lock_clients.insert(host_port, lock_client.clone());
|
||||
}
|
||||
}
|
||||
|
||||
set_endpoints.push(endpoint);
|
||||
|
||||
if disk.is_none() {
|
||||
@@ -164,7 +152,10 @@ impl Sets {
|
||||
}
|
||||
}
|
||||
|
||||
let lockers = set_lock_clients.values().cloned().collect::<Vec<Arc<dyn LockClient>>>();
|
||||
let lockers = lock_registry
|
||||
.as_ref()
|
||||
.map(|registry| registry.clients_for_endpoints(&set_endpoints))
|
||||
.unwrap_or_default();
|
||||
let set_disks = SetDisks::new(
|
||||
runtime_sources::local_node_name().await,
|
||||
Arc::new(RwLock::new(set_drive)),
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
collections::{HashMap, HashSet},
|
||||
sync::{Arc, OnceLock},
|
||||
time::SystemTime,
|
||||
};
|
||||
@@ -59,6 +59,35 @@ const TEST_RPC_SECRET: &str = "test-rpc-secret";
|
||||
|
||||
pub(crate) type WorkloadSnapshotProviderRef = Arc<dyn WorkloadAdmissionSnapshotProvider + Send + Sync>;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct LockRegistry {
|
||||
clients: HashMap<String, Arc<dyn LockClient>>,
|
||||
}
|
||||
|
||||
impl LockRegistry {
|
||||
pub(crate) fn new(clients: HashMap<String, Arc<dyn LockClient>>) -> Self {
|
||||
Self { clients }
|
||||
}
|
||||
|
||||
pub(crate) fn clients_for_endpoints(&self, endpoints: &[Endpoint]) -> Vec<Arc<dyn LockClient>> {
|
||||
let mut seen_hosts = HashSet::with_capacity(endpoints.len());
|
||||
let mut clients = Vec::with_capacity(endpoints.len());
|
||||
|
||||
for endpoint in endpoints {
|
||||
let host_port = endpoint.host_port();
|
||||
if host_port.is_empty() || !seen_hosts.insert(host_port.clone()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(client) = self.clients.get(&host_port) {
|
||||
clients.push(client.clone());
|
||||
}
|
||||
}
|
||||
|
||||
clients
|
||||
}
|
||||
}
|
||||
|
||||
static WORKLOAD_ADMISSION_SNAPSHOT_PROVIDER: OnceLock<WorkloadSnapshotProviderRef> = OnceLock::new();
|
||||
|
||||
pub(crate) fn set_workload_admission_snapshot_provider(
|
||||
@@ -256,6 +285,11 @@ pub(crate) fn global_lock_clients() -> Option<&'static HashMap<String, Arc<dyn L
|
||||
get_global_lock_clients()
|
||||
}
|
||||
|
||||
pub(crate) fn lock_registry() -> Option<LockRegistry> {
|
||||
global_lock_clients()
|
||||
.map(|clients| LockRegistry::new(clients.iter().map(|(host, client)| (host.clone(), client.clone())).collect()))
|
||||
}
|
||||
|
||||
pub(crate) fn set_primary_lock_client(client: Arc<dyn LockClient>) -> std::result::Result<(), Arc<dyn LockClient>> {
|
||||
set_global_lock_client(client)
|
||||
}
|
||||
@@ -469,3 +503,43 @@ pub(crate) async fn initialize_local_disk_maps(endpoint_pools: EndpointServerPoo
|
||||
pub(crate) async fn init_tier_config_mgr(store: Arc<ECStore>) -> Result<()> {
|
||||
GLOBAL_TierConfigMgr.write().await.init(store).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::LockRegistry;
|
||||
use crate::disk::endpoint::Endpoint;
|
||||
use rustfs_lock::{LocalClient, LockClient};
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
fn url_endpoint(raw: &str) -> Endpoint {
|
||||
Endpoint {
|
||||
url: url::Url::parse(raw).expect("test endpoint url"),
|
||||
is_local: false,
|
||||
pool_idx: 0,
|
||||
set_idx: 0,
|
||||
disk_idx: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_registry_selects_unique_clients_in_endpoint_order() {
|
||||
let client_a: Arc<dyn LockClient> = Arc::new(LocalClient::new());
|
||||
let client_b: Arc<dyn LockClient> = Arc::new(LocalClient::new());
|
||||
let registry = LockRegistry::new(HashMap::from([
|
||||
("node-a:9000".to_string(), client_a.clone()),
|
||||
("node-b:9000".to_string(), client_b.clone()),
|
||||
]));
|
||||
let endpoints = vec![
|
||||
url_endpoint("http://node-a:9000/data-a"),
|
||||
url_endpoint("http://node-a:9000/data-b"),
|
||||
url_endpoint("http://node-missing:9000/data"),
|
||||
url_endpoint("http://node-b:9000/data"),
|
||||
];
|
||||
|
||||
let clients = registry.clients_for_endpoints(&endpoints);
|
||||
|
||||
assert_eq!(clients.len(), 2);
|
||||
assert!(Arc::ptr_eq(&clients[0], &client_a));
|
||||
assert!(Arc::ptr_eq(&clients[1], &client_b));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user