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 obtainingbindis waiting forr2to 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