Are there any docs/examples of using functions wit...
# arrow
m
Are there any docs/examples of using functions with
Raise
error handling inside a
Flow
? I assume the pattern would typically be to wrap it all in an
Either
and produce a
Flow<Either<E, T>>
but i want to make sure a raised error/left is treated similarly to throwing an exception inside the flow producer. The docs page on parallelism mentions that using typed errors in flow is prone to leaking raise scope but im not seeing too much guidance on the typed errors docs about how to avoid this
a
Right now there's no special integration of
Raise
within
Flow
, so indeed I would recommend to wrap the values as
Either
. The main issue is that if you have a function of the form
Copy code
fun Raise<Error>.foo(): Flow<Int>
then the consumption of the
Flow
may be completely detached from the
Raise
, so when you call
raise
, there "nowhere to go"
m
Yea i wanted to avoid that as well since turning into a
Raise<Error>.getData():Data
into
getDataFlow(): Flow<Either<Error,Data>>
essentially shifts it closer to being a sort of
Ior
type flow but with the error being treated as a terminal value.
Are there any proposed designs/discussions for library integrations between
Raise
and flow? Ill probably end up implementing some stuff for my own use cases and I'd be happy to contribute those
a
I don't think so, but @simon.vergauwen may know more
m
I am also interested in this! 👍 Currently working with non-trivial
Flow
compositions with
Either
in the mix, and would have loved some pointers in the docs. If I have some time during my currently hectic work days, I'll try and put together an example of something I struggled with, to give you an idea of the kind of pointers that could be helpful when diving into this for the first time!
s
The most straight-forward is
Flow<Either<E, A>>
since it's quite clear what is going on, but sometimes it's not convenient for doing more complex stuff and Arrow doesn't offer functions out-of-the-box to make working with
Flow<Either<E, A>>
easier. That's where
context(FlowCollector, Raise<E>)
works quite well, but it's kind-of dangerous in the sense that it is only correct if you eventually do
flow { either { } }
. However with the
context
you can write some code much simpler than you can with
Flow<Either<E, A>>
since you can rely on the raise signal itself across coroutines that run within your flow. As I'm writing this I want to reiterate that you need to be careful with coroutines scopes and their cancellation but the same rules applies as regular CancellationException.
👍 1
m
Do you have an example of that pattern? From what i understand youre saying instead of having a function that returns
Flow<Either<E,A>>
you have a function with
context(FlowCollector<T>, Raise<E>
and returns unit, then do the
flow{either{ }}
at that functions call site?
s
Maybe we can add these examples to the website somewhere, but I think these are the two meaningful ways of using
Flow
&
Either
together. And only usage1 is really useful to be honest. Usage 2 might be easier to just work with
Either
directly and not bother with the DSL. I would try to separate my business logic from the "Flow combination logic" as much as possible anyway.