mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-28 16:07:05 +00:00
Fix/getobjectlength (#920)
* fix getobject content length resp * Fix regression in exception handling for non-existent key with enhanced compression predicate and metadata improvements (#915) * Initial plan * Fix GetObject regression by excluding error responses from compression The issue was that CompressionLayer was attempting to compress error responses, which could cause Content-Length header mismatches. By excluding 4xx and 5xx responses from compression, we ensure error responses (like NoSuchKey) are sent correctly without body truncation. Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * Enhance NoSuchKey fix with improved compression predicate and comprehensive tests - Enhanced ShouldCompress predicate with size-based exclusion (< 256 bytes) - Added detailed documentation explaining the compression logic - Added debug logging for better observability - Created comprehensive test suite with 4 test cases: - test_get_deleted_object_returns_nosuchkey - test_head_deleted_object_returns_nosuchkey - test_get_nonexistent_object_returns_nosuchkey - test_multiple_gets_deleted_object - Added extensive inline documentation and comments - Created docs/fix-nosuchkey-regression.md with full analysis Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * Add compression best practices documentation Added comprehensive guide covering: - Best practices for HTTP response compression - Common pitfalls and solutions - Performance considerations and trade-offs - Testing guidelines and examples - Monitoring and alerting recommendations - Migration guide for existing services Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * fix * fmt * fmt * Fix/objectdelete (#917) * fix getobject content length resp * fix delete object --------- Co-authored-by: houseme <housemecn@gmail.com> * Add comprehensive analysis of NoSuchKey fix and related improvements Created detailed documentation analyzing: - HTTP compression layer fix (primary issue) - Content-length calculation fix from PR #917 - Delete object metadata fixes from PR #917 - How all components work together - Complete scenario walkthrough - Performance impact analysis - Testing strategy and deployment checklist This ties together all the changes in the PR branch including the merged improvements from PR #917. Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * replace `once_cell` to `std` * fmt --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> Co-authored-by: houseme <housemecn@gmail.com> Co-authored-by: weisd <im@weisd.in> * fmt --------- Co-authored-by: weisd <weishidavip@163.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> Co-authored-by: weisd <im@weisd.in>
This commit is contained in:
+21
-24
@@ -73,13 +73,13 @@ pub const MAX_DELETE_LIST: usize = 1000;
|
||||
// ============================================================================
|
||||
|
||||
// Global singleton FastLock manager shared across all lock implementations
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
/// Enum wrapper for different lock manager implementations
|
||||
pub enum GlobalLockManager {
|
||||
Enabled(Arc<fast_lock::FastObjectLockManager>),
|
||||
Disabled(fast_lock::DisabledLockManager),
|
||||
Enabled(Arc<FastObjectLockManager>),
|
||||
Disabled(DisabledLockManager),
|
||||
}
|
||||
|
||||
impl Default for GlobalLockManager {
|
||||
@@ -99,11 +99,11 @@ impl GlobalLockManager {
|
||||
match locks_enabled.as_str() {
|
||||
"false" | "0" | "no" | "off" | "disabled" => {
|
||||
tracing::info!("Lock system disabled via RUSTFS_ENABLE_LOCKS environment variable");
|
||||
Self::Disabled(fast_lock::DisabledLockManager::new())
|
||||
Self::Disabled(DisabledLockManager::new())
|
||||
}
|
||||
_ => {
|
||||
tracing::info!("Lock system enabled");
|
||||
Self::Enabled(Arc::new(fast_lock::FastObjectLockManager::new()))
|
||||
Self::Enabled(Arc::new(FastObjectLockManager::new()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ impl GlobalLockManager {
|
||||
}
|
||||
|
||||
/// Get the FastObjectLockManager if enabled, otherwise returns None
|
||||
pub fn as_fast_lock_manager(&self) -> Option<Arc<fast_lock::FastObjectLockManager>> {
|
||||
pub fn as_fast_lock_manager(&self) -> Option<Arc<FastObjectLockManager>> {
|
||||
match self {
|
||||
Self::Enabled(manager) => Some(manager.clone()),
|
||||
Self::Disabled(_) => None,
|
||||
@@ -123,11 +123,8 @@ impl GlobalLockManager {
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl fast_lock::LockManager for GlobalLockManager {
|
||||
async fn acquire_lock(
|
||||
&self,
|
||||
request: fast_lock::ObjectLockRequest,
|
||||
) -> std::result::Result<fast_lock::FastLockGuard, fast_lock::LockResult> {
|
||||
impl LockManager for GlobalLockManager {
|
||||
async fn acquire_lock(&self, request: ObjectLockRequest) -> std::result::Result<FastLockGuard, LockResult> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_lock(request).await,
|
||||
Self::Disabled(manager) => manager.acquire_lock(request).await,
|
||||
@@ -139,7 +136,7 @@ impl fast_lock::LockManager for GlobalLockManager {
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> std::result::Result<fast_lock::FastLockGuard, fast_lock::LockResult> {
|
||||
) -> std::result::Result<FastLockGuard, LockResult> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_read_lock(bucket, object, owner).await,
|
||||
Self::Disabled(manager) => manager.acquire_read_lock(bucket, object, owner).await,
|
||||
@@ -152,7 +149,7 @@ impl fast_lock::LockManager for GlobalLockManager {
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> std::result::Result<fast_lock::FastLockGuard, fast_lock::LockResult> {
|
||||
) -> std::result::Result<FastLockGuard, LockResult> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_read_lock_versioned(bucket, object, version, owner).await,
|
||||
Self::Disabled(manager) => manager.acquire_read_lock_versioned(bucket, object, version, owner).await,
|
||||
@@ -164,7 +161,7 @@ impl fast_lock::LockManager for GlobalLockManager {
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> std::result::Result<fast_lock::FastLockGuard, fast_lock::LockResult> {
|
||||
) -> std::result::Result<FastLockGuard, LockResult> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_write_lock(bucket, object, owner).await,
|
||||
Self::Disabled(manager) => manager.acquire_write_lock(bucket, object, owner).await,
|
||||
@@ -177,21 +174,21 @@ impl fast_lock::LockManager for GlobalLockManager {
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> std::result::Result<fast_lock::FastLockGuard, fast_lock::LockResult> {
|
||||
) -> std::result::Result<FastLockGuard, LockResult> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_write_lock_versioned(bucket, object, version, owner).await,
|
||||
Self::Disabled(manager) => manager.acquire_write_lock_versioned(bucket, object, version, owner).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn acquire_locks_batch(&self, batch_request: fast_lock::BatchLockRequest) -> fast_lock::BatchLockResult {
|
||||
async fn acquire_locks_batch(&self, batch_request: BatchLockRequest) -> BatchLockResult {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.acquire_locks_batch(batch_request).await,
|
||||
Self::Disabled(manager) => manager.acquire_locks_batch(batch_request).await,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_lock_info(&self, key: &fast_lock::ObjectKey) -> Option<fast_lock::ObjectLockInfo> {
|
||||
fn get_lock_info(&self, key: &ObjectKey) -> Option<ObjectLockInfo> {
|
||||
match self {
|
||||
Self::Enabled(manager) => manager.get_lock_info(key),
|
||||
Self::Disabled(manager) => manager.get_lock_info(key),
|
||||
@@ -248,7 +245,7 @@ impl fast_lock::LockManager for GlobalLockManager {
|
||||
}
|
||||
}
|
||||
|
||||
static GLOBAL_LOCK_MANAGER: OnceCell<Arc<GlobalLockManager>> = OnceCell::new();
|
||||
static GLOBAL_LOCK_MANAGER: OnceLock<Arc<GlobalLockManager>> = OnceLock::new();
|
||||
|
||||
/// Get the global shared lock manager instance
|
||||
///
|
||||
@@ -263,7 +260,7 @@ pub fn get_global_lock_manager() -> Arc<GlobalLockManager> {
|
||||
/// This function is deprecated. Use get_global_lock_manager() instead.
|
||||
/// Returns FastObjectLockManager when locks are enabled, or panics when disabled.
|
||||
#[deprecated(note = "Use get_global_lock_manager() instead")]
|
||||
pub fn get_global_fast_lock_manager() -> Arc<fast_lock::FastObjectLockManager> {
|
||||
pub fn get_global_fast_lock_manager() -> Arc<FastObjectLockManager> {
|
||||
let manager = get_global_lock_manager();
|
||||
manager.as_fast_lock_manager().unwrap_or_else(|| {
|
||||
panic!("Cannot get FastObjectLockManager when locks are disabled. Use get_global_lock_manager() instead.");
|
||||
@@ -301,7 +298,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disabled_manager_direct() {
|
||||
let manager = fast_lock::DisabledLockManager::new();
|
||||
let manager = DisabledLockManager::new();
|
||||
|
||||
// All operations should succeed immediately
|
||||
let guard = manager.acquire_read_lock("bucket", "object", "owner").await;
|
||||
@@ -316,7 +313,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_enabled_manager_direct() {
|
||||
let manager = fast_lock::FastObjectLockManager::new();
|
||||
let manager = FastObjectLockManager::new();
|
||||
|
||||
// Operations should work normally
|
||||
let guard = manager.acquire_read_lock("bucket", "object", "owner").await;
|
||||
@@ -331,8 +328,8 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_global_manager_enum_wrapper() {
|
||||
// Test the GlobalLockManager enum directly
|
||||
let enabled_manager = GlobalLockManager::Enabled(Arc::new(fast_lock::FastObjectLockManager::new()));
|
||||
let disabled_manager = GlobalLockManager::Disabled(fast_lock::DisabledLockManager::new());
|
||||
let enabled_manager = GlobalLockManager::Enabled(Arc::new(FastObjectLockManager::new()));
|
||||
let disabled_manager = GlobalLockManager::Disabled(DisabledLockManager::new());
|
||||
|
||||
assert!(!enabled_manager.is_disabled());
|
||||
assert!(disabled_manager.is_disabled());
|
||||
@@ -352,7 +349,7 @@ mod tests {
|
||||
async fn test_batch_operations_work() {
|
||||
let manager = get_global_lock_manager();
|
||||
|
||||
let batch = fast_lock::BatchLockRequest::new("owner")
|
||||
let batch = BatchLockRequest::new("owner")
|
||||
.add_read_lock("bucket", "obj1")
|
||||
.add_write_lock("bucket", "obj2");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user