Here is one piece of the problem:
while let Some(page) = object_stream.next().await {
match page {
// ListObjectsV2Output
Ok(p) => {
if let Some(contents) = p.contents {
all_objects.extend(contents);
}
}
// SdkError<ListObjectsV2Error, Response>
Err(err) => {
let raw_response = &err.raw_response();
let service_error = &err.as_service_error();
error!("ListObjectsV2Error: {:?} {:?}", &service_error, &raw_response);
return Err(S3Error::Error(format!("ListObjectsV2Error: {:?}", err)));
}
}
} while let Some(page) = object_stream.next().await {
match page {
// ListObjectsV2Output
Ok(p) => {
if let Some(contents) = p.contents {
all_objects.extend(contents);
}
}
// SdkError<ListObjectsV2Error, Response>
Err(err) => {
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {:?} {:?}", service_error, raw_response);
return Err(S3Error::Error(format!("ListObjectsV2Error: {:?}", err)));
}
}
}
I would have written it this way while let Some(page) = object_stream.next().await {
let p: ListObjectsV2Output = page.map_err(|err| {
// SdkError<ListObjectsV2Error, Response>
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {service_error:?} {raw_response:?}");
S3Error::Error(format!("ListObjectsV2Error: {err:?}"))
})?;
if let Some(contents) = p.contents {
all_objects.extend(contents);
}
}
although if your crate defines `S3Error`, then I would prefer to write while let Some(page) = object_stream.next().await {
if let Some(contents) = page?.contents {
all_objects.extend(contents);
}
}
by implementing `From`: impl From<SdkError<ListObjectsV2Error, Response>> for S3Error {
fn from(err: SdkError<ListObjectsV2Error, Response>) -> S3Error {
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {service_error:?} {raw_response:?}");
S3Error::Error(format!("ListObjectsV2Error: {err:?}"))
}
}My problem is that I should have something like
(http_status, reason) where http_status is a String or u16, reason is a enum with SomeError(String) structure. So essentially having a flat meaningful structure instead of this what we currently have. I do not have any mental model about the error structure of the AWS libs or don't even know where to start to create that mental model. As a result I just try to turn everything to a string and return it altogether hoping that the real issue is there somwhere in that structure.
I think the AWS library error handling is way to complex for what it does and one way we could improve that if Rust had a great example of a binary (bin) project that has lets say 2 layers of functions and showing how to organize your error effectively.
Now do this for a lib project. Without this you end up with this hot mess. At least this is how I see it. If you have a suggestion how should I return errors from a util.rs that has s3_list_objects() to my http handler than I would love to hear what you have to say.
Thanks for your suggestions anyway! I am going to re-implement my error handling and see if it gives us more clarity with impl.