Ill see your async and raise you reactive @sadache @guillaumebort - - PowerPoint PPT Presentation

i ll see your async and raise you reactive sadache
SMART_READER_LITE
LIVE PREVIEW

Ill see your async and raise you reactive @sadache @guillaumebort - - PowerPoint PPT Presentation

Ill see your async and raise you reactive @sadache @guillaumebort @zenexity What is Play? The Play framework makes it easier to build web applications with Java & Scala. Play is based on a lightweight, stateless, web- friendly


slide-1
SLIDE 1

I’ll see your async and raise you reactive

slide-2
SLIDE 2

@guillaumebort @sadache

slide-3
SLIDE 3

@zenexity

slide-4
SLIDE 4

What is Play?

  • The Play framework makes it easier to build

web applications with Java & Scala.

  • Play is based on a lightweight, stateless, web-

friendly architecture for highly-scalable applications

  • thanks to its reactive model, based on Iteratee

IO.

slide-5
SLIDE 5

The Web Evolved

slide-6
SLIDE 6

Flows of data everywhere

slide-7
SLIDE 7

Flows of data everywhere

  • Polling, Server Sent Events, Comet,

Websockets

  • Data upload
slide-8
SLIDE 8

And it changes everything

  • Handle continuous flows of data
  • Improve expressiveness for concurrent

code

  • Scale vertically and horizontally
slide-9
SLIDE 9

With Play1.x

  • We decided not to go WAR!
  • one request one thread doesn’t scale
  • Hint: a thread doesn’t need to be blocked

when doing IO

slide-10
SLIDE 10

Java.io.InputStream

public abstract int read() throws IOException Reads the next byte of data from the input stream. [...] This method blocks until input data is available,

slide-11
SLIDE 11

Limitations of Java’s current streams model

  • Resources consumption (memory, threads,

disk)

  • Pro-active waiting
slide-12
SLIDE 12

A reactive model

  • Inversion of control
  • The source controls the execution
  • Without loosing control
slide-13
SLIDE 13

Play2

  • Composable streams handling with

Iteratees

  • Reactive
  • Control
slide-14
SLIDE 14

An Iteratee

  • Is the Consumer
  • Represents a state of processing input, can be

either:

  • Done with a computed value and input left from

last chunk

  • Cont with a function which represents the way you

push more Input

  • Error with a message and the input which caused

that error

slide-15
SLIDE 15

An Iteratee

def fold[B]( //Done with a computed value and input left from last chunk done: (A, Input[E]) => Promise[B], //Cont with a function which represents the way you push more Input cont: (Input[E] => Iteratee[E, A]) => Promise[B], //Error with a message and the input which caused that error error: (String, Input[E]) => Promise[B] ): Promise[B]

slide-16
SLIDE 16

Input

  • Represents chunks of input that will be

passed into an iteratee, can be either of:

  • El(), EOF, Empty
slide-17
SLIDE 17

A Done Iteratee

val doneIteratee = new Iteratee[String,Int] { def fold[B]( done: (A, Input[E]) => Promise[B], cont: (Input[E] => Iteratee[E, A]) => Promise[B], error: (String, Input[E]) => Promise[B]): Promise[B] = done(1,Input.Empty) }

slide-18
SLIDE 18

An Iteratee

def fold[B]( done: (A, Input[E]) => Promise[B], cont: (Input[E] => Iteratee[E, A]) => Promise[B], error: (String, Input[E]) => Promise[B] ): Promise[B]

slide-19
SLIDE 19

Should I write all of that for creating a simple Iteratee?

  • Iteratee constructors for various Input

consuming scenarios

slide-20
SLIDE 20

foreach Iteratee

val printlnIteratee: Iteratee[String,Unit] = Iteratee.foreach[String](s => println(s))

slide-21
SLIDE 21

fold Iteratee

val inputLength: Iteratee[Array[Byte],A] = Iteratee.fold[Array[Byte],Int](0) { (length, bytes) => length + bytes.size }

slide-22
SLIDE 22

consume Iteratee

val consume = Iteratee.consume [String]()

slide-23
SLIDE 23

But how to push data into an Iteratee?

  • Enumerators are the input source

(producer)

  • Socket In, File, Events
slide-24
SLIDE 24

An Enumerator

trait Enumerator[E] { /** * Apply this Enumerator to an Iteratee */ def apply[A](i: Iteratee[E, A]): Promise[Iteratee[E, A]] }

slide-25
SLIDE 25

Fold again and again?

def fold[B]( done: (A, Input[E]) => Promise[B], cont: (Input[E] => Iteratee[E, A]) => Promise[B], error: (String, Input[E]) => Promise[B] ): Promise[B]

slide-26
SLIDE 26

Fold again and again?

  • Use Enumerator Constructors
slide-27
SLIDE 27

List Enumerator

val enumerateUsers: Enumerator[String] = { Enumerator("Guillaume", "Sadek", "Peter", "Erwan") } val consume = Iteratee.foreach[String](s => println(s)) enumerateUsers(printLn) //or enumerateUsers |>> printLn

slide-28
SLIDE 28

Callback Enumerator

Enumerator.fromCallback { () => Promise.timeout(Some(new Date), 100 milliseconds) }

slide-29
SLIDE 29

Callback Enumerator

def fromCallback[E]( retriever: () => Promise[Option[E]],

  • nComplete: () => Unit = () => (),
  • nError: (String, Input[E]) => Unit = (_:

String, _: Input[E]) => () ): Enumerator[E] = { ... }

slide-30
SLIDE 30

Callback Enumerator

val timeStream = Enumerator.fromCallback { () => Promise.timeout(Some(new Date), 100 milliseconds) } val printlnSink = Iteratee.foreach[Date](date => println(date)) timeStream |>> printlnSink

slide-31
SLIDE 31

Push Enumerator

val channel = Enumerator.pushee[String] { onStart = pushee => pushee.push("Hello") pushee.push("World") } channel |>> Iteratee.foreach(println)

slide-32
SLIDE 32

Enumerators à la carte

  • bject AvailableStreams {

val cpu: Enumerator[JsValue] = Enumerator.fromCallback( /* code here */ ) val memory: Enumerator[JsValue] = Enumerator.fromCallback( /* code here */ ) val threads: Enumerator[JsValue] = Enumerator.fromCallback( /* code here */ ) val heap: Enumerator[JsValue] = Enumerator.fromCallback( /* code here */ ) } val physicalMachine = AvailableStreams.cpu >- AvailableStreams.memory val jvm = AvailableStreams.threads >- AvailableStreams.heap def usersWidgetsComposition(prefs: Preferences) = { // do the composition dynamically }

slide-33
SLIDE 33

And adapters: Enumeratees!

val sum: Iteratee[Int,Int] = Iteratee.fold[Int,Int](0) { (s,e) => s + e } val strings: Enumerator[String] = Enumerator("1","2","3","4") //create am Enumeratee using the map method on Enumeratee val toInt: Enumeratee[String,Int] = Enumeratee.map[String]{ s => s.toInt } val adaptedIteratee: Iteratee[String,Int] = toInt.transform (sum) //this works! strings |>> adaptedIteratee //or strings &> toInt >>> sum

slide-34
SLIDE 34

Where to use Iteratees, Enumerators and Enumeratees?

slide-35
SLIDE 35

File Upload

trait Action[A] extends (Request[A] => Result) { def parser: BodyParser[A] } trait BodyParser[+T] extends (RequestHeader => Iteratee[Array[Byte],T] )

slide-36
SLIDE 36

Streaming

  • Streaming big files to the client
  • Http 1.1 Chunking and Comet
  • Websockets, Server Sent Events