SlideShare a Scribd company logo
1 of 73
Download to read offline
1
Error Management
ZIO vs Future
Dublin Scala Meetup, May 11th
John A. De Goes   @jdegoes
Kai @kaidaxofficial
...with help of Pavel Shirshov @shirshovp
Agenda
A Tale of Two Effects
2
Next-Gen Debugging Conclusion
Managing Errors
3
A TALE OF
TWO EFFECTS
FUTURE
Parallel
Future enables parallel
computations and
non-blocking gathering.
Error
Future has a built-in error
channel for
Throwable-based errors.
Eager
Future is not referentially
transparent; refactoring
may change behavior.
4
FUTURE
Async
Future enables
non-blocking code that
efficiently uses threads.
5
Future ZIO Effect
go running
Procedural Functional
def program: Unit = {
println("What’s your name?")
val name = readLine()
println(s"Howdy. $name!")
return ()
}
val program = for {
_ <- putStrLn("What’s your name?")
name <- getStrLn
_ <- putStrLn(s"Howdy, $name")
} yield ()
7
Future ZIO
Performance > 100x slower > 100x faster
Cancellation & Timeouts 𐄂 ✔
Effect Combinators 𐄂 ✔
Resource Safety 𐄂 ✔
Fiber Concurrency 𐄂 ✔
Equational & Type Reasoning 𐄂 ✔
Testability 𐄂 ✔
Error Management & Debugging ? ?
8
ZIO[R, E, A]
Environment Type
Failure Type
Success Type
9
ZIO[R, E, A]
~
R => Either[E, A]
10
type Task [ +A] = ZIO[Any, Throwable, A]
type UIO [ +A] = ZIO[Any, Nothing, A]
type TaskR[+R,+A] = ZIO[ R, Throwable, A]
type IO [+E,+A] = ZIO[Any, E, A]
11
type Task [ +A] = ZIO[Any, Throwable, A]
type UIO [ +A] = ZIO[Any, Nothing, A]
type TaskR[+R,+A] = ZIO[ R, Throwable, A]
type IO [+E,+A] = ZIO[Any, E, A]
12
type Task [ +A] = ZIO[Any, Throwable, A]
type UIO [ +A] = ZIO[Any, Nothing, A]
type TaskR[+R,+A] = ZIO[ R, Throwable, A]
type IO [+E,+A] = ZIO[Any, E, A]
13
type Task [ +A] = ZIO[Any, Throwable, A]
type UIO [ +A] = ZIO[Any, Nothing, A]
type TaskR[+R,+A] = ZIO[ R, Throwable, A]
type IO [+E,+A] = ZIO[Any, E, A]
ZIO[R, E, A]
Synchronous Asynchronous Errors Resource
ZIO.succeed(…)
ZIO.effect(…)
ZIO.effectTotal(…)
effectBlocking(…)
ZIO.effectAsync(…)
ZIO.effectAsyncMaybe(…)
ZIO.effectAsyncInte…(…)
ZIO.fromFuture(…)
ZIO.fail(…)
ZIO.fromOption(…)
ZIO.fromEither(…)
ZIO.fromTry(…)
ZIO.bracket(…)
ZIO.reserve(…)
ZIO.ensuring(…)
fromAutoCloseable(…)
15
ERROR
MANAGEMENT
FUTURE
Fail Domain errors, business errors,
transient errors, expected errors...
Expected Errors
Not Reflected in Types
DieSystem errors, fatal errors,
unanticipated errors, defects...
Unexpected Errors
Reflected in Types
16
ERROR DUALITY
17
ERROR DUALITY
Not Reflected in TypesNot Reflected in Types
val failed: Future[Nothing] =
Future.failed(new Exception)
val died: Future[Nothing] =
Future(throw new Error)
FUTURE
18
ERROR DUALITY
Not Reflected in TypesReflected in Types
val failed: IO[String, Nothing] =
ZIO.fail(“Uh oh!”)
val died: IO[Nothing, Nothing] =
ZIO.dieMessage(“Uh oh!”)
19
ERROR COMPOSITION
e1
e2t
First Error
20
ERROR COMPOSITION
e1
e2t
Second Error
21
ERROR COMPOSITION
e1
e2tFinalizer Error
22
ERROR COMPOSITION
e1
e2t
?
23
ERROR COMPOSITION
e1
e2t
FUTURE
Thrown away!!!Reported on side channel!!!
24
ERROR COMPOSITION
e1
e2t
Cause[E]
25
ERROR COMPOSITION
e1
e2t
Cause[E]
Cause.Fail(e1)
26
ERROR COMPOSITION
e1
e2t
Cause[E]
Cause.Both(
Cause.Fail(e1),
Cause.Fail(e2))
27
ERROR COMPOSITION
e1
e2t
Cause[E]
Cause.Both(
Cause.Fail(e1),
Cause.Then(
Cause.Fail(e2),
Cause.Die(t))
zio.FiberFailure: Fiber failed.
╥
╠══╗
║ ║
║ ║
║ ║
║ ╠─ A checked error was not handled:
║ ║
Failed(DatabaseUnreachableError)
║ ║
║ ╠─ A finalizer threw an error:
║ ▼
Die(IndexOutOfBoundsException())
║
╠─ A checked error was not handled:
▼ Failed(UserIdNotFoundError) 28
ERROR COMPOSITION
e2
t
e1
Asynchronous
29
ERROR PROPAGATION
Synchronous
ConcurrentParallel
Resource
Asynchronous
30
ERROR PROPAGATION
Synchronous
ConcurrentParallel
Resource
FUTURE
Asynchronous
31
ERROR PROPAGATION
Synchronous
ConcurrentParallel
Resource
32
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect1.orElse(effect2) future1.fallback(future2)
ZIO#either
ZIO#run
FUTURE
33
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect.catchAll(f) future.recoverWith(pf)
ZIO#either
ZIO#run
FUTURE
34
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect.catchSome(pf) future.recoverWith(pf)
ZIO#either
ZIO#run
FUTURE
35
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect.fold(err, succ)
ZIO#either
ZIO#run
FUTURE
36
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect.foldM(err, succ)
ZIO#either
ZIO#run
FUTURE
37
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
effect.either
ZIO#either
ZIO#run
FUTURE
38
ERROR RECOVERY
Fallback Catching Folding Value
ZIO#orElse(…)
ZIO#orElseEither(…)
ZIO#catchAll(…)
ZIO#catchSome(…)
ZIO#fold(…, …)
ZIO#foldM(…, …)
ZIO#either
ZIO#run
effect.run
FUTURE
39
BEST
PRACTICES
40
1. DON’T TYPE UNEXPECTED ERRORS
ZIO.effect(httpClient.get(url)).refineOrDie {
case e : TemporarilyUnavailable => e
}.retry(RetryPolicy).orDie
: IO[TemporarilyUnavailable, Response]
41
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
sealed trait UserServiceError
extends Exception
case class InvalidUserId(id: ID)
extends UserServiceError
case class ExpiredAuth(id: ID)
extends UserServiceError
UserServiceError
InvalidUserId ExpiredAuth
42
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
userServiceError match {
case InvalidUserId(id) => ...
case ExpiredAuth(id) => ...
}
43
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
for {
service <- userAuth(token)
_ <- service.userProfile(userId)
body <- generateEmail(orderDetails)
receipt <- sendEmail(“Your Order Details”,
body, profile.email)
} yield receipt
ExpiredAuth
44
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
for {
service <- userAuth(token)
_ <- service.userProfile(userId)
body <- generateEmail(orderDetails)
receipt <- sendEmail(“Your Order Details”,
body, profile.email)
} yield receipt
InvalidUserId
45
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
for {
service <- userAuth(token)
_ <- service.userProfile(userId)
body <- generateEmail(orderDetails)
receipt <- sendEmail(“Your Order Details”,
body, profile.email)
} yield receipt
Nothing
46
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
for {
service <- userAuth(token)
_ <- service.userProfile(userId)
body <- generateEmail(orderDetails)
receipt <- sendEmail(“Your Order Details”,
body, profile.email)
} yield receipt
EmailDeliveryError
47
2. DO EXTEND EXCEPTION WITH SEALED TRAITS
for {
service <- userAuth(token)
_ <- service.userProfile(userId)
body <- generateEmail(orderDetails)
receipt <- sendEmail(“Your Order Details”,
body, profile.email)
} yield receipt
IO[Exception, Receipt]
48
3. DON’T REFLEXIVELY LOG ERRORS
uploadFile(“contacts.csv”).catchAll { error =>
// Log error and re-fail:
for {
_ <- logger.error(error)
_ <- ZIO.fail(error)
} yield ()
}
49
4. DO GET TO KNOW UIO
type UIO[+A] = ZIO[Any, Nothing, A]
Cannot fail!
lazy val processed: UIO[Unit] =
processUpload(upload).either.flatMap {
case Left (_) => processed.delay(1.minute)
case Right(_) => ZIO.succeed(())
}
50
4. DO GET TO KNOW UIO
Fails with UploadError
lazy val processed: UIO[Unit] =
processUpload(upload).either.flatMap {
case Left (_) => processed.delay(1.minute)
case Right(_) => ZIO.succeed(())
}
51
4. DO GET TO KNOW UIO
Fails with Nothing
52
4. DO GET TO KNOW UIO
lazy val processed: UIO[Unit] =
processUpload(upload).either.flatMap {
case Left (_) => processed.delay(1.minute)
case Right(_) => ZIO.succeed(())
}
Fails with Nothing
NEXT-GENERATION
DEBUGGING
54
def asyncDbCall(sql: SQL): Future[Result]
def selectHumans(): Future[Result] = ...asyncDbCall(...)...
def selectPets(): Future[Result] = ...asyncDbCall(...)...
FUTURE
55
def asyncDbCall(sql: SQL): Future[Result]
def selectHumans(): Future[Result] = ...asyncDbCall(...)...
def selectPets(): Future[Result] = ...asyncDbCall(...)...
FUTURE
Which function failed, selectHumans or selectPets?
PostgresException: Syntax error at or near 42
at example$.getConnection(example.scala:43)
at example$.$anonfun$asyncDbCall$1(example.scala:23)
at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658)
at scala.util.Success.$anonfun$map$1(Try.scala:255)
at scala.util.Success.map(Try.scala:213)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
56
Which function failed, selectHumans or selectPets?
FUTURE
def asyncDbCall(sql: SQL): Future[Result]
def selectHumans(): Future[Result] = ...asyncDbCall(...)...
def selectPets(): Future[Result] = ...asyncDbCall(...)...
Only the last operation is mentioned
PostgresException: Syntax error at or near 42
at example$.getConnection(example.scala:43)
at example$.$anonfun$asyncDbCall$1(example.scala:23)
at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658)
at scala.util.Success.$anonfun$map$1(Try.scala:255)
at scala.util.Success.map(Try.scala:213)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
57
Which function failed, selectHumans or selectPets?
FUTURE
Only the last operation is mentioned
There is NO way to know!!!
def asyncDbCall(sql: SQL): Future[Result]
def selectHumans(): Future[Result] = ...asyncDbCall(...)...
def selectPets(): Future[Result] = ...asyncDbCall(...)...
PostgresException: Syntax error at or near 42
at example$.getConnection(example.scala:43)
at example$.$anonfun$asyncDbCall$1(example.scala:23)
at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658)
at scala.util.Success.$anonfun$map$1(Try.scala:255)
at scala.util.Success.map(Try.scala:213)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
58
Asynchronous
def myQuery =
for {
_ <- UIO(println(“Querying!”))
res <- queryDatabase
} yield res
59
Failure!
def myQuery =
for {
_ <- UIO(println(“Querying!”))
res <- queryDatabase
} yield res
60
def myQuery =
for {
_ <- UIO(println(“Querying!”))
res <- queryDatabase
} yield res
Fiber:0 ZIO Execution trace:
at myQuery(example.scala:4)
at myQuery(example.scala:3)
Fiber:0 was supposed to continue to:
a future continuation at myQuery(example.scala:5)
Failure!
61
def myQuery =
UIO(println(“Querying!”))
.flatMap(_ =>
queryDatabase
.map(res => res))
Fiber:0 ZIO Execution trace:
at myQuery(example.scala:4)
at myQuery(example.scala:3)
Fiber:0 was supposed to continue to:
a future continuation at myQuery(example.scala:5)
62
def myQuery =
UIO(println(“Querying!”))
.flatMap(_ =>
queryDatabase
.map(res => res))
Fiber:0 ZIO Execution trace:
at myQuery(example.scala:4)
at myQuery(example.scala:3)
Fiber:0 was supposed to continue to:
a future continuation at myQuery(example.scala:5)
The Past
63
def myQuery =
UIO(println(“Querying!”))
.flatMap(_ =>
queryDatabase
.map(res => res))
Fiber:0 ZIO Execution trace:
at myQuery(example.scala:4)
at myQuery(example.scala:3)
Fiber:0 was supposed to continue to:
a future continuation at myQuery(example.scala:5)
The Past
The Future
64
def asyncDbCall(sql: SQL): Task[Result]
val selectHumans: Task[Result] = ...asyncDbCall(...)...
val selectPets: Task[Result] = ...asyncDbCall(...)...
65
def asyncDbCall(sql: SQL): Task[Result]
val selectHumans: Task[Result] = ...asyncDbCall(...)...
val selectPets: Task[Result] = ...asyncDbCall(...)...
Fiber:0 ZIO Execution trace:
at asyncDbCall(example.scala:22)
at selectHumans(example.scala:26)
Fiber:0 was supposed to continue to:
a future continuation at selectHumans(example.scala:27)
66
def asyncDbCall(sql: SQL): Task[Result]
val selectHumans: Task[Result] = ...asyncDbCall(...)...
val selectPets: Task[Result] = ...asyncDbCall(...)...
Fiber:0 ZIO Execution trace:
at asyncDbCall(example.scala:22)
at selectHumans(example.scala:26)
Fiber:0 was supposed to continue to:
a future continuation at selectHumans(example.scala:27)
Gotcha!
67
EXECUTION TRACES
def doWork(condition: Boolean) = {
if (condition) {
doSideWork()
}
doMainWork()
}
java.lang.Exception: Worker failed!
at example$.doMainWork(example.scala:54)
at example$.doWork(example.scala:50)
at example$$anon$1.run(example.scala:60)
No mention of doSideWork()
PROCEDURAL
68
EXECUTION TRACES
def doWork(condition: Boolean) =
for {
_ <- IO.when(condition)(doSideWork)
_ <- doMainWork
} yield ()
Fiber:0 ZIO Execution trace:
at example$.doMainWork(example.scala:27)
at example$.doWork(example.scala:23)
at example$.doSideWork(example.scala:26)
The conditional was true!
69
CONCURRENT TRACES
uploadUsers uploadPets
uploadTo(target)
error!
def uploadUsers(users: List[User]): Task[Unit] =
IO.foreachPar_(users.map(toJSON))(uploadTo(dest1))
def uploadPets(pets: List[Pet]): Task[Unit] =
IO.foreachPar_(pets.map(toJSON))(uploadTo(dest2))
def uploadTo(dest: URL)(json: JSON): Task[Unit] = ...
70
CONCURRENT TRACES
uploadUsers uploadPets
uploadTo(target)
error!
java.lang.Exception: Expired credentials
at example$.$anonfun$uploadTo$1(example.scala:28)
Fiber:1 ZIO Execution trace:
at example$.uploadTo(example.scala:28)
Fiber:1 was supposed to continue to: <empty trace>
Fiber:1 was spawned by:
╥
╠─ Fiber:0 ZIO Execution trace: <empty trace>
║
║ Fiber:0 was supposed to continue to:
║ example$.uploadUsers(example.scala:21)
71
TAGLESS FINAL TRACES
Gain insights into FP libraries
72
● Tracing is fast , impact is negligible for real apps
● > 50x faster than Future
● ...even on synthetic benchmarks!
● Impact can be limited by config
● Much lower than monad transformers [10x]
● Enabled by default, no Java agents, no ceremony
Disable if tracing is a hot spot
effect.untraced
MADE FOR
PRODUCTION
I
73
CONCLUSION
https://github.com/zio
https://gitter.im/zio/core
https://zio.dev
@jdegoes
@kaidaxofficial
@shirshovp

More Related Content

What's hot

Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOPDzmitry Naskou
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type ClassesJohn De Goes
 
java 8 new features
java 8 new features java 8 new features
java 8 new features Rohit Verma
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...Philip Schwarz
 
Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans Hitesh-Java
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentationVan Huong
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaVladimir Kostyukov
 
java.io - streams and files
java.io - streams and filesjava.io - streams and files
java.io - streams and filesMarcello Thiry
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersPiotr Paradziński
 
Towards Functional Programming through Hexagonal Architecture
Towards Functional Programming through Hexagonal ArchitectureTowards Functional Programming through Hexagonal Architecture
Towards Functional Programming through Hexagonal ArchitectureCodelyTV
 
Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8Knoldus Inc.
 
Production-ready GraphQL with Caliban
Production-ready GraphQL with CalibanProduction-ready GraphQL with Caliban
Production-ready GraphQL with CalibanPierre Ricadat
 

What's hot (20)

Zio in real world
Zio in real worldZio in real world
Zio in real world
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Java 8 Lambda Expressions
Java 8 Lambda ExpressionsJava 8 Lambda Expressions
Java 8 Lambda Expressions
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
 
Spring Batch 2.0
Spring Batch 2.0Spring Batch 2.0
Spring Batch 2.0
 
Java I/O
Java I/OJava I/O
Java I/O
 
java.io - streams and files
java.io - streams and filesjava.io - streams and files
java.io - streams and files
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
 
Introduction to spring boot
Introduction to spring bootIntroduction to spring boot
Introduction to spring boot
 
Towards Functional Programming through Hexagonal Architecture
Towards Functional Programming through Hexagonal ArchitectureTowards Functional Programming through Hexagonal Architecture
Towards Functional Programming through Hexagonal Architecture
 
Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
Production-ready GraphQL with Caliban
Production-ready GraphQL with CalibanProduction-ready GraphQL with Caliban
Production-ready GraphQL with Caliban
 

Similar to Error Management: Future vs ZIO

Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL AntipatternsKrishnakumar S
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven EngineeringMike Brittain
 
Oa Framework Tutorial
Oa Framework TutorialOa Framework Tutorial
Oa Framework Tutorialnolimit797
 
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...tdc-globalcode
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developersLuiz Messias
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and ToolsBob Paulin
 
Introduction to aop
Introduction to aopIntroduction to aop
Introduction to aopDror Helper
 
Highload JavaScript Framework without Inheritance
Highload JavaScript Framework without InheritanceHighload JavaScript Framework without Inheritance
Highload JavaScript Framework without InheritanceFDConf
 
Uma introdução ao framework Spring
Uma introdução ao framework SpringUma introdução ao framework Spring
Uma introdução ao framework Springelliando dias
 
invokedynamic for Mere Mortals [Code One 2019]
invokedynamic for Mere Mortals [Code One 2019]invokedynamic for Mere Mortals [Code One 2019]
invokedynamic for Mere Mortals [Code One 2019]David Buck
 
SAP strikes back Your SAP server now counter attacks.
SAP strikes back Your SAP server now counter attacks.SAP strikes back Your SAP server now counter attacks.
SAP strikes back Your SAP server now counter attacks.Dmitry Iudin
 
Clearvision - Importing with JIM and other tools
Clearvision - Importing with JIM and other toolsClearvision - Importing with JIM and other tools
Clearvision - Importing with JIM and other toolsLondon APE
 
Productive Debugging
Productive DebuggingProductive Debugging
Productive DebuggingiThink
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Ivan Čukić
 
10 wp7 local database
10 wp7   local database10 wp7   local database
10 wp7 local databaseTao Wang
 

Similar to Error Management: Future vs ZIO (20)

Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL Antipatterns
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven Engineering
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
Oa Framework Tutorial
Oa Framework TutorialOa Framework Tutorial
Oa Framework Tutorial
 
Getting Started With Testing
Getting Started With TestingGetting Started With Testing
Getting Started With Testing
 
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at ...
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
 
Input sanitization
Input sanitizationInput sanitization
Input sanitization
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 
Introduction to aop
Introduction to aopIntroduction to aop
Introduction to aop
 
Highload JavaScript Framework without Inheritance
Highload JavaScript Framework without InheritanceHighload JavaScript Framework without Inheritance
Highload JavaScript Framework without Inheritance
 
Uma introdução ao framework Spring
Uma introdução ao framework SpringUma introdução ao framework Spring
Uma introdução ao framework Spring
 
invokedynamic for Mere Mortals [Code One 2019]
invokedynamic for Mere Mortals [Code One 2019]invokedynamic for Mere Mortals [Code One 2019]
invokedynamic for Mere Mortals [Code One 2019]
 
SAP strikes back Your SAP server now counter attacks.
SAP strikes back Your SAP server now counter attacks.SAP strikes back Your SAP server now counter attacks.
SAP strikes back Your SAP server now counter attacks.
 
Clearvision - Importing with JIM and other tools
Clearvision - Importing with JIM and other toolsClearvision - Importing with JIM and other tools
Clearvision - Importing with JIM and other tools
 
Productive Debugging
Productive DebuggingProductive Debugging
Productive Debugging
 
Html5 bug
Html5 bugHtml5 bug
Html5 bug
 
Wt oep visiting card
Wt oep visiting cardWt oep visiting card
Wt oep visiting card
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
 
10 wp7 local database
10 wp7   local database10 wp7   local database
10 wp7 local database
 

More from John De Goes

One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }John De Goes
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final TaglessJohn De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingJohn De Goes
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New GameJohn De Goes
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional ArchitectureJohn De Goes
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemJohn De Goes
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsJohn De Goes
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn De Goes
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!John De Goes
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...John De Goes
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and FutureJohn De Goes
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!John De Goes
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScriptJohn De Goes
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsJohn De Goes
 

More from John De Goes (20)

One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect System
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScript
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
 

Recently uploaded

WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 

Recently uploaded (20)

Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 

Error Management: Future vs ZIO

  • 1. 1 Error Management ZIO vs Future Dublin Scala Meetup, May 11th John A. De Goes   @jdegoes Kai @kaidaxofficial ...with help of Pavel Shirshov @shirshovp
  • 2. Agenda A Tale of Two Effects 2 Next-Gen Debugging Conclusion Managing Errors
  • 3. 3 A TALE OF TWO EFFECTS FUTURE
  • 4. Parallel Future enables parallel computations and non-blocking gathering. Error Future has a built-in error channel for Throwable-based errors. Eager Future is not referentially transparent; refactoring may change behavior. 4 FUTURE Async Future enables non-blocking code that efficiently uses threads.
  • 6. Procedural Functional def program: Unit = { println("What’s your name?") val name = readLine() println(s"Howdy. $name!") return () } val program = for { _ <- putStrLn("What’s your name?") name <- getStrLn _ <- putStrLn(s"Howdy, $name") } yield ()
  • 7. 7 Future ZIO Performance > 100x slower > 100x faster Cancellation & Timeouts 𐄂 ✔ Effect Combinators 𐄂 ✔ Resource Safety 𐄂 ✔ Fiber Concurrency 𐄂 ✔ Equational & Type Reasoning 𐄂 ✔ Testability 𐄂 ✔ Error Management & Debugging ? ?
  • 8. 8 ZIO[R, E, A] Environment Type Failure Type Success Type
  • 9. 9 ZIO[R, E, A] ~ R => Either[E, A]
  • 10. 10 type Task [ +A] = ZIO[Any, Throwable, A] type UIO [ +A] = ZIO[Any, Nothing, A] type TaskR[+R,+A] = ZIO[ R, Throwable, A] type IO [+E,+A] = ZIO[Any, E, A]
  • 11. 11 type Task [ +A] = ZIO[Any, Throwable, A] type UIO [ +A] = ZIO[Any, Nothing, A] type TaskR[+R,+A] = ZIO[ R, Throwable, A] type IO [+E,+A] = ZIO[Any, E, A]
  • 12. 12 type Task [ +A] = ZIO[Any, Throwable, A] type UIO [ +A] = ZIO[Any, Nothing, A] type TaskR[+R,+A] = ZIO[ R, Throwable, A] type IO [+E,+A] = ZIO[Any, E, A]
  • 13. 13 type Task [ +A] = ZIO[Any, Throwable, A] type UIO [ +A] = ZIO[Any, Nothing, A] type TaskR[+R,+A] = ZIO[ R, Throwable, A] type IO [+E,+A] = ZIO[Any, E, A]
  • 14. ZIO[R, E, A] Synchronous Asynchronous Errors Resource ZIO.succeed(…) ZIO.effect(…) ZIO.effectTotal(…) effectBlocking(…) ZIO.effectAsync(…) ZIO.effectAsyncMaybe(…) ZIO.effectAsyncInte…(…) ZIO.fromFuture(…) ZIO.fail(…) ZIO.fromOption(…) ZIO.fromEither(…) ZIO.fromTry(…) ZIO.bracket(…) ZIO.reserve(…) ZIO.ensuring(…) fromAutoCloseable(…)
  • 16. Fail Domain errors, business errors, transient errors, expected errors... Expected Errors Not Reflected in Types DieSystem errors, fatal errors, unanticipated errors, defects... Unexpected Errors Reflected in Types 16 ERROR DUALITY
  • 17. 17 ERROR DUALITY Not Reflected in TypesNot Reflected in Types val failed: Future[Nothing] = Future.failed(new Exception) val died: Future[Nothing] = Future(throw new Error) FUTURE
  • 18. 18 ERROR DUALITY Not Reflected in TypesReflected in Types val failed: IO[String, Nothing] = ZIO.fail(“Uh oh!”) val died: IO[Nothing, Nothing] = ZIO.dieMessage(“Uh oh!”)
  • 28. zio.FiberFailure: Fiber failed. ╥ ╠══╗ ║ ║ ║ ║ ║ ║ ║ ╠─ A checked error was not handled: ║ ║ Failed(DatabaseUnreachableError) ║ ║ ║ ╠─ A finalizer threw an error: ║ ▼ Die(IndexOutOfBoundsException()) ║ ╠─ A checked error was not handled: ▼ Failed(UserIdNotFoundError) 28 ERROR COMPOSITION e2 t e1
  • 32. 32 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect1.orElse(effect2) future1.fallback(future2) ZIO#either ZIO#run FUTURE
  • 33. 33 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect.catchAll(f) future.recoverWith(pf) ZIO#either ZIO#run FUTURE
  • 34. 34 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect.catchSome(pf) future.recoverWith(pf) ZIO#either ZIO#run FUTURE
  • 35. 35 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect.fold(err, succ) ZIO#either ZIO#run FUTURE
  • 36. 36 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect.foldM(err, succ) ZIO#either ZIO#run FUTURE
  • 37. 37 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) effect.either ZIO#either ZIO#run FUTURE
  • 38. 38 ERROR RECOVERY Fallback Catching Folding Value ZIO#orElse(…) ZIO#orElseEither(…) ZIO#catchAll(…) ZIO#catchSome(…) ZIO#fold(…, …) ZIO#foldM(…, …) ZIO#either ZIO#run effect.run FUTURE
  • 40. 40 1. DON’T TYPE UNEXPECTED ERRORS ZIO.effect(httpClient.get(url)).refineOrDie { case e : TemporarilyUnavailable => e }.retry(RetryPolicy).orDie : IO[TemporarilyUnavailable, Response]
  • 41. 41 2. DO EXTEND EXCEPTION WITH SEALED TRAITS sealed trait UserServiceError extends Exception case class InvalidUserId(id: ID) extends UserServiceError case class ExpiredAuth(id: ID) extends UserServiceError UserServiceError InvalidUserId ExpiredAuth
  • 42. 42 2. DO EXTEND EXCEPTION WITH SEALED TRAITS userServiceError match { case InvalidUserId(id) => ... case ExpiredAuth(id) => ... }
  • 43. 43 2. DO EXTEND EXCEPTION WITH SEALED TRAITS for { service <- userAuth(token) _ <- service.userProfile(userId) body <- generateEmail(orderDetails) receipt <- sendEmail(“Your Order Details”, body, profile.email) } yield receipt ExpiredAuth
  • 44. 44 2. DO EXTEND EXCEPTION WITH SEALED TRAITS for { service <- userAuth(token) _ <- service.userProfile(userId) body <- generateEmail(orderDetails) receipt <- sendEmail(“Your Order Details”, body, profile.email) } yield receipt InvalidUserId
  • 45. 45 2. DO EXTEND EXCEPTION WITH SEALED TRAITS for { service <- userAuth(token) _ <- service.userProfile(userId) body <- generateEmail(orderDetails) receipt <- sendEmail(“Your Order Details”, body, profile.email) } yield receipt Nothing
  • 46. 46 2. DO EXTEND EXCEPTION WITH SEALED TRAITS for { service <- userAuth(token) _ <- service.userProfile(userId) body <- generateEmail(orderDetails) receipt <- sendEmail(“Your Order Details”, body, profile.email) } yield receipt EmailDeliveryError
  • 47. 47 2. DO EXTEND EXCEPTION WITH SEALED TRAITS for { service <- userAuth(token) _ <- service.userProfile(userId) body <- generateEmail(orderDetails) receipt <- sendEmail(“Your Order Details”, body, profile.email) } yield receipt IO[Exception, Receipt]
  • 48. 48 3. DON’T REFLEXIVELY LOG ERRORS uploadFile(“contacts.csv”).catchAll { error => // Log error and re-fail: for { _ <- logger.error(error) _ <- ZIO.fail(error) } yield () }
  • 49. 49 4. DO GET TO KNOW UIO type UIO[+A] = ZIO[Any, Nothing, A] Cannot fail!
  • 50. lazy val processed: UIO[Unit] = processUpload(upload).either.flatMap { case Left (_) => processed.delay(1.minute) case Right(_) => ZIO.succeed(()) } 50 4. DO GET TO KNOW UIO Fails with UploadError
  • 51. lazy val processed: UIO[Unit] = processUpload(upload).either.flatMap { case Left (_) => processed.delay(1.minute) case Right(_) => ZIO.succeed(()) } 51 4. DO GET TO KNOW UIO Fails with Nothing
  • 52. 52 4. DO GET TO KNOW UIO lazy val processed: UIO[Unit] = processUpload(upload).either.flatMap { case Left (_) => processed.delay(1.minute) case Right(_) => ZIO.succeed(()) } Fails with Nothing
  • 54. 54 def asyncDbCall(sql: SQL): Future[Result] def selectHumans(): Future[Result] = ...asyncDbCall(...)... def selectPets(): Future[Result] = ...asyncDbCall(...)... FUTURE
  • 55. 55 def asyncDbCall(sql: SQL): Future[Result] def selectHumans(): Future[Result] = ...asyncDbCall(...)... def selectPets(): Future[Result] = ...asyncDbCall(...)... FUTURE Which function failed, selectHumans or selectPets? PostgresException: Syntax error at or near 42 at example$.getConnection(example.scala:43) at example$.$anonfun$asyncDbCall$1(example.scala:23) at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658) at scala.util.Success.$anonfun$map$1(Try.scala:255) at scala.util.Success.map(Try.scala:213) at scala.concurrent.Future.$anonfun$map$1(Future.scala:292) at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33) at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
  • 56. 56 Which function failed, selectHumans or selectPets? FUTURE def asyncDbCall(sql: SQL): Future[Result] def selectHumans(): Future[Result] = ...asyncDbCall(...)... def selectPets(): Future[Result] = ...asyncDbCall(...)... Only the last operation is mentioned PostgresException: Syntax error at or near 42 at example$.getConnection(example.scala:43) at example$.$anonfun$asyncDbCall$1(example.scala:23) at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658) at scala.util.Success.$anonfun$map$1(Try.scala:255) at scala.util.Success.map(Try.scala:213) at scala.concurrent.Future.$anonfun$map$1(Future.scala:292) at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33) at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
  • 57. 57 Which function failed, selectHumans or selectPets? FUTURE Only the last operation is mentioned There is NO way to know!!! def asyncDbCall(sql: SQL): Future[Result] def selectHumans(): Future[Result] = ...asyncDbCall(...)... def selectPets(): Future[Result] = ...asyncDbCall(...)... PostgresException: Syntax error at or near 42 at example$.getConnection(example.scala:43) at example$.$anonfun$asyncDbCall$1(example.scala:23) at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:658) at scala.util.Success.$anonfun$map$1(Try.scala:255) at scala.util.Success.map(Try.scala:213) at scala.concurrent.Future.$anonfun$map$1(Future.scala:292) at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33) at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
  • 58. 58 Asynchronous def myQuery = for { _ <- UIO(println(“Querying!”)) res <- queryDatabase } yield res
  • 59. 59 Failure! def myQuery = for { _ <- UIO(println(“Querying!”)) res <- queryDatabase } yield res
  • 60. 60 def myQuery = for { _ <- UIO(println(“Querying!”)) res <- queryDatabase } yield res Fiber:0 ZIO Execution trace: at myQuery(example.scala:4) at myQuery(example.scala:3) Fiber:0 was supposed to continue to: a future continuation at myQuery(example.scala:5) Failure!
  • 61. 61 def myQuery = UIO(println(“Querying!”)) .flatMap(_ => queryDatabase .map(res => res)) Fiber:0 ZIO Execution trace: at myQuery(example.scala:4) at myQuery(example.scala:3) Fiber:0 was supposed to continue to: a future continuation at myQuery(example.scala:5)
  • 62. 62 def myQuery = UIO(println(“Querying!”)) .flatMap(_ => queryDatabase .map(res => res)) Fiber:0 ZIO Execution trace: at myQuery(example.scala:4) at myQuery(example.scala:3) Fiber:0 was supposed to continue to: a future continuation at myQuery(example.scala:5) The Past
  • 63. 63 def myQuery = UIO(println(“Querying!”)) .flatMap(_ => queryDatabase .map(res => res)) Fiber:0 ZIO Execution trace: at myQuery(example.scala:4) at myQuery(example.scala:3) Fiber:0 was supposed to continue to: a future continuation at myQuery(example.scala:5) The Past The Future
  • 64. 64 def asyncDbCall(sql: SQL): Task[Result] val selectHumans: Task[Result] = ...asyncDbCall(...)... val selectPets: Task[Result] = ...asyncDbCall(...)...
  • 65. 65 def asyncDbCall(sql: SQL): Task[Result] val selectHumans: Task[Result] = ...asyncDbCall(...)... val selectPets: Task[Result] = ...asyncDbCall(...)... Fiber:0 ZIO Execution trace: at asyncDbCall(example.scala:22) at selectHumans(example.scala:26) Fiber:0 was supposed to continue to: a future continuation at selectHumans(example.scala:27)
  • 66. 66 def asyncDbCall(sql: SQL): Task[Result] val selectHumans: Task[Result] = ...asyncDbCall(...)... val selectPets: Task[Result] = ...asyncDbCall(...)... Fiber:0 ZIO Execution trace: at asyncDbCall(example.scala:22) at selectHumans(example.scala:26) Fiber:0 was supposed to continue to: a future continuation at selectHumans(example.scala:27) Gotcha!
  • 67. 67 EXECUTION TRACES def doWork(condition: Boolean) = { if (condition) { doSideWork() } doMainWork() } java.lang.Exception: Worker failed! at example$.doMainWork(example.scala:54) at example$.doWork(example.scala:50) at example$$anon$1.run(example.scala:60) No mention of doSideWork() PROCEDURAL
  • 68. 68 EXECUTION TRACES def doWork(condition: Boolean) = for { _ <- IO.when(condition)(doSideWork) _ <- doMainWork } yield () Fiber:0 ZIO Execution trace: at example$.doMainWork(example.scala:27) at example$.doWork(example.scala:23) at example$.doSideWork(example.scala:26) The conditional was true!
  • 69. 69 CONCURRENT TRACES uploadUsers uploadPets uploadTo(target) error! def uploadUsers(users: List[User]): Task[Unit] = IO.foreachPar_(users.map(toJSON))(uploadTo(dest1)) def uploadPets(pets: List[Pet]): Task[Unit] = IO.foreachPar_(pets.map(toJSON))(uploadTo(dest2)) def uploadTo(dest: URL)(json: JSON): Task[Unit] = ...
  • 70. 70 CONCURRENT TRACES uploadUsers uploadPets uploadTo(target) error! java.lang.Exception: Expired credentials at example$.$anonfun$uploadTo$1(example.scala:28) Fiber:1 ZIO Execution trace: at example$.uploadTo(example.scala:28) Fiber:1 was supposed to continue to: <empty trace> Fiber:1 was spawned by: ╥ ╠─ Fiber:0 ZIO Execution trace: <empty trace> ║ ║ Fiber:0 was supposed to continue to: ║ example$.uploadUsers(example.scala:21)
  • 71. 71 TAGLESS FINAL TRACES Gain insights into FP libraries
  • 72. 72 ● Tracing is fast , impact is negligible for real apps ● > 50x faster than Future ● ...even on synthetic benchmarks! ● Impact can be limited by config ● Much lower than monad transformers [10x] ● Enabled by default, no Java agents, no ceremony Disable if tracing is a hot spot effect.untraced MADE FOR PRODUCTION