mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 15:16:56 +00:00
refactor(lock): restructure lock crate, remove unused modules and clarify directory layout
- Remove unused core/rwlock.rs and manager/ modules (ManagerFactory, LifecycleManager, NamespaceManager) - Move all lock-related code into crates/lock/src with clear submodules: client, core, utils, etc. - Ensure only necessary files and APIs are exposed, improve maintainability - No functional logic change, pure structure and cleanup refactor Signed-off-by: dandan <dandan@dandandeMac-Studio.local>
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
// 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.
|
||||
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Lock operation related error types
|
||||
#[derive(Error, Debug)]
|
||||
pub enum LockError {
|
||||
/// Lock acquisition timeout
|
||||
#[error("Lock acquisition timeout for resource '{resource}' after {timeout:?}")]
|
||||
Timeout { resource: String, timeout: Duration },
|
||||
|
||||
/// Resource not found
|
||||
#[error("Resource not found: {resource}")]
|
||||
ResourceNotFound { resource: String },
|
||||
|
||||
/// Permission denied
|
||||
#[error("Permission denied: {reason}")]
|
||||
PermissionDenied { reason: String },
|
||||
|
||||
/// Network error
|
||||
#[error("Network error: {message}")]
|
||||
Network {
|
||||
message: String,
|
||||
#[source]
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
/// Internal error
|
||||
#[error("Internal error: {message}")]
|
||||
Internal { message: String },
|
||||
|
||||
/// Resource is already locked
|
||||
#[error("Resource '{resource}' is already locked by {owner}")]
|
||||
AlreadyLocked { resource: String, owner: String },
|
||||
|
||||
/// Invalid lock handle
|
||||
#[error("Invalid lock handle: {handle_id}")]
|
||||
InvalidHandle { handle_id: String },
|
||||
|
||||
/// Configuration error
|
||||
#[error("Configuration error: {message}")]
|
||||
Configuration { message: String },
|
||||
|
||||
/// Serialization error
|
||||
#[error("Serialization error: {message}")]
|
||||
Serialization {
|
||||
message: String,
|
||||
#[source]
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
/// Deserialization error
|
||||
#[error("Deserialization error: {message}")]
|
||||
Deserialization {
|
||||
message: String,
|
||||
#[source]
|
||||
source: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
}
|
||||
|
||||
impl LockError {
|
||||
/// Create timeout error
|
||||
pub fn timeout(resource: impl Into<String>, timeout: Duration) -> Self {
|
||||
Self::Timeout {
|
||||
resource: resource.into(),
|
||||
timeout,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create resource not found error
|
||||
pub fn resource_not_found(resource: impl Into<String>) -> Self {
|
||||
Self::ResourceNotFound {
|
||||
resource: resource.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create permission denied error
|
||||
pub fn permission_denied(reason: impl Into<String>) -> Self {
|
||||
Self::PermissionDenied { reason: reason.into() }
|
||||
}
|
||||
|
||||
/// Create network error
|
||||
pub fn network(message: impl Into<String>, source: impl std::error::Error + Send + Sync + 'static) -> Self {
|
||||
Self::Network {
|
||||
message: message.into(),
|
||||
source: Box::new(source),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create internal error
|
||||
pub fn internal(message: impl Into<String>) -> Self {
|
||||
Self::Internal { message: message.into() }
|
||||
}
|
||||
|
||||
/// Create lock already locked error
|
||||
pub fn already_locked(resource: impl Into<String>, owner: impl Into<String>) -> Self {
|
||||
Self::AlreadyLocked {
|
||||
resource: resource.into(),
|
||||
owner: owner.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create invalid handle error
|
||||
pub fn invalid_handle(handle_id: impl Into<String>) -> Self {
|
||||
Self::InvalidHandle {
|
||||
handle_id: handle_id.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create configuration error
|
||||
pub fn configuration(message: impl Into<String>) -> Self {
|
||||
Self::Configuration { message: message.into() }
|
||||
}
|
||||
|
||||
/// Create serialization error
|
||||
pub fn serialization(message: impl Into<String>, source: impl std::error::Error + Send + Sync + 'static) -> Self {
|
||||
Self::Serialization {
|
||||
message: message.into(),
|
||||
source: Box::new(source),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create deserialization error
|
||||
pub fn deserialization(message: impl Into<String>, source: impl std::error::Error + Send + Sync + 'static) -> Self {
|
||||
Self::Deserialization {
|
||||
message: message.into(),
|
||||
source: Box::new(source),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if it is a retryable error
|
||||
pub fn is_retryable(&self) -> bool {
|
||||
matches!(self, Self::Timeout { .. } | Self::Network { .. } | Self::Internal { .. })
|
||||
}
|
||||
|
||||
/// Check if it is a fatal error
|
||||
pub fn is_fatal(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::ResourceNotFound { .. } | Self::PermissionDenied { .. } | Self::Configuration { .. }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Lock operation Result type
|
||||
pub type Result<T> = std::result::Result<T, LockError>;
|
||||
|
||||
/// Convert from std::io::Error
|
||||
impl From<std::io::Error> for LockError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
match err.kind() {
|
||||
std::io::ErrorKind::TimedOut => Self::Internal {
|
||||
message: "IO timeout".to_string(),
|
||||
},
|
||||
std::io::ErrorKind::NotFound => Self::ResourceNotFound {
|
||||
resource: "unknown".to_string(),
|
||||
},
|
||||
std::io::ErrorKind::PermissionDenied => Self::PermissionDenied { reason: err.to_string() },
|
||||
_ => Self::Internal {
|
||||
message: err.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from serde_json::Error
|
||||
impl From<serde_json::Error> for LockError {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
if err.is_io() {
|
||||
Self::network("JSON serialization IO error", err)
|
||||
} else if err.is_syntax() {
|
||||
Self::deserialization("JSON syntax error", err)
|
||||
} else if err.is_data() {
|
||||
Self::deserialization("JSON data error", err)
|
||||
} else {
|
||||
Self::serialization("JSON serialization error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from tonic::Status
|
||||
impl From<tonic::Status> for LockError {
|
||||
fn from(status: tonic::Status) -> Self {
|
||||
match status.code() {
|
||||
tonic::Code::DeadlineExceeded => Self::Internal {
|
||||
message: "gRPC deadline exceeded".to_string(),
|
||||
},
|
||||
tonic::Code::NotFound => Self::ResourceNotFound {
|
||||
resource: "unknown".to_string(),
|
||||
},
|
||||
tonic::Code::PermissionDenied => Self::PermissionDenied {
|
||||
reason: status.message().to_string(),
|
||||
},
|
||||
tonic::Code::Unavailable => Self::Network {
|
||||
message: "gRPC service unavailable".to_string(),
|
||||
source: Box::new(status),
|
||||
},
|
||||
_ => Self::Internal {
|
||||
message: status.message().to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_error_creation() {
|
||||
let timeout_err = LockError::timeout("test-resource", Duration::from_secs(5));
|
||||
assert!(matches!(timeout_err, LockError::Timeout { .. }));
|
||||
|
||||
let not_found_err = LockError::resource_not_found("missing-resource");
|
||||
assert!(matches!(not_found_err, LockError::ResourceNotFound { .. }));
|
||||
|
||||
let permission_err = LockError::permission_denied("insufficient privileges");
|
||||
assert!(matches!(permission_err, LockError::PermissionDenied { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_retryable() {
|
||||
let timeout_err = LockError::timeout("test", Duration::from_secs(1));
|
||||
assert!(timeout_err.is_retryable());
|
||||
|
||||
let network_err = LockError::network("connection failed", std::io::Error::new(std::io::ErrorKind::ConnectionRefused, ""));
|
||||
assert!(network_err.is_retryable());
|
||||
|
||||
let not_found_err = LockError::resource_not_found("test");
|
||||
assert!(!not_found_err.is_retryable());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_fatal() {
|
||||
let not_found_err = LockError::resource_not_found("test");
|
||||
assert!(not_found_err.is_fatal());
|
||||
|
||||
let permission_err = LockError::permission_denied("test");
|
||||
assert!(permission_err.is_fatal());
|
||||
|
||||
let timeout_err = LockError::timeout("test", Duration::from_secs(1));
|
||||
assert!(!timeout_err.is_fatal());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user