Andrei Bechet
07/22/2021, 11:40 AMeither
with coroutines in Springboot and I am not sure I fully understand what’s happening.
Take for example this code:
suspend myServiceFunction() = either {
val r1 = someApiCall(...).bind()
// Either<Fail,Res1>
val r2 = someOtherApiCall(...).bind()
// Either<Fail,Res2>
combineOperation(r1, r2) // Either<Fail, Res2>
}
My question is the following: how can we best make someApiCall
and someOtherApiCall
run in parallel? Is the bind
for obtaining r2
is waiting for r1
to first get returned? Thanks 🙂Andrei Bechet
07/22/2021, 11:42 AMsomeApiCall
and someOtherApiCall
are using async rest clientssimon.vergauwen
07/22/2021, 11:52 AMIs theSo the answer to this question is yes. Sofor obtainingbind
is waiting forr2
to first get returned?r1
bind
unwraps Either.Right
, and if it find Either.Left
it jumps out of the either { }
block and returns the encountered Either.Left
value. This allows you write imperative style code, instead of flatMap
based code.
This snippet is equivalent to your code:
someApiCall(...).flatMap { r1 ->
someOtherApiCall(...).flatMap { r2 ->
combineOperation(r1, r2)
}
}
If combineOperation
is also returning Either
at least, and if so then your snippet is probably missing a bind()
on combineOperation(r1, r2)
.Andrei Bechet
07/22/2021, 11:55 AMsomeApiCall
and someOtherApiCall
in simultaneously and doing the bing
only after they’re done?simon.vergauwen
07/22/2021, 11:55 AMparZip
from Arrow Fx Coroutines, which allows for doing this:
suspend myServiceFunction() = either {
parZip(
{ someApiCall(...).bind() },
{ someOtherApiCall(...).bind() }
) { r1, r2 ->
combineOperation(r1, r2) .bind()
}
}
So here we simply call parZip
inside either
, which takes 3 functions suspend () -> A
and suspend () -> B
and another (A, B) -> C
.
This will run both functions in parallel, and then use the lambda to combine the results.
If an Either.Left
or exception is found then it’ll cancel both parallel operations.Andrei Bechet
07/22/2021, 11:57 AMEither
business and no exceptions 🙂 )
Now the fun starts getting springboot to play ball with this 😄simon.vergauwen
07/22/2021, 12:02 PMsimon.vergauwen
07/22/2021, 12:02 PMAndrei Bechet
07/22/2021, 12:03 PMRestController
and RestTemplates
) however there’s no limitation to change to WebFlux if it’s neededsimon.vergauwen
07/22/2021, 12:03 PMparZip
yourself too)
https://github.com/arrow-kt/arrow/blob/main/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZip.kt#L78Andrei Bechet
07/22/2021, 12:04 PMAndrei Bechet
07/22/2021, 12:04 PMNo thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
simon.vergauwen
07/22/2021, 12:04 PMDisposableBean
and CoroutineScope
.Andrei Bechet
07/22/2021, 12:05 PMsimon.vergauwen
07/22/2021, 12:07 PMsimon.vergauwen
07/22/2021, 12:07 PMCompletableFuture
, and then in your controller you can just do future { suspendFun() }
.
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/simon.vergauwen
07/22/2021, 12:08 PMAndrei Bechet
07/22/2021, 12:09 PMAndrei Bechet
07/22/2021, 12:10 PMsimon.vergauwen
07/22/2021, 12:13 PMAndrei Bechet
07/22/2021, 12:15 PMsimon.vergauwen
07/22/2021, 12:16 PMsuspend
APIs everywhere.Andrei Bechet
07/22/2021, 12:17 PMsimon.vergauwen
07/22/2021, 12:19 PMcoRouter
from Spring WebFlux
.
It has very similar API to Ktor’s routing { }
DSL, and support coroutines out-of-the-box 😉
https://docs.spring.io/spring-framework/docs/current/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/co-router.htmlAndrei Bechet
07/23/2021, 12:12 PMcoRouter
as that would be the next step_simon.vergauwen
07/23/2021, 12:14 PMAndrei Bechet
07/23/2021, 12:16 PMAndrei Bechet
07/23/2021, 12:19 PMEither
and also explaining it to all our new comers on the project.
Actually the discussion to move away from exceptions is a very interesting one.simon.vergauwen
07/23/2021, 12:26 PMsuspend
+ Either
, and Validated
/ Ior
which you can see as variants on Either
is the most common use-case.
Two other good ones are when you want to accumulate errors with Validated
to validate a form or something, and Ior
to collect both errors, and succeed values. For example for getting the results of n
jobs.
Arrow Fx Coroutines just adds some other cool stuff for concurrency on top of KotlinX Coroutines. CircuitBreaker, compose-able declarative Resource type, Schedule for repeating and retrying, and some sugar APIs for concurrent operations.
That gives you a nice tool belt for building backends or apps.
With Arrow going 1.0.0 , where going to be putting more time into docs etc so hopefully that’ll also help.Andrei Bechet
07/23/2021, 12:27 PMsimon.vergauwen
07/23/2021, 12:29 PMsimon.vergauwen
08/01/2021, 8:14 PMAndrei Bechet
08/04/2021, 8:26 AMsimon.vergauwen
08/04/2021, 11:32 AMAndrei Bechet
08/04/2021, 12:31 PMAndrei Bechet
08/04/2021, 12:31 PMsimon.vergauwen
08/04/2021, 2:26 PMsimon.vergauwen
08/04/2021, 2:27 PMsimon.vergauwen
08/04/2021, 2:28 PMsimon.vergauwen
08/04/2021, 2:28 PMAndrei Bechet
08/04/2021, 2:29 PMsimon.vergauwen
08/04/2021, 2:29 PMCircuitBreaker
, Schedule
, Resource
, some extensions on Flow
. Those things are more like “Misc background information for those interested”, so it was my least prio 😅simon.vergauwen
08/04/2021, 2:30 PMAndrei Bechet
08/04/2021, 2:30 PM