fix(logging): reduce listing cancellation error noise (#4372)

* fix(logging): reduce listing cancellation error noise

* fix(ecstore): preserve filemeta io error kind

* fix(ecstore): avoid redundant clone lint in test

---------

Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: overtrue <anzhengchao@gmail.com>
This commit is contained in:
cxymds
2026-07-08 09:35:24 +08:00
committed by GitHub
parent 3c3113619e
commit d25ddb0e1e
4 changed files with 240 additions and 42 deletions
+66 -1
View File
@@ -13,6 +13,7 @@
// limitations under the License.
use rustfs_rio::{InternodeHttpError, InternodeHttpErrorKind};
use std::error::Error as StdError;
use std::hash::{Hash, Hasher};
use std::io::{self};
use std::path::PathBuf;
@@ -20,6 +21,8 @@ use std::path::PathBuf;
pub type Error = DiskError;
pub type Result<T> = core::result::Result<T, Error>;
const METACACHE_OUTPUT_STREAM_CLOSED: &str = "metacache output stream closed";
// DiskError == StorageErr
#[derive(Debug, thiserror::Error)]
pub enum DiskError {
@@ -158,6 +161,26 @@ impl DiskError {
DiskError::Io(std::io::Error::other(error))
}
pub(crate) fn metacache_output_stream_closed() -> Self {
DiskError::Io(std::io::Error::new(std::io::ErrorKind::BrokenPipe, METACACHE_OUTPUT_STREAM_CLOSED))
}
pub(crate) fn is_metacache_output_stream_closed(&self) -> bool {
matches!(
self,
DiskError::Io(io_error)
if io_error.kind() == std::io::ErrorKind::BrokenPipe
&& io_error.to_string() == METACACHE_OUTPUT_STREAM_CLOSED
)
}
pub(crate) fn contains_io_error_kind(&self, kind: std::io::ErrorKind) -> bool {
match self {
DiskError::Io(io_error) => io_error_chain_contains_kind(io_error, kind),
_ => false,
}
}
pub fn is_all_not_found(errs: &[Option<DiskError>]) -> bool {
for err in errs.iter() {
if let Some(err) = err {
@@ -250,7 +273,7 @@ impl DiskError {
impl From<rustfs_filemeta::Error> for DiskError {
fn from(e: rustfs_filemeta::Error) -> Self {
match e {
rustfs_filemeta::Error::Io(e) => DiskError::other(e),
rustfs_filemeta::Error::Io(e) => DiskError::Io(e),
rustfs_filemeta::Error::FileNotFound => DiskError::FileNotFound,
rustfs_filemeta::Error::FileVersionNotFound => DiskError::FileVersionNotFound,
rustfs_filemeta::Error::FileCorrupt => DiskError::FileCorrupt,
@@ -260,6 +283,29 @@ impl From<rustfs_filemeta::Error> for DiskError {
}
}
fn io_error_chain_contains_kind(io_error: &std::io::Error, kind: std::io::ErrorKind) -> bool {
if io_error.kind() == kind {
return true;
}
let mut source = StdError::source(io_error);
while let Some(err) = source {
if let Some(io_error) = err.downcast_ref::<std::io::Error>()
&& io_error.kind() == kind
{
return true;
}
if let Some(disk_error) = err.downcast_ref::<DiskError>()
&& disk_error.contains_io_error_kind(kind)
{
return true;
}
source = err.source();
}
false
}
impl From<std::io::Error> for DiskError {
fn from(e: std::io::Error) -> Self {
match e.downcast::<DiskError>() {
@@ -900,6 +946,25 @@ mod tests {
assert!(converted_io.to_string().contains("broken pipe"));
}
#[test]
fn test_wrapped_io_error_kind_detection() {
let filemeta_error = rustfs_filemeta::Error::Io(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "broken pipe"));
let disk_error = DiskError::from(filemeta_error);
assert!(disk_error.contains_io_error_kind(std::io::ErrorKind::BrokenPipe));
assert!(!disk_error.contains_io_error_kind(std::io::ErrorKind::TimedOut));
}
#[test]
fn test_metacache_output_stream_closed_classification_survives_clone() {
let disk_error = DiskError::metacache_output_stream_closed();
let cloned_error = disk_error.clone();
assert!(disk_error.is_metacache_output_stream_closed());
assert!(cloned_error.is_metacache_output_stream_closed());
assert_eq!(disk_error, cloned_error);
}
#[test]
fn test_error_display_preservation() {
let disk_errors = vec![