use crate::types::{AbsoluteOffset, GroupId, Request, ReservationId};
use std::ops::Range;
use thiserror::Error;
use tokio::sync::{mpsc, oneshot};
#[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum ManagerError {
#[error("内部逻辑错误: {0}")]
Internal(String),
#[error("管理器当前正在执行 Finalize 操作,不接受新请求")]
ManagerFinalizing,
#[error("预留 ID {0} 未找到")]
ReservationNotFound(ReservationId),
#[error(
"预留 ID {reservation_id} 的提交大小不匹配: 期望 {expected} 字节, 实际收到 {actual} 字节"
)]
CommitSizeMismatch {
reservation_id: ReservationId,
expected: usize,
actual: usize,
},
#[error("预留 ID {0} 已经被提交过数据")]
AlreadyCommitted(ReservationId),
#[error(
"提交偏移量无效 (预留 ID {0}): 提交偏移量 {1} 与预留记录的范围 {2:?} 不匹配"
)]
SubmitOffsetInvalid(
ReservationId,
AbsoluteOffset, Range<AbsoluteOffset>, ),
#[error(
"提交的数据块范围无效 (预留 ID {0}): 块偏移 {1}, 块长度 {2} 超出了预留范围 {3:?}"
)]
SubmitRangeInvalid(
ReservationId,
AbsoluteOffset, usize, Range<AbsoluteOffset>, ),
#[error(
"单次提交数据大小不正确 (预留 ID {reservation_id}): 期望 {expected} 字节, 实际提供 {actual} 字节"
)]
SubmitSizeIncorrect {
reservation_id: ReservationId,
expected: usize,
actual: usize,
},
#[error(
"分块提交时块大小过大 (预留 ID {reservation_id}): 预留剩余空间 {largest} 字节, 尝试添加 {actual} 字节"
)]
SubmitSizeTooLarge {
reservation_id: ReservationId,
largest: usize,
actual: usize,
},
#[error("未能找到预留 ID {0} 关联的分组 ID (内部错误)")]
GroupNotFoundForReservation(ReservationId),
#[error("分组 ID {0} 未找到 (内部错误)")]
GroupNotFound(GroupId),
#[error("分组 {0} 的数据块不连续: 在偏移 {1} 后期望下一个块从 {1} 开始, 但实际为 {2}")]
GroupNotContiguous(GroupId, AbsoluteOffset, AbsoluteOffset),
#[error(
"分组 {0} 的总大小不匹配: 元数据记录期望总大小 {1} 字节, 实际提交数据总大小 {2} 字节"
)]
GroupSizeMismatch(GroupId, usize, usize),
#[error(
"分组 {0} 的起始偏移不匹配: 元数据记录期望偏移 {1:?}, 实际第一个数据块偏移 {2:?}"
)]
GroupOffsetMismatch(
GroupId,
Option<AbsoluteOffset>, Option<AbsoluteOffset>, ),
#[error("分组 {0} 因包含失败的预留而无法被视为成功处理")]
GroupContainsFailures(GroupId),
#[error("发送分组 {0} 的成功合并数据失败 (通道可能已关闭或已满)")]
SendCompletionFailed(GroupId),
#[error("合并分组 {0} 的数据块后大小校验失败: 期望 {1} 字节, 实际得到 {2} 字节")]
MergeSizeMismatch(GroupId, usize, usize),
}
#[derive(Error, Debug)]
pub enum BufferError {
#[error("向管理器发送请求失败 (管理器可能已停止): {0}")]
SendRequestError(#[from] mpsc::error::SendError<Request>),
#[error("从管理器接收回复失败 (管理器可能已停止): {0}")]
ReceiveReplyError(#[from] oneshot::error::RecvError),
#[error("管理器报告处理错误: {0}")]
ManagerError(#[from] ManagerError),
}
#[cfg(test)]
mod tests {
use super::*;
use std::ops::Range;
#[test]
fn test_manager_error_creation_and_equality() {
assert_eq!(
ManagerError::Internal("test".to_string()),
ManagerError::Internal("test".to_string())
);
assert_ne!(
ManagerError::Internal("test1".to_string()),
ManagerError::Internal("test2".to_string())
);
assert_eq!(
ManagerError::ManagerFinalizing,
ManagerError::ManagerFinalizing
);
assert_eq!(
ManagerError::ReservationNotFound(1),
ManagerError::ReservationNotFound(1)
);
assert_ne!(
ManagerError::ReservationNotFound(1),
ManagerError::ReservationNotFound(2)
);
let cs_mismatch1 = ManagerError::CommitSizeMismatch {
reservation_id: 1,
expected: 100,
actual: 90,
};
let cs_mismatch2 = ManagerError::CommitSizeMismatch {
reservation_id: 1,
expected: 100,
actual: 90,
};
let cs_mismatch3 = ManagerError::CommitSizeMismatch {
reservation_id: 2, expected: 100,
actual: 90,
};
assert_eq!(cs_mismatch1, cs_mismatch2); assert_ne!(cs_mismatch1, cs_mismatch3);
assert_eq!(
ManagerError::AlreadyCommitted(1),
ManagerError::AlreadyCommitted(1)
);
let offset_invalid1 = ManagerError::SubmitOffsetInvalid(1, 10, Range { start: 0, end: 20 });
let offset_invalid2 = ManagerError::SubmitOffsetInvalid(1, 10, Range { start: 0, end: 20 });
assert_eq!(offset_invalid1, offset_invalid2);
let range_invalid1 =
ManagerError::SubmitRangeInvalid(1, 5, 10, Range { start: 0, end: 10 });
let range_invalid2 =
ManagerError::SubmitRangeInvalid(1, 5, 10, Range { start: 0, end: 10 });
assert_eq!(range_invalid1, range_invalid2);
let size_incorrect1 = ManagerError::SubmitSizeIncorrect {
reservation_id: 1,
expected: 10,
actual: 5,
};
let size_incorrect2 = ManagerError::SubmitSizeIncorrect {
reservation_id: 1,
expected: 10,
actual: 5,
};
assert_eq!(size_incorrect1, size_incorrect2);
let size_too_large1 = ManagerError::SubmitSizeTooLarge {
reservation_id: 1,
largest: 10,
actual: 15,
};
let size_too_large2 = ManagerError::SubmitSizeTooLarge {
reservation_id: 1,
largest: 10,
actual: 15,
};
assert_eq!(size_too_large1, size_too_large2);
assert_eq!(
ManagerError::GroupNotFoundForReservation(1),
ManagerError::GroupNotFoundForReservation(1)
);
assert_eq!(
ManagerError::GroupNotFound(1),
ManagerError::GroupNotFound(1)
);
assert_eq!(
ManagerError::GroupNotContiguous(1, 100, 110),
ManagerError::GroupNotContiguous(1, 100, 110)
);
assert_eq!(
ManagerError::GroupSizeMismatch(1, 100, 90),
ManagerError::GroupSizeMismatch(1, 100, 90)
);
assert_eq!(
ManagerError::GroupOffsetMismatch(1, Some(0), Some(10)),
ManagerError::GroupOffsetMismatch(1, Some(0), Some(10))
);
assert_eq!(
ManagerError::GroupContainsFailures(1),
ManagerError::GroupContainsFailures(1)
);
assert_eq!(
ManagerError::SendCompletionFailed(1),
ManagerError::SendCompletionFailed(1)
);
assert_eq!(
ManagerError::MergeSizeMismatch(1, 100, 90),
ManagerError::MergeSizeMismatch(1, 100, 90)
);
}
#[test]
fn test_manager_error_display() {
assert_eq!(
format!("{}", ManagerError::Internal("abc".to_string())),
"内部逻辑错误: abc"
);
assert_eq!(
format!("{}", ManagerError::ManagerFinalizing),
"管理器当前正在执行 Finalize 操作,不接受新请求"
);
assert_eq!(
format!("{}", ManagerError::ReservationNotFound(42)),
"预留 ID 42 未找到"
);
assert_eq!(
format!("{}", ManagerError::CommitSizeMismatch{ reservation_id: 1, expected: 10, actual: 8}),
"预留 ID 1 的提交大小不匹配: 期望 10 字节, 实际收到 8 字节"
);
}
#[test]
fn test_buffer_error_from_manager_error() {
let manager_err = ManagerError::ReservationNotFound(123);
let buffer_err: BufferError = manager_err.clone().into();
match buffer_err {
BufferError::ManagerError(me) => assert_eq!(me, manager_err),
_ => panic!("Expected BufferError::ManagerError"),
}
}
}