Introduction to Asynchronous scala

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

Transcript of Introduction to Asynchronous scala

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