mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-06 21:33:14 +00:00
375482a4b6
* refactor(issue-633): clarify layered io control policies * refactor(issue-633): consolidate timeout and deadlock layers * refactor(issue-633): align storage backpressure metadata * refactor(issue-633): unify storage backpressure transitions * refactor(issue-633): simplify watermark transition API * test(issue-633): add storage backpressure transition test * refactor(issue-633): align storage pipe meta shape * refactor(issue-633): enrich storage monitor metadata * refactor(issue-633): finalize storage backpressure convergence * refactor(issue-633): complete scheduler layer convergence * refactor(issue-633): reduce concurrency facade config duplication * refactor(issue-633): migrate storage callsites to final policy names * chore(issue-633): apply final pre-commit normalization * refactor(issue-633): unify timeout wrapper dynamic size path * refactor(issue-633): make concurrency policies copyable * refactor(issue-633): converge storage io hot paths * fix(issue-633): honor storage timeout min bound * fix(storage): avoid timeout calc panic on huge sizes * refactor(storage): consolidate timeout checks and test attrs * fix(storage): harden io scheduler core config mapping * refactor(storage): eliminate patch-on-patch patterns and dead code - Remove trivial accessor methods on ConcurrencyConfig that just return pub fields - Remove dead BackpressureEvent/BackpressureEventType types from concurrency crate - Fix io_schedule test using wrong constructor (from_core_config -> from_scheduler_config) - Update manager.rs to use config fields directly instead of removed accessors * fix: adopt review feedback for config guards * test: remove needless struct update defaults * fix: harden timeout policy and preserve api alias
243 lines
7.2 KiB
Rust
243 lines
7.2 KiB
Rust
// 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.
|
|
|
|
//! Configuration for concurrency management
|
|
|
|
use crate::{
|
|
backpressure::PipeBackpressurePolicy, deadlock::DeadlockMonitorPolicy, scheduler::SchedulerPolicy,
|
|
timeout::TimeoutManagerPolicy,
|
|
};
|
|
use std::time::Duration;
|
|
|
|
/// Feature flags for concurrency modules
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct ConcurrencyFeatures {
|
|
/// Enable timeout control
|
|
pub timeout: bool,
|
|
/// Enable lock optimization
|
|
pub lock: bool,
|
|
/// Enable deadlock detection
|
|
pub deadlock: bool,
|
|
/// Enable backpressure management
|
|
pub backpressure: bool,
|
|
/// Enable I/O scheduling
|
|
pub scheduler: bool,
|
|
}
|
|
|
|
impl Default for ConcurrencyFeatures {
|
|
fn default() -> Self {
|
|
Self {
|
|
timeout: cfg!(feature = "timeout"),
|
|
lock: cfg!(feature = "lock"),
|
|
deadlock: cfg!(feature = "deadlock"),
|
|
backpressure: cfg!(feature = "backpressure"),
|
|
scheduler: cfg!(feature = "scheduler"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ConcurrencyFeatures {
|
|
/// Create with all features enabled
|
|
pub fn all() -> Self {
|
|
Self {
|
|
timeout: true,
|
|
lock: true,
|
|
deadlock: true,
|
|
backpressure: true,
|
|
scheduler: true,
|
|
}
|
|
}
|
|
|
|
/// Create with no features enabled
|
|
pub fn none() -> Self {
|
|
Self {
|
|
timeout: false,
|
|
lock: false,
|
|
deadlock: false,
|
|
backpressure: false,
|
|
scheduler: false,
|
|
}
|
|
}
|
|
|
|
/// Check if any feature is enabled
|
|
pub fn any_enabled(&self) -> bool {
|
|
self.timeout || self.lock || self.deadlock || self.backpressure || self.scheduler
|
|
}
|
|
}
|
|
|
|
/// Facade policy for lock manager behavior.
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct LockManagerPolicy {
|
|
/// Enable lock optimization.
|
|
pub enabled: bool,
|
|
/// Lock acquisition timeout.
|
|
pub acquire_timeout: Duration,
|
|
}
|
|
|
|
impl Default for LockManagerPolicy {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
acquire_timeout: Duration::from_secs(5),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Main configuration for concurrency management
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct ConcurrencyConfig {
|
|
/// Feature flags
|
|
pub features: ConcurrencyFeatures,
|
|
/// Timeout facade policy.
|
|
pub timeout_policy: TimeoutManagerPolicy,
|
|
/// Lock facade policy.
|
|
pub lock_policy: LockManagerPolicy,
|
|
/// Deadlock facade policy.
|
|
pub deadlock_policy: DeadlockMonitorPolicy,
|
|
/// Backpressure facade policy.
|
|
pub backpressure_policy: PipeBackpressurePolicy,
|
|
/// Scheduler facade policy.
|
|
pub scheduler_policy: SchedulerPolicy,
|
|
}
|
|
|
|
impl ConcurrencyConfig {
|
|
/// Create configuration from environment variables
|
|
pub fn from_env() -> Self {
|
|
let mut config = Self::default();
|
|
|
|
// Read from environment if available
|
|
if let Ok(val) = std::env::var("RUSTFS_TIMEOUT_DEFAULT")
|
|
&& let Ok(secs) = val.parse::<u64>()
|
|
{
|
|
config.timeout_policy.default_timeout = Duration::from_secs(secs);
|
|
}
|
|
|
|
if let Ok(val) = std::env::var("RUSTFS_TIMEOUT_MAX")
|
|
&& let Ok(secs) = val.parse::<u64>()
|
|
{
|
|
config.timeout_policy.max_timeout = Duration::from_secs(secs);
|
|
}
|
|
|
|
if let Ok(val) = std::env::var("RUSTFS_BACKPRESSURE_BUFFER_SIZE")
|
|
&& let Ok(size) = val.parse::<usize>()
|
|
{
|
|
config.backpressure_policy.buffer_size = size;
|
|
}
|
|
|
|
if let Ok(val) = std::env::var("RUSTFS_IO_BUFFER_SIZE")
|
|
&& let Ok(size) = val.parse::<usize>()
|
|
{
|
|
config.scheduler_policy.base_buffer_size = size;
|
|
}
|
|
|
|
config
|
|
}
|
|
|
|
/// Validate configuration
|
|
pub fn validate(&self) -> Result<(), ConfigError> {
|
|
if self.timeout_policy.default_timeout > self.timeout_policy.max_timeout {
|
|
return Err(ConfigError::InvalidTimeout("default_timeout cannot exceed max_timeout".to_string()));
|
|
}
|
|
if self.timeout_policy.min_timeout > self.timeout_policy.max_timeout {
|
|
return Err(ConfigError::InvalidTimeout("min_timeout cannot exceed max_timeout".to_string()));
|
|
}
|
|
|
|
if self.backpressure_policy.high_watermark <= self.backpressure_policy.low_watermark
|
|
|| self.backpressure_policy.high_watermark > 100
|
|
{
|
|
return Err(ConfigError::InvalidBackpressure(
|
|
"high_watermark must be > low_watermark and <= 100".to_string(),
|
|
));
|
|
}
|
|
|
|
if self.scheduler_policy.base_buffer_size > self.scheduler_policy.max_buffer_size {
|
|
return Err(ConfigError::InvalidScheduler(
|
|
"base_buffer_size cannot exceed max_buffer_size".to_string(),
|
|
));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Configuration error
|
|
#[allow(clippy::enum_variant_names)]
|
|
#[derive(Debug, Clone, thiserror::Error)]
|
|
pub enum ConfigError {
|
|
/// Invalid timeout configuration
|
|
#[error("Invalid timeout config: {0}")]
|
|
InvalidTimeout(String),
|
|
|
|
/// Invalid backpressure configuration
|
|
#[error("Invalid backpressure config: {0}")]
|
|
InvalidBackpressure(String),
|
|
|
|
/// Invalid scheduler configuration
|
|
#[error("Invalid scheduler config: {0}")]
|
|
InvalidScheduler(String),
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_default_config() {
|
|
let config = ConcurrencyConfig::default();
|
|
assert!(config.validate().is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_invalid_timeout() {
|
|
let config = ConcurrencyConfig {
|
|
timeout_policy: TimeoutManagerPolicy {
|
|
default_timeout: Duration::from_secs(100),
|
|
max_timeout: Duration::from_secs(50),
|
|
enable_dynamic: true,
|
|
..Default::default()
|
|
},
|
|
..Default::default()
|
|
};
|
|
assert!(
|
|
config.validate().is_err(),
|
|
"validate() should return an error when default_timeout > max_timeout"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_invalid_min_timeout() {
|
|
let config = ConcurrencyConfig {
|
|
timeout_policy: TimeoutManagerPolicy {
|
|
min_timeout: Duration::from_secs(100),
|
|
max_timeout: Duration::from_secs(50),
|
|
..Default::default()
|
|
},
|
|
..Default::default()
|
|
};
|
|
assert!(
|
|
config.validate().is_err(),
|
|
"validate() should return an error when min_timeout > max_timeout"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_features() {
|
|
let features = ConcurrencyFeatures::all();
|
|
assert!(features.any_enabled());
|
|
|
|
let features = ConcurrencyFeatures::none();
|
|
assert!(!features.any_enabled());
|
|
}
|
|
}
|