1. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka voló sobre el nido del Future
Javier Santos
David Vallejo
2. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
About us
David Vallejo @dvnavarro
« It’s not a bug – it’s an
undocumented feature.»
Anonymous
Javier Santos @jpaniego
«Hay dos formas de programar sin
errores; solo la tercera funciona»
Alan J Perlis
3. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Introduction: A functional world
● Purely functional: whole world could be implemented
in a single functional line
● Functional features
○ Robust
○ Debuggable
○ Predictable
○ Pluggable
4. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Introduction: A functional world
● Example
type Context = (Input,Output,Error)
type Action = Context => (Context,Event)
def main(
actions: Iterable[Action],
context: Context):(Context,Seq[Event]) = {
((context,Seq.empty[Event]) /: actions) {
case ((context,events),action) =>
action.apply(context) match {
case (context,event) => (context, events :+ event)
}
}
}
5. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
6. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Introduction: A functional world
● Problem? World actions are not precalculated.
What happens to I/O?
● World can be considered as
○ asynchronous: Things may happen at same time
○ reactive: Things may happen due to
■ actions: that trigger …
■ ...events: action consequences.
7. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Introduction: Runnable & Callable
● java.lang.Runnable
trait Runnable {
def run(): Unit
}
● java.util.concurrent.Callable
trait Callable[V] {
def call(): V
}
8. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Introduction: Threads
● Scala’s concurrency model is built on Java’s
● java.lang.Thread
val myThread = new Thread(new Runnable {
def run(){
println(“hi”)
}
}
myThread.start()
● Thread improvements (ExecutorService ~ Thread pool)
● Anyway, Threads abstraction level is too low
9. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
What about Scala and threads?
10. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Overview
● By default, non-blocking operations
● They will hold a T value at some point
● So a future may be uncompleted(it has no value yet) or
completed
● Completion will be treated as a scala.util.Try value
It will have two possible values:
○ Success(t: T)
○ Failure(t: Throwable)
11. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Overview
● Future example
import scala.concurrent._
import ExecutionContext.Implicits.global
val firstPrimeNumbers: Future[List[Int]] = Future {
List(1,2,3,5,7,11,13)
//what if 'calculateFirstPrimeNumbers(100000000)'…
}
res0: Future[List[Int]]
12. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Overview
● Failing Future example
import scala.concurrent._
import ExecutionContext.Implicits.global
val thisWillFail: Future[Int] = Future(2 / 0)
res0: Future[Int]
13. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: ExecutionContext
● A future, once it’s completed, it never changes of value
● An ExecutionContext
○ executes tasks submitted to them.
○ They can be seen as thread pools.
○ Most of future ops require an implicit
ExecutionContext.
14. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Expecting results
● Expecting results.
○ Blocker way (discouraged but sometimes
mandatory).
○ Non-blocker way: using callbacks
15. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Blocking - Await
● Blocking: Await.result / Await.ready
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future{
Thread.sleep(10000)
2
}
println(Await.result(f,12.seconds))
//2
16. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Blocking - Await
● Blocking: Await (Problem: Not enough time)
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future{
Thread.sleep(10000)
2
}
println(Await.result(f,5.seconds))
java.util.concurrent.TimeoutException: Futures timed out after
[5 seconds]
17. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Non-blocking - Callbacks
● Non-Blocking: callbacks
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future{
Thread.sleep(10000)
2
}
f.onComplete( n => println(n) )
//at some point, “Success(2)” will appear
Non-blocking
18. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Callbacks
● Callbacks will be executed asynchronously when future
is completed
● type Callback = Try[T] => Unit
● Try[T] ~ Either[Throwable,T]
○ Left(throwable) ~ Failure(throwable)
○ Right(t) ~ Success(t)
19. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Callbacks
● onComplete
f.onComplete( (t: Try[Int]) => println(t) )
//Success(2)
● onSuccess
f.onSuccess( n => println(n) )
//2
● onFailure
f.onFailure( throwable => println(throwable.getMessage) )
//it will never print an error (because it equals Success(2))
20. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Operations
● map
def getFirstMillionOfPrimes(): Future[List[Int]] = ???
getFirstMillionOfPrimes().map(
(list: List[Int]) => list.head)
res0: Future[Int]
22. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Monad behavior
● Composition
○ Future is like a monad
■ Point Function: Future.apply
■ Bind Function: flatMap
■ Some math properties and so...
○ Since Future has map,flatMap,filter methods;
it can be composed easily in a for-comprehension
23. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
24. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Composition
● Problem
var result: String = “”
val f1: Future[Unit] = Future{
result += “Hi ”
}
val f2: Future[Unit] = Future{
result += “ everyone”
}
● result value? “Hi everyone”? “ everyoneHi”?
25. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
26. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Composition
● for-comprehension is your friend
for {
primes <- getFirstMillionPrimes()
primesString <- concatenate(primes)
} yield primesString
res0: Future[String]
Future[List[Int]]
Future[String]
27. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Recovering from failure
● recover
val f: Future[Int] = Future{
1 / 0
}.recover{
case e: ArithmeticException => 0
}
28. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Recovering from failure
● recoverWith
val f: Future[Int] = Future{
1 / 0
}.recoverWith{
case e: ArithmeticException => Future(0)
}
29. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Recovering from failure
● fallbackTo
val f1: Future[Int] = Future{
1 / 0
}
val f2: Future[Int] = Future(0)
val f = f1 fallbackTo f2
30. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: Overview
● Futures can be created by
○ Future.apply
○ Promises
● You can think about it like
○ Future ~ Read future value
○ Promise ~ Write future value
● Promises are single-assigned (just once. Immutable as
futures)
31. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: Baggage & claim
Menu
order
Menu
Being
Cooked
Ticket
Menu ready
32. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: Baggage & claim
Begin
completion
Future[T]
p.success
or
p.failure
Try[T]
Promise[T]
33. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: example
val r: T = produceSomething()
p success r
doSomethingElse()
startDoingSomething()
f onSuccess {
case r: T => handleResult()
}
val p = promise[T]
val f = p.future
Producer Consumer
34. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: completion
● complete
val p = promise[Int]
p.complete(Try(2))
● completeWith
val p = promise[Int]
p.completeWith(Future(2))
35. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future alternatives
● Scalaz futures
● Scala’s async library
36. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Tones of slides and however...
Futures/Promises
Akka actors
37. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
38. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: main concepts
● Actors, actors everywhere
● Asynchronous messages
● Event-driven processes
● Distributed systems
39. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Actors
● Black box
● State without race condition
● Messages to update the state
40. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Actors
class MyFirstActor extends Actor {
override def receive = {
case _ => println("Hello World!")
}
}
41. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Send a message
● Tell message
actor ! "Hi"
● Ask message
actor ? "Are you there"
42. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Ask pattern
implicit val timeout = Timeout(5 seconds)
val f: Future[String] =
(actorRef ? AreYouThere).mapTo[String]
43. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: An example
44. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Services user
service
contact
service
address
service
System
GetUser(id)
GetContacts(name)
GetAddress(name)
Option[User]
List[Contact]
Address
UserInfo
45. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Ask Pattern & For
Comprehension
class UserServiceActor extends Actor {
val users: Map[String, User] =
Map("1" -> User("John"), "2" -> User("Jack"))
override def receive = {
case GetUser(userId: String) =>
sender ! users.get(userId)
}
}
46. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Ask Pattern & For
Comprehension
def getInfo(userId: String): Future[UserInfo] =
for {
Some(user) <- (usersActor ? GetUser(userId))
.mapTo[Option[User]]
contacts <- (contactsActor.?(GetContacts(user.name))
(Timeout(5 seconds),context.self))
.mapTo[List[Contact]]
address <- (addressesActor ? GetAddress(user.name))
.mapTo[Address]
} yield UserInfo(user, contacts, address)
47. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
48. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
scalera.es
@scalerablog
49. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
50. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Primeros pasos con Akka:
Olvídate de los threads
27 NOVEMBER
TRACK D
18:00
51. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Caminando de Java a Scala en
menos de 2 horas
28 NOVEMBER
TRACK B
9:30
52. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
53. MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka voló sobre el nido del Future
Javier Santos
David Vallejo