mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 22:57:59 -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"
|
lazy_static = "1.5.0"
|
||||||
tar = "0.4.44"
|
tar = "0.4.44"
|
||||||
toml = "0.8.20"
|
toml = "0.8.20"
|
||||||
|
thiserror = "2.0.11"
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
tempdir = "0.3.7"
|
tempdir = "0.3.7"
|
||||||
|
|||||||
@@ -16,44 +16,77 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::{fmt, sync::Arc};
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
use darkfi::{
|
use darkfi::{
|
||||||
rpc::jsonrpc::{ErrorCode::ServerError, JsonError, JsonResult},
|
rpc::jsonrpc::{ErrorCode, JsonError},
|
||||||
Error,
|
Error, RpcError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Constant for the error code
|
||||||
|
pub const ERROR_CODE_PING_DARKFID_FAILED: i32 = -32300;
|
||||||
|
|
||||||
/// Custom RPC errors available for blockchain explorer.
|
/// Custom RPC errors available for blockchain explorer.
|
||||||
/// Please sort them sensefully.
|
/// These represent specific RPC-related failures.
|
||||||
pub enum RpcError {
|
#[derive(Debug, thiserror::Error)]
|
||||||
// Misc errors
|
pub enum ExplorerdError {
|
||||||
PingFailed = -32300,
|
#[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) {
|
/// Provides a conversion from [`ExplorerdError`] to darkfi [`Error`] type.
|
||||||
let msg = match e {
|
impl From<ExplorerdError> for Error {
|
||||||
// Misc errors
|
fn from(err: ExplorerdError) -> Self {
|
||||||
RpcError::PingFailed => "Darkfid daemon ping error",
|
let error: RpcError = err.into();
|
||||||
};
|
error.into()
|
||||||
|
|
||||||
(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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonError::new(ServerError(code), Some(default_msg), id).into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a database error by formatting the output, logging it with target-specific context,
|
/// Conversion from [`ExplorerdRpcError`] to [`RpcError`]
|
||||||
/// and returning a [`DatabaseError`].
|
impl From<ExplorerdError> for RpcError {
|
||||||
pub fn handle_database_error(target: &str, message: &str, error: impl std::fmt::Debug) -> Error {
|
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 error_message = format!("{}: {:?}", message, error);
|
||||||
let formatted_target = format!("explorerd:: {target}");
|
let formatted_target = format!("explorerd::{}", target);
|
||||||
error!(target: &formatted_target, "{}", error_message);
|
error!(target: &formatted_target, "{}", error_message);
|
||||||
Error::DatabaseError(error_message)
|
Error::DatabaseError(error_message)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ use darkfi::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{server_error, RpcError},
|
error::{server_error, ExplorerdError},
|
||||||
Explorerd,
|
Explorerd,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ impl Explorerd {
|
|||||||
debug!(target: "explorerd::rpc::ping_darkfid", "Pinging darkfid daemon...");
|
debug!(target: "explorerd::rpc::ping_darkfid", "Pinging darkfid daemon...");
|
||||||
if let Err(e) = self.darkfid_client.ping().await {
|
if let Err(e) = self.darkfid_client.ping().await {
|
||||||
error!(target: "explorerd::rpc::ping_darkfid", "Failed to ping darkfid daemon: {}", e);
|
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()
|
JsonResponse::new(JsonValue::Boolean(true), id).into()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user