Skip to content

Add NoSuchKeyError as possible errorcode #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {
#[cfg(feature = "genproto")]
fn generate_protos() {
download_file(
"https://raw.githubusercontent.com/lightningdevkit/vss-server/e1a88afd61f56d7e8e90a32036ca12389e36fe44/app/src/main/proto/vss.proto",
"https://raw.githubusercontent.com/lightningdevkit/vss-server/62e888e1bd3305d23b15da857edffaf527163048/app/src/main/proto/vss.proto",
"src/proto/vss.proto",
).unwrap();

Expand Down
15 changes: 15 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ use std::fmt::{Display, Formatter};
/// information regarding each error code and corresponding use-cases.
#[derive(Debug)]
pub enum VssError {
/// Please refer to [`ErrorCode::NoSuchKeyException`].
NoSuchKeyError(String),

/// Please refer to [`ErrorCode::InvalidRequestException`].
InvalidRequestError(String),

/// Please refer to [`ErrorCode::ConflictException`].
ConflictError(String),

/// Please refer to [`ErrorCode::InternalServerException`].
InternalServerError(String),

/// There is an unknown error, it could be a client-side bug, unrecognized error-code, network error
/// or something else.
InternalError(String),
}

Expand All @@ -33,6 +44,9 @@ impl VssError {
impl Display for VssError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
VssError::NoSuchKeyError(message) => {
write!(f, "Requested key does not exist: {}", message)
}
VssError::InvalidRequestError(message) => {
write!(f, "Request sent to VSS Storage was invalid: {}", message)
}
Expand All @@ -54,6 +68,7 @@ impl Error for VssError {}
impl From<ErrorResponse> for VssError {
fn from(error_response: ErrorResponse) -> Self {
match error_response.error_code() {
ErrorCode::NoSuchKeyException => VssError::NoSuchKeyError(error_response.message),
ErrorCode::InvalidRequestException => VssError::InvalidRequestError(error_response.message),
ErrorCode::ConflictException => VssError::ConflictError(error_response.message),
ErrorCode::InternalServerException => VssError::InternalServerError(error_response.message),
Expand Down
17 changes: 12 additions & 5 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ pub struct GetObjectRequest {
/// Authorization and billing can also be performed at the `store_id` level.
#[prost(string, tag = "1")]
pub store_id: ::prost::alloc::string::String,
/// `Key` for which the value is to be fetched.
/// The key of the value to be fetched.
///
/// If the specified `key` does not exist, returns `ErrorCode.NO_SUCH_KEY_EXCEPTION` in the
/// the `ErrorResponse`.
///
/// Consistency Guarantee:
/// Get(read) operations against a `key` are consistent reads and will reflect all previous writes,
Expand Down Expand Up @@ -287,17 +290,19 @@ pub struct KeyValue {
pub enum ErrorCode {
/// Default protobuf Enum value. Will not be used as `ErrorCode` by server.
Unknown = 0,
/// CONFLICT_EXCEPTION is used when the request contains mismatched version (either key or global)
/// Used when the request contains mismatched version (either key or global)
/// in `PutObjectRequest`. For more info refer `PutObjectRequest`.
ConflictException = 1,
/// INVALID_REQUEST_EXCEPTION is used in the following cases:
/// Used in the following cases:
/// - The request was missing a required argument.
/// - The specified argument was invalid, incomplete or in the wrong format.
/// - The request body of api cannot be deserialized into corresponding protobuf object.
InvalidRequestException = 2,
/// An internal server error occurred, client is probably at no fault and can safely retry this
/// error with exponential backoff.
/// Used when an internal server error occurred, client is probably at no fault and can safely retry
/// this error with exponential backoff.
InternalServerException = 3,
/// Used when the specified `key` in a `GetObjectRequest` does not exist.
NoSuchKeyException = 4,
}
impl ErrorCode {
/// String value of the enum field names used in the ProtoBuf definition.
Expand All @@ -310,6 +315,7 @@ impl ErrorCode {
ErrorCode::ConflictException => "CONFLICT_EXCEPTION",
ErrorCode::InvalidRequestException => "INVALID_REQUEST_EXCEPTION",
ErrorCode::InternalServerException => "INTERNAL_SERVER_EXCEPTION",
ErrorCode::NoSuchKeyException => "NO_SUCH_KEY_EXCEPTION",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
Expand All @@ -319,6 +325,7 @@ impl ErrorCode {
"CONFLICT_EXCEPTION" => Some(Self::ConflictException),
"INVALID_REQUEST_EXCEPTION" => Some(Self::InvalidRequestException),
"INTERNAL_SERVER_EXCEPTION" => Some(Self::InternalServerException),
"NO_SUCH_KEY_EXCEPTION" => Some(Self::NoSuchKeyException),
_ => None,
}
}
Expand Down
24 changes: 24 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,30 @@ mod tests {
mock_server.expect(1).assert();
}

#[tokio::test]
async fn test_no_such_key_err_handling() {
let base_url = mockito::server_url();
let vss_client = VssClient::new(&base_url);

// NoSuchKeyError
let error_response = ErrorResponse {
error_code: ErrorCode::NoSuchKeyException.into(),
message: "NoSuchKeyException".to_string(),
};
let mock_server = mockito::mock("POST", GET_OBJECT_ENDPOINT)
.with_status(409)
.with_body(&error_response.encode_to_vec())
.create();

let get_result = vss_client
.get_object(&GetObjectRequest { store_id: "store".to_string(), key: "non_existent_key".to_string() })
.await;
assert!(matches!(get_result.unwrap_err(), VssError::NoSuchKeyError { .. }));

// Verify 1 request hit the server
mock_server.expect(1).assert();
}

#[tokio::test]
async fn test_invalid_request_err_handling() {
let base_url = mockito::server_url();
Expand Down