Skip to content

Commit

Permalink
remove CallError (#1087)
Browse files Browse the repository at this point in the history
* refactor: remove `CallError`

* use error msg in InvalidParams

* fix tests

* remove unused dependency anyhow

* Update core/src/error.rs

* Update core/src/lib.rs

* Update core/src/lib.rs

* fix nit

* fix error object display impl

* remove invalid params

* Update proc-macros/tests/ui/correct/only_client.rs

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>

* fix UI tests on new rustc

* invalid params: strictly jsonrpc spec

* grumbles: unify type hints

---------

Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
  • Loading branch information
niklasad1 and lexnv authored Apr 21, 2023
1 parent 5466279 commit d6a9622
Show file tree
Hide file tree
Showing 30 changed files with 237 additions and 293 deletions.
2 changes: 1 addition & 1 deletion benches/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ fn gen_rpc_module() -> jsonrpsee::RpcModule<()> {
module
.register_async_method(ASYNC_SLOW_CALL, |_, _| async move {
tokio::time::sleep(SLOW_CALL).await;
Result::<_, jsonrpsee::core::Error>::Ok("slow call async")
"slow call async"
})
.unwrap();

Expand Down
4 changes: 1 addition & 3 deletions client/http-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ use jsonrpsee_core::client::{
use jsonrpsee_core::params::BatchRequestBuilder;
use jsonrpsee_core::traits::ToRpcParams;
use jsonrpsee_core::{Error, JsonRawValue, TEN_MB_SIZE_BYTES};
use jsonrpsee_types::error::CallError;
use jsonrpsee_types::{ErrorObject, ResponseSuccess, TwoPointZero};
use serde::de::DeserializeOwned;
use tower::layer::util::Identity;
Expand Down Expand Up @@ -300,8 +299,7 @@ where

// NOTE: it's decoded first to `JsonRawValue` and then to `R` below to get
// a better error message if `R` couldn't be decoded.
let response = ResponseSuccess::try_from(serde_json::from_slice::<Response<&JsonRawValue>>(&body)?)
.map_err(|e| Error::Call(CallError::Custom(e)))?;
let response = ResponseSuccess::try_from(serde_json::from_slice::<Response<&JsonRawValue>>(&body)?)?;

let result = serde_json::from_str(response.result.get()).map_err(Error::ParseError)?;

Expand Down
5 changes: 2 additions & 3 deletions client/http-client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use jsonrpsee_core::{rpc_params, DeserializeOwned};
use jsonrpsee_test_utils::helpers::*;
use jsonrpsee_test_utils::mocks::Id;
use jsonrpsee_test_utils::TimeoutFutureExt;
use jsonrpsee_types::error::{CallError, ErrorObjectOwned};
use jsonrpsee_types::error::ErrorObjectOwned;

fn init_logger() {
let _ = tracing_subscriber::FmtSubscriber::builder()
Expand Down Expand Up @@ -276,10 +276,9 @@ async fn run_request_with_response(response: String) -> Result<String, Error> {
}

fn assert_jsonrpc_error_response(err: Error, exp: ErrorObjectOwned) {
let exp = CallError::Custom(exp);
match &err {
Error::Call(err) => {
assert_eq!(err.to_string(), exp.to_string());
assert_eq!(err, &exp);
}
e => panic!("Expected error: \"{err}\", got: {e:?}"),
};
Expand Down
5 changes: 2 additions & 3 deletions client/ws-client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use jsonrpsee_core::{rpc_params, DeserializeOwned, Error};
use jsonrpsee_test_utils::helpers::*;
use jsonrpsee_test_utils::mocks::{Id, WebSocketTestServer};
use jsonrpsee_test_utils::TimeoutFutureExt;
use jsonrpsee_types::error::{CallError, ErrorObjectOwned};
use jsonrpsee_types::error::ErrorObjectOwned;
use serde_json::Value as JsonValue;

fn init_logger() {
Expand Down Expand Up @@ -393,10 +393,9 @@ async fn run_request_with_response(response: String) -> Result<String, Error> {
}

fn assert_error_response(err: Error, exp: ErrorObjectOwned) {
let exp = CallError::Custom(exp);
match &err {
Error::Call(e) => {
assert_eq!(e.to_string(), exp.to_string());
assert_eq!(e, &exp);
}
e => panic!("Expected error: \"{err}\", got: {e:?}"),
};
Expand Down
3 changes: 1 addition & 2 deletions core/src/client/async_client/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use futures_timer::Delay;
use futures_util::future::{self, Either};
use tokio::sync::{mpsc, oneshot};

use jsonrpsee_types::error::CallError;
use jsonrpsee_types::response::SubscriptionError;
use jsonrpsee_types::{
ErrorObject, Id, Notification, RequestSer, Response, ResponseSuccess, SubscriptionId, SubscriptionResponse,
Expand Down Expand Up @@ -176,7 +175,7 @@ pub(crate) fn process_single_response(
max_capacity_per_subscription: usize,
) -> Result<Option<RequestMessage>, Error> {
let response_id = response.id.clone().into_owned();
let result = ResponseSuccess::try_from(response).map(|s| s.result).map_err(|e| Error::Call(CallError::Custom(e)));
let result = ResponseSuccess::try_from(response).map(|s| s.result).map_err(Error::Call);

match manager.request_status(&response_id) {
RequestStatus::PendingMethodCall => {
Expand Down
43 changes: 3 additions & 40 deletions core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@

use std::fmt;

use jsonrpsee_types::error::{
CallError, ErrorObject, ErrorObjectOwned, CALL_EXECUTION_FAILED_CODE, INVALID_PARAMS_CODE, UNKNOWN_ERROR_CODE,
};
use jsonrpsee_types::error::ErrorObjectOwned;

/// Convenience type for displaying errors.
#[derive(Clone, Debug, PartialEq, Eq)]
Expand All @@ -45,20 +43,12 @@ impl<T: fmt::Display> fmt::Display for Mismatch<T> {
}
}

// NOTE(niklasad1): this `From` impl is a bit opinionated to regard all generic errors as `CallError`.
// In practice this should be the most common use case for users of this library.
impl From<anyhow::Error> for Error {
fn from(err: anyhow::Error) -> Self {
Error::Call(CallError::Failed(err))
}
}

/// Error type.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Error that occurs when a call failed.
/// JSON-RPC error which can occur when a JSON-RPC call fails.
#[error("{0}")]
Call(#[from] CallError),
Call(#[from] ErrorObjectOwned),
/// Networking error or error on the low-level protocol layer.
#[error("Networking or low-level protocol error: {0}")]
Transport(#[source] anyhow::Error),
Expand Down Expand Up @@ -118,33 +108,6 @@ pub enum Error {
EmptyBatchRequest,
}

impl Error {
/// Create `Error::CallError` from a generic error.
/// Useful if you don't care about specific JSON-RPC error code and
/// just wants to return your custom error type.
pub fn to_call_error<E>(err: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Error::Call(CallError::from_std_error(err))
}
}

impl From<Error> for ErrorObjectOwned {
fn from(err: Error) -> Self {
match err {
Error::Call(CallError::Custom(err)) => err,
Error::Call(CallError::InvalidParams(e)) => {
ErrorObject::owned(INVALID_PARAMS_CODE, e.to_string(), None::<()>)
}
Error::Call(CallError::Failed(e)) => {
ErrorObject::owned(CALL_EXECUTION_FAILED_CODE, e.to_string(), None::<()>)
}
_ => ErrorObject::owned(UNKNOWN_ERROR_CODE, err.to_string(), None::<()>),
}
}
}

/// Generic transport error.
#[derive(Debug, thiserror::Error)]
pub enum GenericTransportError {
Expand Down
2 changes: 1 addition & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub use async_trait::async_trait;
pub use error::{Error, GenericTransportError, StringError};

/// JSON-RPC result.
pub type RpcResult<T> = std::result::Result<T, Error>;
pub type RpcResult<T> = std::result::Result<T, jsonrpsee_types::ErrorObjectOwned>;

/// Empty server `RpcParams` type to use while registering modules.
pub type EmptyServerParams = Vec<()>;
Expand Down
8 changes: 1 addition & 7 deletions core/src/server/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ use std::io;
use std::time::Duration;

use crate::tracing::tx_log_from_str;
use crate::Error;
use jsonrpsee_types::error::{ErrorCode, ErrorObject, OVERSIZED_RESPONSE_CODE, OVERSIZED_RESPONSE_MSG};
use jsonrpsee_types::{Id, InvalidRequest, Response, ResponsePayload};
use serde::Serialize;
use tokio::sync::mpsc::{self, OwnedPermit};
use serde_json::value::to_raw_value;
use tokio::sync::mpsc::{self, OwnedPermit};

use super::{DisconnectError, SendTimeoutError, SubscriptionMessage, TrySendError};

Expand Down Expand Up @@ -169,11 +168,6 @@ impl MethodSinkPermit {
self.send_raw(json)
}

/// Helper for sending the general purpose `Error` as a JSON-RPC errors to the client.
pub fn send_call_error(self, id: Id, err: Error) {
self.send_error(id, err.into())
}

/// Send a raw JSON-RPC message to the client, `MethodSink` does not check the validity
/// of the JSON being sent.
pub fn send_raw(self, json: String) {
Expand Down
9 changes: 4 additions & 5 deletions core/src/server/rpc_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use crate::server::subscription::{
};
use crate::traits::ToRpcParams;
use futures_util::{future::BoxFuture, FutureExt};
use jsonrpsee_types::error::{CallError, ErrorCode, ErrorObject};
use jsonrpsee_types::error::{ErrorCode, ErrorObject};
use jsonrpsee_types::{
Id, Params, Request, Response, ResponsePayload, ResponseSuccess, SubscriptionId as RpcSubscriptionId,
};
Expand Down Expand Up @@ -253,7 +253,7 @@ impl Methods {
tracing::trace!("[Methods::call] Method: {:?}, params: {:?}", method, params);
let (resp, _) = self.inner_call(req, 1, mock_subscription_permit()).await;
let rp = serde_json::from_str::<Response<T>>(&resp.result)?;
ResponseSuccess::try_from(rp).map(|s| s.result).map_err(|e| Error::Call(CallError::Custom(e)))
ResponseSuccess::try_from(rp).map(|s| s.result).map_err(Error::Call)
}

/// Make a request (JSON-RPC method call or subscription) by using raw JSON.
Expand Down Expand Up @@ -385,9 +385,8 @@ impl Methods {
let (resp, rx) = self.inner_call(req, buf_size, mock_subscription_permit()).await;

// TODO: hack around the lifetime on the `SubscriptionId` by deserialize first to serde_json::Value.
let as_success: ResponseSuccess<serde_json::Value> = serde_json::from_str::<Response<_>>(&resp.result)?
.try_into()
.map_err(|e| Error::Call(CallError::Custom(e)))?;
let as_success: ResponseSuccess<serde_json::Value> =
serde_json::from_str::<Response<_>>(&resp.result)?.try_into()?;

let sub_id = as_success.result.try_into().map_err(|_| Error::InvalidSubscriptionId)?;

Expand Down
3 changes: 1 addition & 2 deletions examples/examples/http_proxy_middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
//! like to query a certain `URI` path for statistics.

use hyper::{Body, Client, Request};
use jsonrpsee::core::RpcResult;
use std::net::SocketAddr;
use std::time::Duration;

Expand Down Expand Up @@ -95,7 +94,7 @@ async fn run_server() -> anyhow::Result<SocketAddr> {

let mut module = RpcModule::new(());
module.register_method("say_hello", |_, _| "lo").unwrap();
module.register_method("system_health", |_, _| RpcResult::Ok(serde_json::json!({ "health": true }))).unwrap();
module.register_method("system_health", |_, _| serde_json::json!({ "health": true })).unwrap();

let handle = server.start(module)?;

Expand Down
11 changes: 8 additions & 3 deletions examples/examples/proc_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@

use std::net::SocketAddr;

use jsonrpsee::core::{async_trait, client::Subscription, Error, SubscriptionResult};
use jsonrpsee::core::{async_trait, client::Subscription, SubscriptionResult};
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::server::{PendingSubscriptionSink, ServerBuilder, SubscriptionMessage};
use jsonrpsee::types::ErrorObjectOwned;
use jsonrpsee::ws_client::WsClientBuilder;

type ExampleHash = [u8; 32];
Expand All @@ -41,7 +42,11 @@ where
{
/// Async method call example.
#[method(name = "getKeys")]
async fn storage_keys(&self, storage_key: StorageKey, hash: Option<Hash>) -> Result<Vec<StorageKey>, Error>;
async fn storage_keys(
&self,
storage_key: StorageKey,
hash: Option<Hash>,
) -> Result<Vec<StorageKey>, ErrorObjectOwned>;

/// Subscription that takes a `StorageKey` as input and produces a `Vec<Hash>`.
#[subscription(name = "subscribeStorage" => "override", item = Vec<Hash>)]
Expand All @@ -56,7 +61,7 @@ impl RpcServer<ExampleHash, ExampleStorageKey> for RpcServerImpl {
&self,
storage_key: ExampleStorageKey,
_hash: Option<ExampleHash>,
) -> Result<Vec<ExampleStorageKey>, Error> {
) -> Result<Vec<ExampleStorageKey>, ErrorObjectOwned> {
Ok(vec![storage_key])
}

Expand Down
7 changes: 4 additions & 3 deletions examples/examples/proc_macro_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@

use std::net::SocketAddr;

use jsonrpsee::core::{async_trait, Error};
use jsonrpsee::core::async_trait;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::server::ServerBuilder;
use jsonrpsee::types::ErrorObjectOwned;
use jsonrpsee::ws_client::WsClientBuilder;

type ExampleHash = [u8; 32];
Expand All @@ -53,14 +54,14 @@ impl Config for ExampleHash {
#[rpc(server, client, namespace = "foo", client_bounds(T::Hash: jsonrpsee::core::DeserializeOwned), server_bounds(T::Hash: jsonrpsee::core::Serialize + Clone))]
pub trait Rpc<T: Config> {
#[method(name = "bar")]
fn method(&self) -> Result<T::Hash, Error>;
fn method(&self) -> Result<T::Hash, ErrorObjectOwned>;
}

pub struct RpcServerImpl;

#[async_trait]
impl RpcServer<ExampleHash> for RpcServerImpl {
fn method(&self) -> Result<<ExampleHash as Config>::Hash, Error> {
fn method(&self) -> Result<<ExampleHash as Config>::Hash, ErrorObjectOwned> {
Ok([0u8; 32])
}
}
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/ws_pubsub_with_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ use futures::{Stream, StreamExt};
use jsonrpsee::core::client::{Subscription, SubscriptionClientT};
use jsonrpsee::core::Serialize;
use jsonrpsee::server::{RpcModule, ServerBuilder, SubscriptionMessage, TrySendError};
use jsonrpsee::types::ErrorObjectOwned;
use jsonrpsee::ws_client::WsClientBuilder;
use jsonrpsee::{rpc_params, PendingSubscriptionSink};
use tokio::time::interval;
Expand Down Expand Up @@ -72,7 +71,7 @@ async fn run_server() -> anyhow::Result<SocketAddr> {
let idx = match params.one::<usize>() {
Ok(p) => p,
Err(e) => {
let _ = pending.reject(ErrorObjectOwned::from(e)).await;
let _ = pending.reject(e).await;
return Ok(());
}
};
Expand Down
7 changes: 6 additions & 1 deletion proc-macros/src/render_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ impl RpcDescription {
if args.len() != 1 {
return quote_spanned!(args.span() => compile_error!("RpcResult must have one argument"));
}
quote!(#ty)

// The type alias `RpcResult<T>` is modified to `Result<T, Error>`.
let ret_ty = args.last_mut().unwrap();
let err_ty = self.jrps_client_item(quote! { core::Error });

quote! { core::result::Result<#ret_ty, #err_ty> }
} else {
// Any other type name isn't allowed.
quote_spanned!(type_name.span() => compile_error!("The return type must be Result or RpcResult"))
Expand Down
4 changes: 2 additions & 2 deletions proc-macros/tests/ui/correct/custom_ret_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::net::SocketAddr;

use jsonrpsee::core::{async_trait, RpcResult, Serialize};
use jsonrpsee::core::{async_trait, Serialize};
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::server::{IntoResponse, ServerBuilder};
use jsonrpsee::types::ResponsePayload;
Expand Down Expand Up @@ -86,7 +86,7 @@ async fn main() {
let client = WsClientBuilder::default().build(&server_url).await.unwrap();

let get_error_object = |err| match err {
jsonrpsee::core::Error::Call(jsonrpsee::types::error::CallError::Custom(object)) => object,
jsonrpsee::core::Error::Call(object) => object,
_ => panic!("wrong error kind: {:?}", err),
};

Expand Down
6 changes: 3 additions & 3 deletions proc-macros/tests/ui/correct/only_client.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Example of using proc macro to generate working client.

use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use jsonrpsee::proc_macros::rpc;

#[rpc(client)]
pub trait Rpc {
#[method(name = "foo")]
async fn async_method(&self, param_a: u8, param_b: String) -> RpcResult<u16>;
async fn async_method(&self, param_a: u8, param_b: String) -> Result<u16, Error>;

#[method(name = "bar")]
fn sync_method(&self) -> RpcResult<u16>;
fn sync_method(&self) -> Result<u16, Error>;

#[subscription(name = "subscribe", item = String)]
async fn sub(&self) -> Result<(), Error>;
Expand Down
5 changes: 2 additions & 3 deletions proc-macros/tests/ui/incorrect/rpc/rpc_empty_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use jsonrpsee::core::Error;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};

pub trait Config {
type Hash: Send + Sync + 'static;
Expand All @@ -10,7 +9,7 @@ pub trait Config {
#[rpc(server, client, namespace = "foo", client_bounds(), server_bounds())]
pub trait EmptyBounds<Conf: Config> {
#[method(name = "bar")]
fn method(&self) -> Result<Conf::Hash, Error>;
fn method(&self) -> RpcResult<Conf::Hash>;
}

fn main() {}
Loading

0 comments on commit d6a9622

Please sign in to comment.