futures-rs icon indicating copy to clipboard operation
futures-rs copied to clipboard

Idea: try_join like macro returning a tuple in case of Err

Open yara-blue opened this issue 3 years ago • 0 comments

Usecase

It would be nice to be able to figure out which branch in the try_join statement ran into an error. For example I would like to wrap any error while transmitting updates in the code below.

    async fn update(&mut self, msg: traits::AppUpdate) -> Result<(), eyre::Report> {
        let send_local = self.local_tx.update(msg.clone());
        let send_remote = self.remote_tx.update(msg);
        try_join!(send_remote, send_local)?; // which one erred??
        Ok(())
    }

Solution

One way to address this is with a new macro, let's call it try_join2 for now, we can figure out a good name later. This would work similarly to try_join however instead of returning Result<T, E> is would return Result<T, (Option<E1>, Option<E2>)>. A user can then match on the Err variant to figure out which branch failed. As a bonus we get to join on futures returning different error types and still abort early when an error happens!

    async fn update(&mut self, msg: traits::AppUpdate) -> Result<(), eyre::Report> {
        let send_local = self.local_tx.update(msg.clone());
        let send_remote = self.remote_tx.update(msg);
        match try_join2!(send_remote, send_local) {
            Ok(_, _) => Ok(()),
            Err(Some(e), _) => Err(e).wrap_err("while updating remote"),
            Err(_, Some(e)) => Err(e).wrap_err("while updating local"),
        }
    }

Alternatives

Similar semantics can probably be achieved with select however that will lead to less readable code.

Let me know what you think of this idea, if you decide this fits in futures-rs I would love to implement it.

yara-blue avatar Sep 23 '22 16:09 yara-blue