Skip to content
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

Feature EitherFlow #141

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Feature EitherFlow #141

wants to merge 1 commit into from

Conversation

gabfssilva
Copy link

@gabfssilva gabfssilva commented Sep 28, 2018

Not sure if it's useful to other people, but, for sure it's a nice feature to choose two flows based on the element value (of an Either, of course).

@johanandren
Copy link
Member

You may find this issue over in akka/akka interesting: akka/akka#25578

It could also cover the either scenario, although without any type system guarantee that you cover all subtypes of an ADT

@gabfssilva
Copy link
Author

gabfssilva commented Oct 1, 2018

Indeed. But I guess it only applies if your scenario is based on polymorphism. It also relies on reflection, I don't know if I like the idea very much. =( haha
I also thought to use pattern matching to direct to the right flow, somehow like flatMapConcat, but without the need to return a new source, like:

val flow1: Flow[Payment, UniqueResult, NotUsed] = ???
val flow2: Flow[Exception, UniqueResult, NotUsed] = ???

queueSource
  .map(somethingThatReturnsATry)
  .viaMatching {
    case Success(_) => flow1
    case Failure(_) => flow2
  }
  .map { result: UniqueResult =>
    //yey =)
  }

@johanandren
Copy link
Member

Having that not materialize the flow each time would probably be very surprising, which is why partition looks how it looks with an identifier for the downstream to choose for a given input. The alternative, to materialize a new flow (the selected one) for every element, will be expensive.

I think that case is interesting though, and I think the builder idea could have an optional transformation as well to extract the inner value from different types.

@gabfssilva
Copy link
Author

I'm wondering, if I already have the downstream flows created, how expensive will it be to just redirect to the specific downstream flow based on each materialized value? For me, the expensive part would be to create a new source/flow for each materialized value (like flatMatConcat), but, it's not the case, right?
How expensive would it be and what do you mean by "surprising"?

@johanandren
Copy link
Member

You have to somehow upfront materialize the Flow (which you can only do by attaching both a source and a sink to it and create a RunnableGraph) so that you can backpressure if any of the downstreams are backpressuring (since you can't know the type of the next element coming downstream and if that can really be emitted downstream) and then you have to identify running downstream flows based on the blueprint they were created with.

Not sure what you mean with "for each materialized value", there's no materialized values at play here as far as I can see, just the elements in the stream and which stream they should be sent to.

@gabfssilva
Copy link
Author

Sorry, my bad. Not the materialized value, I meant the elements.

I think I get what you meant.

There's no way to generate the blueprint using something like viaMatching?

@johanandren
Copy link
Member

There's no way to generate the blueprint using something like viaMatching?

I haven't seen or figured one out a reasonable way to use a partial/total function to select and lay out the stream up front at the same time. Which is what led me down the builder path.

@hochgi
Copy link
Contributor

hochgi commented Mar 24, 2019

@gabfssilva Have you seen PartitionWith?

@ennru
Copy link
Member

ennru commented Dec 17, 2019

This behaviour could even be achieved with an alsoTo and two collectType operators.

@gabfssilva
Copy link
Author

@hochgi sorry for the delay and yeah, I did, I just wanted to achieve the same behavior without GraphDSL. :)

@ennru It works when you want to send to a sink or if you want to filter the elements out of the stream. The proposal here is to direct the element to the right flow based on the type and not filter any element out.

I guess the closest things that achieve the behavior I want is the @johanandren proposal, but, again, it relies on reflection and has no capabilities to do exhaustive pattern matching in order to avoid message loss.

I figured since Either is such a common ADT it'd make sense to use something like it to redirect the elements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants