codemotion 2015 - akka voló sobre el nido del future
TRANSCRIPT
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka voló sobre el nido del FutureJavier SantosDavid Vallejo
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
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
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)
}
}
}
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
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.
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
}
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
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
What about Scala and threads?
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 valueIt will have two possible values:○ Success(t: T)○ Failure(t: Throwable)
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]]
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]
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.
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Expecting results
● Expecting results.
○ Blocker way (discouraged but sometimes mandatory).
○ Non-blocker way: using callbacks
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
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]
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
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)
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))
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]
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future: Operations
● flatMap
def getFirstMillionOfPrimes(): Future[List[Int]] = ???
def concatenate(l: List[Int]): Future[String] = ???
getFirstMillionOfPrimes().flatMap( (list: List[Int]) => concatenate(list))
res0: Future[String]
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
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
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”?
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
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]
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}
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)}
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
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)
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: Baggage & claim
Menuorder
MenuBeing
Cooked
Ticket
Menu ready
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Promise: Baggage & claim
Begincompletion
Future[T]
p.successor
p.failure
Try[T]
Promise[T]
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
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))
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Future alternatives
● Scalaz futures
● Scala’s async library
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Tones of slides and however...
Futures/Promises
Akka actors
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: main concepts
● Actors, actors everywhere
● Asynchronous messages
● Event-driven processes
● Distributed systems
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Actors
● Black box
● State without race condition
● Messages to update the state
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Actors
class MyFirstActor extends Actor { override def receive = { case _ => println("Hello World!") }
}
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Send a message
● Tell message
actor ! "Hi"
● Ask message
actor ? "Are you there"
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]
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: An example
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka: Services userservice
contactservice
addressservice
System
GetUser(id)
GetContacts(name)
GetAddress(name)
Option[User]
List[Contact]
AddressUserInfo
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) } }
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)
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
scalera.es
@scalerablog
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Primeros pasos con Akka:Olvídate de los threads
27 NOVEMBERTRACK D
18:00
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Caminando de Java a Scala en menos de 2 horas
28 NOVEMBERTRACK B
9:30
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
MADRID · NOV 27-28 · 2015
Scala Programming @ Madrid
Akka voló sobre el nido del FutureJavier SantosDavid Vallejo