diff --git a/Cargo.lock b/Cargo.lock index d78d1fa0..426fced1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -800,6 +800,7 @@ name = "cuprate-rpc-interface" version = "0.0.0" dependencies = [ "axum", + "cuprate-database", "cuprate-epee-encoding", "cuprate-helper", "cuprate-json-rpc", @@ -809,6 +810,7 @@ dependencies = [ "paste", "serde", "serde_json", + "thiserror", "tokio", "tower", "ureq", diff --git a/rpc/interface/Cargo.toml b/rpc/interface/Cargo.toml index 5f173177..56f3fd49 100644 --- a/rpc/interface/Cargo.toml +++ b/rpc/interface/Cargo.toml @@ -9,18 +9,20 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/rpc/cuprate-rpc-inte keywords = ["cuprate", "rpc", "interface"] [features] -default = ["dummy", "serde"] -dummy = [] +default = ["dummy", "serde"] +dummy = [] [dependencies] cuprate-epee-encoding = { path = "../../net/epee-encoding", default-features = false } cuprate-json-rpc = { path = "../json-rpc", default-features = false } cuprate-rpc-types = { path = "../types", features = ["serde", "epee"], default-features = false } cuprate-helper = { path = "../../helper", features = ["asynch"], default-features = false } +cuprate-database = { path = "../../storage/database" } axum = { version = "0.7.5", features = ["json"], default-features = false } serde = { workspace = true, optional = true } tower = { workspace = true } +thiserror = { workspace = true } paste = { workspace = true } futures = { workspace = true } diff --git a/rpc/interface/README.md b/rpc/interface/README.md index e8be2d0d..eb878643 100644 --- a/rpc/interface/README.md +++ b/rpc/interface/README.md @@ -33,7 +33,7 @@ This crate simply handles: - Defining handler function signatures - (De)serialization of requests/responses (JSON-RPC, binary, JSON) -The actual server details are all handled by the [`axum`] and [`tower`] ecosystem.a +The actual server details are all handled by the [`axum`] and [`tower`] ecosystem. The proper usage of this crate is to: 1. Implement a [`RpcHandler`] @@ -45,8 +45,8 @@ The proper usage of this crate is to: This is your [`tower::Service`] that converts `Request`s into `Response`s, i.e. the "inner handler". -Said concretely, `RpcHandler` is 3 `tower::Service`s where the associated types are -the 3 endpoint enums from [`cuprate_rpc_types`] and the error type from this crate: +Said concretely, `RpcHandler` is 3 `tower::Service`s where the request/response types are +the 3 endpoint enums from [`cuprate_rpc_types`] and the error type is from this crate: - [`JsonRpcRequest`](cuprate_rpc_types::json::JsonRpcRequest) & [`JsonRpcResponse`](cuprate_rpc_types::json::JsonRpcResponse) - [`BinRequest`](cuprate_rpc_types::bin::BinRequest) & [`BinResponse`](cuprate_rpc_types::bin::BinRequest) - [`OtherRequest`](cuprate_rpc_types::other::OtherRequest) & [`OtherResponse`](cuprate_rpc_types::other::OtherRequest) diff --git a/rpc/interface/src/rpc_error.rs b/rpc/interface/src/rpc_error.rs index 47563d65..59f371ab 100644 --- a/rpc/interface/src/rpc_error.rs +++ b/rpc/interface/src/rpc_error.rs @@ -2,8 +2,8 @@ //---------------------------------------------------------------------------------------------------- Import use axum::http::StatusCode; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; + +use cuprate_database::RuntimeError; //---------------------------------------------------------------------------------------------------- RpcError /// Possible errors during RPC operation. @@ -16,9 +16,16 @@ use serde::{Deserialize, Serialize}; /// /// TODO: This is empty as possible errors will be /// enumerated when the handler functions are created. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -pub enum RpcError {} +#[derive(Debug, thiserror::Error)] +pub enum RpcError { + /// A [`std::io::Error`] from the database. + #[error("database I/O error: {0}")] + DatabaseIo(#[from] std::io::Error), + + /// A (non-I/O related) database error. + #[error("database error: {0}")] + DatabaseError(RuntimeError), +} impl From for StatusCode { fn from(_: RpcError) -> Self { @@ -27,6 +34,18 @@ impl From for StatusCode { } } +impl From for RpcError { + fn from(error: RuntimeError) -> Self { + match error { + RuntimeError::Io(io) => Self::DatabaseIo(io), + RuntimeError::KeyExists + | RuntimeError::KeyNotFound + | RuntimeError::ResizeNeeded + | RuntimeError::TableNotFound => Self::DatabaseError(error), + } + } +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { diff --git a/rpc/interface/src/rpc_service.rs b/rpc/interface/src/rpc_service.rs index db848307..b85ac047 100644 --- a/rpc/interface/src/rpc_service.rs +++ b/rpc/interface/src/rpc_service.rs @@ -32,7 +32,7 @@ pub trait RpcService: Request, Response = Response, Error = RpcError, - Future: Future> + Send + Sync + 'static, + Future: Future> + Send + 'static, > { } @@ -46,7 +46,7 @@ impl RpcService for T where Request, Response = Response, Error = RpcError, - Future: Future> + Send + Sync + 'static, + Future: Future> + Send + 'static, > { }