Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Async and Concurrent Error Handling & Cancellation

Async and Concurrent Error Handling & Cancellation

All programs contain side effects. They load data from network, persist to a database, log to console, and display information on screen. In this talk, we will learn how side effects break determinism, and how that smashes our ability to reason about our programs.

Then, we will move onto how we can keep those effects under control using the powers of IO, and how to use the DSL ArrowFx provides to write any pure functional program with a simple syntax.

This presentation was given by Jorge Castillo as part of the 47 Degrees Academy. You can watch the talk in full here: https://www.youtube.com/watch?v=UkcEXUlycC8

47 Degrees Academy

June 11, 2020
Tweet

More Decks by 47 Degrees Academy

Other Decks in Programming

Transcript

  1. Validated
&
ValidatedNel Target
platform:
JVM Running
on
Arrow
v.
0.10.5 Running
on
Kotlin
v.
1.3.50 fun
validateTalk(talk:
Talk):
ValidatedNel<Error,
Talk>
= 



if
(talk.script.length
<
25)
{ 







Error.ScriptTooShort.invalidNel() 



}
else
if
(talk.script.contains("ugly
words"))
{ 







Error.ViolatesCodeOfConduct.invalidNel() 



}
else
if
(talk.duration
>
45)
{

    







Error.TalkTooLong.invalidNel() 



}
else
{ 







talk.validNel() 



} val
res1
=
validateTalk(Talk(45,
"Some
too
short
script",
"EventId1")) val
res2
=
validateTalk(Talk(45,
"This
is
a
long
enough
script
but
with
ugly
words",
"EventId2")) val
res3
=
validateTalk(Talk(60,
"This
is
a
long
enough
script",
"EventId3"))
  2. Why
not
IO<A>? Only
supports
Throwable
errors. No
strongly
typed
errors. sealed
class
Error
:
Throwable()
{ 

object
SpeakerNotFound
:
Error() 

object
InvalidSpeakerId
:
Error() 

object
InvalidEventId
:
Error() } IO
{
speakerService.loadSpeaker("SomeId")
} 

.handleError
{

    



when
(it
as
Error)
{
//
 
unsafe
casting 





SpeakerNotFound
->
TODO() 





InvalidSpeakerId
->
TODO() 





Error.InvalidEventId
->
TODO() 

} }
  3. parMapN Run
N
parallel
ops. Cancelling
parent
 
cancels
all
children. Child
failure
 
cancels
other
children. suspend
fun
main()
{
 



val
op1
=
suspend
{
loadSpeakers()
}
 



val
op2
=
suspend
{
loadRooms()
}
 



val
op3
=
suspend
{
loadVenues()
}


    
 



val
program
=
parMapN(op1,
op2,
op3)
{
(speakers,
rooms,
venues)
->

 







Event(speakers,
rooms,
venues)
 



}
 
 



program.cancel()
//
cancels
all
child
ops.
 }
  4. raceN Racing
computations
parallelly. Returns
the
winner,
cancels
losers. Cancelling
parent
 
cancels
all
children. Child
failure
 
cancels
other
children. suspend
fun
main()
{
 



val
op1
=
suspend
{
loadSpeakers()
}
 



val
op2
=
suspend
{
loadRooms()
}


    



val
op3
=
suspend
{
loadVenues()
}
 
 



val
res
=
raceN(op1,
op2,
op3)
 



res.fold(
 





ifA
=
{},
 





ifB
=
{},
 





ifC
=
{}
 



)
 }
  5. Error
handling? suspend
fun
getTalks()
{
 



val
ops
=
listOf(
 







suspend
{
service.loadTalks(eventId1)
},

 







suspend
{
service.loadTalks(eventId2)
},

 







suspend
{
service.loadTalks(eventId3)
})
 
 



ops.parSequence()
 }
 


    suspend
fun
main()
{
 



val
res
=
Either.catch
{
getTalks()
}
 



res.fold(
 







ifLeft
=
{
/*...*/
},
 







ifRight
=
{
/*...*/
}
 



)