introduction to asynchronous scala

38
Asynchronous Scala April 2015, Javier Santos Promising futures...

Upload: stratio

Post on 18-Jul-2015

470 views

Category:

Software


4 download

TRANSCRIPT

Asynchronous Scala

April 2015, Javier Santos

Promising futures...

Foto emotiva

relacionada con lo que

vamos a contar

Javier Santos PaniegoScala Developer

[email protected]

CONTACT

INTRODUCTION

• Functional World

• Runnable/Callable

• Threads

1 2 3FUTURES

• Completion

• ExecutionContext

• Callbacks

• Future monad

• Composition

• Recovery

PROMISES

• Baggage & Claim

• Completion

INDEX

Introduction

Introduction

Asynchronous Scala: Promising futures

● Purely functional: whole world could be implemented in a single functional line

● Functional features○ Robust○ Debuggable○ Predictable○ Pluggable

Introduction

A functional world

Asynchronous Scala: Promising futures

● 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),actions) =>

action.apply(context) match {

case (context,event) => (context, events :+ event)

}

}

}

Introduction

A functional world

Asynchronous Scala: Promising futures

● 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.

Introduction

A functional world

Asynchronous Scala: Promising futures

● java.lang.Runnable

trait Runnable {

def run(): Unit

}

● java.util.concurrent.Callable

trait Callable[V] {

def call(): V

}

Introduction

Runnable & Callable

Asynchronous Scala: Promising futures

● Scala’s concurrency model is built on Java’s● java.lang.Thread

val myThread = new Thread(new Runnable {

def run(){

println(“hi”)

}

}

myThread.start()

Introduction

Threads

Asynchronous Scala: Promising futures

● Thread improvements○ ExecutorService (obtained from static Executors) allows using

thread policies (like threading pools)

val pool: ExecutorService = Executors.newFixedThreadPool(poolSize)

pool.execute(new Runnable{

def run(){

println(“I’m handling a request”)

}

})

○ Anyway, Threads abstraction level is too low

Introduction

Thread policies

Futures

Futures

Asynchronous Scala: Promising futures

● 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)

Futures

Overview

Asynchronous Scala: Promising futures

● Successfully completion 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(100000)'…

}

res0: Future[List[Int]]

Futures

Success on completion

Asynchronous Scala: Promising futures

● Failure completion example

import scala.concurrent._import ExecutionContext.Implicits.global

val thisWillFail: Future[Int] = Future(2 / 0)

res0: Future[Int]

Futures

Failure on completion

Asynchronous Scala: Promising futures

● 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.

Futures

ExecutionContext

Asynchronous Scala: Promising futures

● Expecting results.

○ Blocker way (discouraged but sometimes mandatory).

○ Non-blocker way: using callbacks

Futures

Expecting results

Asynchronous Scala: Promising futures

● 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

Futures

Blocking: Await

Asynchronous Scala: Promising futures

● 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]

Futures

Blocking: Await problem

Asynchronous Scala: Promising futures

● Non-Blocking: callbacks

import scala.concurrent._import scala.concurrent.duration._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

Futures

Non-blocking: Callbacks

Non-blocking

Asynchronous Scala: Promising futures

● Callbacks will be executed asynchronously when future is completed

● Try[T] => U

● Try[T] ~ Either[Throwable,T]○ Left(throwable) ~ Failure(throwable)○ Right(t) ~ Success(t)

Futures

Callbacks

Asynchronous Scala: Promising futures

● onCompletef.onComplete( (t: Try[Int]) => println(n) )//Success(2)

● onSuccessf.onSuccess( n => println(n) )//2

● onFailuref.onFailure( throwable => println(throwable.getMessage) )//it will never print an error (because it equals Success(2))

Futures

Callbacks

Asynchronous Scala: Promising futures

● Composition○ Future is a monad

■ Type Constructor: T => Future[T]■ Unit Function: Future.apply■ Bind Function: flatMap

○ Since Future has map,flatMap,filter methods; it can be composed easily in a for-comprehension

Futures

Monad behavior

Asynchronous Scala: Promising futures

Futures

Monad behavior

Asynchronous Scala: Promising futures

● map

def getFirstMillionOfPrimes(): Future[List[Int]] = ???

getFirstMillionOfPrimes().map( (list: List[Int]) => list.head)

res0: Future[Int]

Futures

Monad behavior

Asynchronous Scala: Promising futures

● flatMap

def getFirstMillionOfPrimes(): Future[List[Int]] = ???

def concatenate(l: List[Int]): Future[String] = ???

getFirstMillionOfPrimes().flatMap((list: List[Int]) => concatenate(list))

res0: Future[String]

Futures

Monad behavior

Asynchronous Scala: Promising futures

● Problem

var result: String = “”val f1: Future[Unit] = Future{result += “Hi ”}val f2: Future[Unit] = Future{result += “ everyone”}

● result value?

Futures

Composition

Asynchronous Scala: Promising futures

● for-comprehension is your friend

for { primes <- getFirstMillionPrimes() primesString <- concatenate(primes)} yield primes

res0: Future[String]

Futures

Composition

Future[List[Int]]

Future[String]

Asynchronous Scala: Promising futures

● recover

val f: Future[Int] = Future{ 1 / 0 }.recover{ case e: ArithmeticException => 0}

Futures

Recovering from failure

Asynchronous Scala: Promising futures

● recoverWith

val f: Future[Int] = Future{ 1 / 0 }.recoverWith{ case e: ArithmeticException => Future(0)}

Futures

Recovering from failure

Asynchronous Scala: Promising futures

● fallbackTo

val f1: Future[Int] = Future{ 1 / 0 }val f2: Future[Int] = Future(0)

val f = f1 fallbackTo f2

Futures

Recovering from failure

Promises

Promises

Asynchronous Scala: Promising futures

● 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)

Promises

Overview

Asynchronous Scala: Promising futures

Promises

Baggage & claim pattern

Menuorder

MenuBeing

Cooked

Ticket

MenuReady

Asynchronous Scala: Promising futures

Promises

Baggage & claim pattern

Promise[T]

Begincompletion

Future[T]

p.successor

p.failure

Try[T]

Asynchronous Scala: Promising futures

Promises

Example

val producer = future {

val r: T = produceSomething()

p success r

continueDoingSomethingUnrelated()

}

val consumer = future {

startDoingSomething()

f onSuccess {

case r: T => handleResult()

}

}

val p = promise[T]

val f = p.future

Asynchronous Scala: Promising futures

● complete

val p: Promise[Int]p.complete(Try(2))

● completeWith

val p: Promise[Int]p.completeWith(Future(2))

Promises

Overview

Asynchronous Scala: Promising futures

Finished...

...for today

Futures/Promises

Akka actors