Skip to content

Feature request: add support for transforming a tuple of futures into a single future #1421

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

Open
gissuebot opened this issue Oct 31, 2014 · 7 comments
Labels
P3 no SLO package=concurrent type=debeta Request to remove something from @Beta type=enhancement Make an existing feature better

Comments

@gissuebot
Copy link

Original issue created by kristofer.karlsson on 2013-05-22 at 03:01 PM


Sometimes it would be useful to combine the result of multiple futures into a single result, basically transforming a set of futures into a single future.

This is already supported to some extent through Futures.allAsList, but that only works if all futures are of the same type. I would want something similar, but that works on tuples instead of lists.

Something like this:
ListenableFuture<A> future1;
ListenableFuture<B> future1;
Function2<X, A, B> function = new Function2<X, A, B>(){
  @Override
  public X apply(A first, B second) {
    return merge(first, second);
  }
};
ListenableFuture<X> result = Futures.transform(future1, future2, function);

Attached is some sort of minimal implementation of this concept.

@gissuebot
Copy link
Author

Original comment posted by [email protected] on 2013-05-22 at 03:09 PM


Though we've stayed away from Function2 and friends (<https://code.google.com/p/guava-libraries/wiki/IdeaGraveyard#Functions/Predicates_for_n_%3E=_2_inputs>), we can find other ways of merging Futures:

final ListenableFuture<A> future1;
final ListenableFuture<B> future2;
Callable<X> function = new Callable<X>() {
  @Override
  public X call() {
    return merge(future1.get(), future2.get());
  }
};
ListenableFuture<X> result = Futures.combine(function, executor, future1, future2);

In fact, we have this method internally. It may yet make its way out.

@gissuebot
Copy link
Author

Original comment posted by kristofer.karlsson on 2013-05-22 at 03:19 PM


Thanks for quick response.
But if that's the route you're going for it, I could just wrap things as a list instead and do this:

final ListenableFuture<A> future1;
final ListenableFuture<B> future1;
Function<X, ?> function = new Function<X, ?>(){
  @Override
  public X apply(List<?> dummy) {
    return merge(future1.get(), future2.get());
  }
};
ListenableFuture<X> result = Futures.transform(Futures.allAsList(future1, future2), function);

so you wouldn't actually need to expose your combine.
The tuple version is cute, since it gives somewhat nicer type information, and you don't need to invoke outer objects.

You could also do this, but I'm not sure it's any prettier:
ListenableFuture<A> future1;
ListenableFuture<B> future1;
Function<X, ?> function = new Function<X, ?>(){
  @Override
  public X apply(List<?> result) {
    return merge((A) result.get(0), (B) result.get(0));
  }
};
ListenableFuture<X> result = Futures.transform(Futures.allAsList(future1, future2), function);

@gissuebot
Copy link
Author

Original comment posted by [email protected] on 2013-05-22 at 03:27 PM


Yep, allAsList+transform is pretty much how ours is implemented. (As it turns out, ours (a) uses successfulAsList so that you can choose to handle exceptions manually (or just let them propagate) and (b) uses the AsyncFunction version of transform() so that the Function can throw any kind of Exception (important in part because we make you call get() but also sometimes convenient for other reasons.)

Part of what keeps us from going to tuple route is that, if we're going to address complex graphs of Futures, we probably want to go even further than an added method or two. There's at least one popular system available internally at Google, so we're kind of spoiled.

@gissuebot
Copy link
Author

Original comment posted by pettermahlen on 2014-01-31 at 09:24 AM


We've created a framework that aims to simplify the problem of working with non-trivial asynchronous call graphs: https://github.com/spotify/trickle. It may be of interest until the day when the Google-internal system is made available to the public.

@cgdecker cgdecker removed the migrated label Nov 1, 2014
cpovirk added a commit that referenced this issue Dec 21, 2015
We may still develop these further by integrating allAsList/successfulAsList into them.

Related Guava request:
#1421
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=110712191
@cpovirk cpovirk added the type=debeta Request to remove something from @Beta label Mar 25, 2019
@cpovirk
Copy link
Member

cpovirk commented Mar 25, 2019

Let's call this the bug for de-@Beta-ing the FutureCombiner type.

@ronshapiro ronshapiro added the P3 no SLO label Aug 8, 2019
copybara-service bot pushed a commit that referenced this issue Apr 11, 2023
Fixes #3403 #1519 #1421 #3424

RELNOTES=`concurrent`: Remove `@Beta` from `Futures`.
PiperOrigin-RevId: 523457329
@kluever
Copy link
Member

kluever commented Apr 11, 2023

This is now fixed.

@kluever kluever closed this as completed Apr 11, 2023
@cpovirk
Copy link
Member

cpovirk commented Apr 11, 2023

While I did say...

Let's call this the bug for de-@Beta-ing the FutureCombiner type.

...I think I had written that under the assumption that we wouldn't be de-@Beta-ing it until we added the functionality described in the initial post here. So let's have this open to track such an enhancement, even though we remain unlikely to do it anytime soon :(

@cpovirk cpovirk reopened this Apr 11, 2023
copybara-service bot pushed a commit that referenced this issue Apr 11, 2023
Fixes #3403 #1519 #1421 #3424

RELNOTES=`concurrent`: Remove `@Beta` from `Futures`.
PiperOrigin-RevId: 523465435
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 no SLO package=concurrent type=debeta Request to remove something from @Beta type=enhancement Make an existing feature better
Projects
None yet
Development

No branches or pull requests

5 participants