// 移植自 github.com/milvus-io/milvus client/internal/merr (Apache-2.0)
// Copyright (c) LF AI & Data Foundation
///|
/// Milvus RPC 错误的客户端模型。
///
/// 与上游 `merr.RPCError` 一一对应:同一个 Milvus `code` 视为同一个错误,
/// 双轨错误码(modern `code` + legacy `ErrorCode`)整体保留,不简化。
///
/// 构造用带标签的语法;典型路径是 `from_status`,需要手工造错时用
/// 预定义值加 `wrap_*`:
///
/// ```moonbit nocheck
/// let err = @errors.wrap_err_collection_not_found("demo")
/// raise err
/// ```
///
/// 也可以直接构造:
///
/// ```moonbit nocheck
/// raise RpcError(
/// code=100,
/// legacy_code=@common.ErrorCode::CollectionNotExists,
/// message="collection not found",
/// detail="collection not found",
/// retriable=false,
/// input=false,
/// )
/// ```
pub suberror MerError {
/// Milvus modern 数值错误码(`Status.code`),未知码按原值保留。
RpcError(
code~ : Int,
/// 已废弃的 legacy 错误码(`Status.error_code`)。
legacy_code~ : @common.ErrorCode,
/// 面向用户的错误摘要,等价于上游 `RPCError.Error()`。
message~ : String,
/// 服务端返回的详细错误信息(`Status.detail`)。
detail~ : String,
/// 服务端标记的可重试位(`Status.retriable`)。
retriable~ : Bool,
/// 服务端是否把该错误归类为输入错误(`extra_info["is_input_error"] == "true"`)。
input~ : Bool
)
}
///|
/// 错误摘要,与上游 `RPCError.Error()` 一致。
pub impl Show for MerError with fn to_string(self) {
match self {
RpcError(message~, ..) => message
}
}
///|
/// 取错误码。与上游 `merr.Code` 一致;`None` 等价于上游的 `err == nil`。
pub fn MerError::code(self : MerError?) -> Int {
match self {
None => 0
Some(RpcError(code~, ..)) => code
}
}
///|
/// 取 legacy 错误码。`None` 视为 `Success`。
pub fn MerError::legacy_code(self : MerError?) -> @common.ErrorCode {
match self {
None => @common.ErrorCode::Success
Some(RpcError(legacy_code~, ..)) => legacy_code
}
}
///|
/// 取服务端下发的详细错误信息。
pub fn MerError::detail(self : MerError?) -> String {
match self {
None => ""
Some(RpcError(detail~, ..)) => detail
}
}
///|
/// 服务端是否标记该错误可重试。这正是上游 `IsRetryableErr` 的语义:
/// 只看 `Status.retriable`,不做本地猜测。
pub fn MerError::is_retryable(self : MerError?) -> Bool {
match self {
None => false
Some(RpcError(retriable~, ..)) => retriable
}
}
///|
/// 服务端是否把该错误归类为输入错误。
pub fn MerError::is_input_error(self : MerError?) -> Bool {
match self {
None => false
Some(RpcError(input~, ..)) => input
}
}
///|
/// 依据 Milvus `code` 判断两个错误是否同类,对应上游 `RPCError.Is`
/// (`errors.Is` 靠 code 匹配,而不是靠错误文本)。
pub fn MerError::same_code(self : MerError, other : MerError) -> Bool {
match (self, other) {
(RpcError(code~, ..), RpcError(code=other_code, ..)) => code == other_code
}
}
///|
/// 取错误码。与上游 `merr.Code` 一致;`None` 等价于上游的 `err == nil`。
pub fn error_code(err : MerError?) -> Int {
MerError::code(err)
}
///|
/// 取 legacy 错误码。`None` 视为 `Success`。
pub fn error_legacy_code(err : MerError?) -> @common.ErrorCode {
MerError::legacy_code(err)
}
///|
/// 取服务端下发的详细错误信息。
pub fn error_detail(err : MerError?) -> String {
MerError::detail(err)
}
///|
/// 服务端是否标记该错误可重试。这正是上游 `IsRetryableErr` 的语义:
/// 只看 `Status.retriable`,不做本地猜测。
///
/// 这是给 retry 中间件看的唯一判据,等价于上游 `merr.IsRetryableErr`。
pub fn is_retryable_err(err : MerError?) -> Bool {
MerError::is_retryable(err)
}
///|
/// 服务端是否把该错误归类为输入错误。
pub fn is_input_error(err : MerError?) -> Bool {
MerError::is_input_error(err)
}