mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
explorerd/error: enhance error module with parameterized errors and conversions
Enhanced the `explorerd` error module by introducing parameterized errors, improving error propagation through conversions, renaming for clarity, and refining JSON-RPC error handling. Updates include: - Renamed `RpcError` to `ExplorerdError` for use across all application layers (rpc, service, store) - Updated `ExplorerdError` to support parameterized error variants for more detailed and flexible error messages - Added conversions from `ExplorerdError` to `RpcError` and `Error` to aid with error propagation from individual RPC handlers to the `handle_request` method - Renamed `to_tuple` to `to_error_code_message` for improved readability and updated it to support parameterized errors - Revised the `server_error` function to construct `JsonError` responses using `ExplorerdError` - Updated Cargo.toml to include thiserror support - Updated `mod/ping_darkfid` function to use the updated `ExplorerdError`, including error details for additional context
This commit is contained in:
@@ -38,6 +38,7 @@ log = "0.4.26"
|
||||
lazy_static = "1.5.0"
|
||||
tar = "0.4.44"
|
||||
toml = "0.8.20"
|
||||
thiserror = "2.0.11"
|
||||
|
||||
# Testing
|
||||
tempdir = "0.3.7"
|
||||
|
||||
@@ -16,44 +16,77 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::{fmt, sync::Arc};
|
||||
|
||||
use log::error;
|
||||
|
||||
use darkfi::{
|
||||
rpc::jsonrpc::{ErrorCode::ServerError, JsonError, JsonResult},
|
||||
Error,
|
||||
rpc::jsonrpc::{ErrorCode, JsonError},
|
||||
Error, RpcError,
|
||||
};
|
||||
|
||||
// Constant for the error code
|
||||
pub const ERROR_CODE_PING_DARKFID_FAILED: i32 = -32300;
|
||||
|
||||
/// Custom RPC errors available for blockchain explorer.
|
||||
/// Please sort them sensefully.
|
||||
pub enum RpcError {
|
||||
// Misc errors
|
||||
PingFailed = -32300,
|
||||
/// These represent specific RPC-related failures.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ExplorerdError {
|
||||
#[error("Ping darkfid failed: {0}")]
|
||||
PingDarkfidFailed(String),
|
||||
|
||||
#[error("Invalid contract ID: {0}")]
|
||||
InvalidContractId(String),
|
||||
|
||||
#[error("Invalid header hash: {0}")]
|
||||
InvalidHeaderHash(String),
|
||||
|
||||
#[error("Invalid tx hash: {0}")]
|
||||
InvalidTxHash(String),
|
||||
}
|
||||
|
||||
fn to_tuple(e: RpcError) -> (i32, String) {
|
||||
let msg = match e {
|
||||
// Misc errors
|
||||
RpcError::PingFailed => "Darkfid daemon ping error",
|
||||
};
|
||||
|
||||
(e as i32, msg.to_string())
|
||||
}
|
||||
|
||||
pub fn server_error(e: RpcError, id: u16, msg: Option<&str>) -> JsonResult {
|
||||
let (code, default_msg) = to_tuple(e);
|
||||
|
||||
if let Some(message) = msg {
|
||||
return JsonError::new(ServerError(code), Some(message.to_string()), id).into()
|
||||
/// Provides a conversion from [`ExplorerdError`] to darkfi [`Error`] type.
|
||||
impl From<ExplorerdError> for Error {
|
||||
fn from(err: ExplorerdError) -> Self {
|
||||
let error: RpcError = err.into();
|
||||
error.into()
|
||||
}
|
||||
|
||||
JsonError::new(ServerError(code), Some(default_msg), id).into()
|
||||
}
|
||||
|
||||
/// Handles a database error by formatting the output, logging it with target-specific context,
|
||||
/// and returning a [`DatabaseError`].
|
||||
pub fn handle_database_error(target: &str, message: &str, error: impl std::fmt::Debug) -> Error {
|
||||
/// Conversion from [`ExplorerdRpcError`] to [`RpcError`]
|
||||
impl From<ExplorerdError> for RpcError {
|
||||
fn from(err: ExplorerdError) -> Self {
|
||||
RpcError::ServerError(Arc::new(err))
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to convert `ExplorerdRpcError` into error code with corresponding error message.
|
||||
pub fn to_error_code_message(e: &ExplorerdError) -> (i32, String) {
|
||||
match e {
|
||||
ExplorerdError::PingDarkfidFailed(_) => (ERROR_CODE_PING_DARKFID_FAILED, e.to_string()),
|
||||
ExplorerdError::InvalidContractId(_) |
|
||||
ExplorerdError::InvalidHeaderHash(_) |
|
||||
ExplorerdError::InvalidTxHash(_) => (ErrorCode::InvalidParams.code(), e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a [`JsonError`] representing a server error using the provided
|
||||
/// [`ExplorerdError`] , request ID, and optional custom message, returning a [`JsonError`]
|
||||
/// with a corresponding server error code and message.
|
||||
pub fn server_error(e: &ExplorerdError, id: u16, msg: Option<&str>) -> JsonError {
|
||||
let (code, default_msg) = to_error_code_message(e);
|
||||
|
||||
// Use the provided custom message if available; otherwise, use the default.
|
||||
let message = msg.unwrap_or(&default_msg).to_string();
|
||||
|
||||
JsonError::new(ErrorCode::ServerError(code), Some(message), id)
|
||||
}
|
||||
|
||||
/// Logs and converts a database error into a [`DatabaseError`].
|
||||
/// This function ensures the error is logged contextually before being returned.
|
||||
pub fn handle_database_error(target: &str, message: &str, error: impl fmt::Debug) -> Error {
|
||||
let error_message = format!("{}: {:?}", message, error);
|
||||
let formatted_target = format!("explorerd:: {target}");
|
||||
let formatted_target = format!("explorerd::{}", target);
|
||||
error!(target: &formatted_target, "{}", error_message);
|
||||
Error::DatabaseError(error_message)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ use darkfi::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{server_error, RpcError},
|
||||
error::{server_error, ExplorerdError},
|
||||
Explorerd,
|
||||
};
|
||||
|
||||
@@ -221,7 +221,7 @@ impl Explorerd {
|
||||
debug!(target: "explorerd::rpc::ping_darkfid", "Pinging darkfid daemon...");
|
||||
if let Err(e) = self.darkfid_client.ping().await {
|
||||
error!(target: "explorerd::rpc::ping_darkfid", "Failed to ping darkfid daemon: {}", e);
|
||||
return server_error(RpcError::PingFailed, id, None)
|
||||
return server_error(&ExplorerdError::PingDarkfidFailed(e.to_string()), id, None).into()
|
||||
}
|
||||
JsonResponse::new(JsonValue::Boolean(true), id).into()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user