Skip to content

Commit 4969624

Browse files
committed
Switched to HandlerError struct that can be created from any Display + Send + Sync + Debug. Updated samples to reflect this
1 parent fee02e8 commit 4969624

File tree

5 files changed

+50
-24
lines changed

5 files changed

+50
-24
lines changed

lambda-runtime-client/src/error.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
//! This module defines the `RuntimeApiError` trait that developers should implement
22
//! to send their custom errors to the AWS Lambda Runtime Client SDK. The module also
33
//! defines the `ApiError` type returned by the `RuntimeClient` implementations.
4-
use std::{env, error::Error, fmt, io, num::ParseIntError, option::Option};
4+
use std::{
5+
env,
6+
error::Error,
7+
fmt::{self, Display},
8+
io,
9+
num::ParseIntError,
10+
option::Option,
11+
};
512

613
use backtrace;
714
use http::{header::ToStrError, uri::InvalidUri};
@@ -98,9 +105,9 @@ impl ErrorResponse {
98105
}
99106
}
100107

101-
impl From<Box<dyn Error + Send + Sync>> for ErrorResponse {
102-
fn from(e: Box<dyn Error + Send + Sync>) -> Self {
103-
Self::handled(e.description().to_owned())
108+
impl<T: Display + Send + Sync> From<Box<T>> for ErrorResponse {
109+
fn from(e: Box<T>) -> Self {
110+
Self::handled(format!("{}", e))
104111
}
105112
}
106113

@@ -146,6 +153,8 @@ impl Error for ApiError {
146153
None
147154
}
148155
}
156+
unsafe impl Send for ApiError {}
157+
unsafe impl Sync for ApiError {}
149158

150159
impl From<serde_json::Error> for ApiError {
151160
fn from(e: serde_json::Error) -> Self {

lambda-runtime/examples/custom_error.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ impl CustomError {
2727
msg: message.to_owned(),
2828
}
2929
}
30-
31-
fn boxed(self) -> Box<CustomError> {
32-
Box::from(self)
33-
}
3430
}
3531

3632
#[derive(Deserialize)]
@@ -57,7 +53,7 @@ fn my_handler(e: CustomEvent, c: lambda::Context) -> Result<CustomOutput, Handle
5753
error!("Empty first name in request {}", c.aws_request_id);
5854
// in this case, we explicitly initialize and box our custom error type.
5955
// the HandlerError type is an alias to Box<dyn Error>/
60-
return Err(CustomError::new("Empty first name").boxed());
56+
return Err(CustomError::new("Empty first name").into());
6157
}
6258

6359
// For errors simply want to return, because the HandlerError is an alias to any

lambda-runtime/examples/custom_error_failure.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ extern crate simple_logger;
55
#[macro_use]
66
extern crate failure;
77

8-
use failure::Error;
98
use lambda::{lambda, HandlerError};
109
use log::error;
1110
use serde_derive::{Deserialize, Serialize};
@@ -37,7 +36,7 @@ fn main() -> Result<(), Box<dyn StdError>> {
3736
fn my_handler(e: CustomEvent, c: lambda::Context) -> Result<CustomOutput, HandlerError> {
3837
if e.first_name == "" {
3938
error!("Empty first name in request {}", c.aws_request_id);
40-
return Err(Box::from(Error::from(CustomError {}).compat()));
39+
return Err((CustomError {}).into());
4140
}
4241

4342
let _age_num: u8 = e.age.parse()?;

lambda-runtime/src/error.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
11
//! The error module defines the error types that can be returned
22
//! by custom handlers as well as the runtime itself.
3-
use std::{env, error::Error, fmt};
3+
use std::{
4+
env,
5+
error::Error,
6+
fmt::{self, Debug, Display},
7+
};
48

59
use lambda_runtime_client::error::ApiError;
610
use serde_json;
711

8-
/// The `HandlerError` type can be use to abstract any error in the handler method.
9-
/// This allows handler functions to return any error using the `?` syntax. For example
10-
/// `let _age_num: u8 = e.age.parse()?;` will return the `<F as FromStr>::Err` from the
11-
/// handler function.
12-
pub type HandlerError = Box<dyn Error + Send + Sync>;
12+
/// The `HandlerError` struct can be use to abstract any `Err` of the handler method `Result`.
13+
/// The `HandlerError` object can be generated `From` any object that supports `Display`,
14+
/// `Send, `Sync`, and `Debug`. This allows handler functions to return any error using
15+
/// the `?` syntax. For example `let _age_num: u8 = e.age.parse()?;` will return the
16+
/// `<F as FromStr>::Err` from the handler function.
17+
pub struct HandlerError {
18+
msg: String,
19+
}
20+
21+
impl<E: Display + Send + Sync + Debug> From<E> for HandlerError {
22+
fn from(e: E) -> HandlerError {
23+
HandlerError { msg: format!("{}", e) }
24+
}
25+
}
26+
27+
impl Display for HandlerError {
28+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29+
write!(f, "{}", self.msg)
30+
}
31+
}
1332

1433
/// The `RuntimeError` object is returned by the custom runtime as it polls
1534
/// for new events and tries to execute the handler function. The error

lambda-runtime/src/runtime.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ where
215215
"Error for {} is not recoverable, sending fail_init signal and panicking.",
216216
request_id
217217
);
218-
self.runtime_client.fail_init(ErrorResponse::from(Box::from(e)));
218+
self.runtime_client.fail_init(ErrorResponse::from(Box::new(e)));
219219
panic!("Could not send response");
220220
}
221221
}
@@ -226,15 +226,18 @@ where
226226
"Could not marshal output object to Vec<u8> JSON represnetation for request {}: {}",
227227
request_id, e
228228
);
229-
self.runtime_client.fail_init(ErrorResponse::from(Box::from(e)));
229+
self.runtime_client.fail_init(ErrorResponse::from(Box::new(e)));
230230
panic!("Failed to marshal handler output, panic");
231231
}
232232
}
233233
}
234234
Err(e) => {
235235
debug!("Handler returned an error for {}: {}", request_id, e);
236236
debug!("Attempting to send error response to Runtime API for {}", request_id);
237-
match self.runtime_client.event_error(&request_id, ErrorResponse::from(e)) {
237+
match self
238+
.runtime_client
239+
.event_error(&request_id, ErrorResponse::from(Box::new(e)))
240+
{
238241
Ok(_) => info!("Error response for {} accepted by Runtime API", request_id),
239242
Err(e) => {
240243
error!("Unable to send error response for {} to Runtime API: {}", request_id, e);
@@ -243,7 +246,7 @@ where
243246
"Error for {} is not recoverable, sending fail_init signal and panicking",
244247
request_id
245248
);
246-
self.runtime_client.fail_init(ErrorResponse::from(Box::from(e)));
249+
self.runtime_client.fail_init(ErrorResponse::from(Box::new(e)));
247250
panic!("Could not send error response");
248251
}
249252
}
@@ -271,11 +274,11 @@ where
271274
match err.request_id.clone() {
272275
Some(req_id) => {
273276
self.runtime_client
274-
.event_error(&req_id, ErrorResponse::from(Box::from(err)))
277+
.event_error(&req_id, ErrorResponse::from(Box::new(err)))
275278
.expect("Could not send event error response");
276279
}
277280
None => {
278-
self.runtime_client.fail_init(ErrorResponse::from(Box::from(err)));
281+
self.runtime_client.fail_init(ErrorResponse::from(Box::new(err)));
279282
}
280283
}
281284

@@ -355,7 +358,7 @@ pub(crate) mod tests {
355358
"Handler threw an unexpected error: {}",
356359
output.err().unwrap()
357360
);
358-
let output_string = output.unwrap();
361+
let output_string = output.ok().unwrap();
359362
assert_eq!(output_string, "hello", "Unexpected output message: {}", output_string);
360363
}
361364
}

0 commit comments

Comments
 (0)