I have a working Rust example using a (Cloud) API generated by OpenAPI Generator.
The API represents a hierarchy of resources (Apps->Services->Deployments) so the implementation of the functions is necessarily nested; the code needs to iterate over each App to get the App's Services and then iterate over the Services ...
I'm unable to merge API calls into a async fn's for, at least, 2 reasons:
- Joining futures
- Collecting errors
I was hoping to define 3 functions with a common return type; each function has different arguments:
async fn fetch_and_transform_apps() -> Result<Vec<Foo>, anyhow::Error> {...}
async fn fetch_and_transform_services() -> Result<Vec<Foo>, anyhow::Error> {...}
async fn fetch_and_transform_deployments() -> Result<Vec<Foo>, anyhow::Error> {...}
I cannot work out how to implement #1 & #2 above (#3 is working). Here's what I have:
async fn fetch_and_transform_services(...) -> Result<vec<Foo>, anyhow::Error> {
let list_services_reply = list_services(...).await?;
let services = list_services_reply
.services.ok_or_else(|| anyhow::anyhow!("No services found"))?;
let items_futures = services
.iter()
.map(|service| async move {
let items: Result<Vec<Foo>, Error> = fetch_and_transform_deployments(...).await;
items
});
let items = join_all(items_futures)
.await
// The type here is: Vec<Result<Vec<Foo>, anyhow::Error>>
.into_iter()
// The collect type results in the error
.collect::<Result<Vec<koyeb::Koyeb>, anyhow::Error>>();
items
}
The error:
a value of type
std::vec::Vec<Foo>cannot be built from an iterator over elements of typestd::vec::Vec<Foo>the traitFromIterator<std::vec::Vec<Foo>>is not implemented forstd::vec::Vec<Foo>, which is required byResult<std::vec::Vec<Foo>, anyhow::Error>: FromIterator<Result<std::vec::Vec<Foo>, anyhow::Error>>the traitFromIterator<Foo>is implemented forstd::vec::Vec<Foo>for that trait implementation, expectedFoo, foundstd::vec::Vec<Foo>required forResult<std::vec::Vec<Foo>, anyhow::Error>to implementFromIterator<Result<std::vec::Vec<Foo>, anyhow::Error>>
I don't think
collectis capable of this, but you can usetry_foldinstead.You would use this function here:
If the outer
Vechas many items (>1000), you may want to build theVecin between awaits, so that you don't block for an extended period of time.This also will cancel unfinished futures as soon as one fails instead of running every one to completion, but you could finish consuming
items_futuresinstead of returning withnext_vec?if you need to complete them all.