SlideShare ist ein Scribd-Unternehmen logo
1 von 83
Downloaden Sie, um offline zu lesen
@ELMANU 
BACK < 
& future: ACTORS 
AND > PIPES < 
using akka for large-scale data 
migration 
manuel BERNHART
@ELMANU 
AGENDA 
• { BACKGROUND STORY 
• } FUTURES > PIPES < ACTORS 
• | LESSONS LEARNED
@ELMANU 
who is speaking? 
• freelance software consultant 
based in Vienna 
• Vienna Scala User Group 
• web, web, web 
• writing a book on reactive 
web-applications
@ELMANU 
[ { 
BACKGROUND 
STORY
@ELMANU 
talenthouse 
• www.talenthouse.com 
• based in Los Angeles 
• connecting brands and artists 
• 3+ million users
@ELMANU 
BACKGROUND STORY 
• old, slow (very slow) platform 
• re-implementation from scratch with Scala & Play 
• tight schedule, a lot of data to migrate
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM 
DISCLAIMER: 
What follows is not intended as a 
bashing of the source system, but as a 
necessary explanation of its complexity in 
relation to data migration.
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
SOURCE SYSTEM
@ELMANU 
MIGRATION schedule 
•basically, one week-end 
•big-bang kind-of migration 
•if possible incremental migration beforehand
@ELMANU 
[ } 
FUTURES > PIPES 
< ACTORS
@ELMANU 
FUTURES
@ELMANU 
FUTURES 
•scala.concurrent.Future[T] 
•holds a value of type T 
•can either fail or succeed
@ELMANU 
FUTURES: HAPPY 
PATH 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
val futureSum: Future[Int] = Future { 1 + 1 } 
futureSum.map { sum => 
println("The sum is " + sum) 
}
@ELMANU 
FUTURES: SAD PATH 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
val futureDiv: Future[Int] = Future { 1 / 0 } 
val futurePrint: Future[Unit] = futureDiv.map { div => 
println("The division result is " + div) 
} 
Await.result(futurePrint, 1 second)
@ELMANU 
FUTURES: SAD PATH 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
val futureDiv: Future[Int] = Future { 1 / 0 } 
val futurePrint: Future[Unit] = futureDiv.map { div => 
println("The division result is " + div) 
} 
Await.result(futurePrint, 1 second) 
Avoid blocking if possible
@ELMANU 
FUTURES: SAD PATH 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
scala> 
Await.result(futureDiv, 
1.second) 
java.lang.ArithmeticException: 
/ 
by 
zero 
at 
$anonfun$1.apply$mcI$sp(<console>:11) 
at 
$anonfun$1.apply(<console>:11) 
at 
$anonfun$1.apply(<console>:11) 
at 
scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) 
at 
scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) 
at 
scala.concurrent.impl.ExecutionContextImpl 
$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121) 
at 
scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) 
at 
scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) 
at 
scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) 
at 
scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) 
val futureDiv: Future[Int] = Future { 1 / 0 } 
futureDiv.map { div => 
println("The division result is " + div) 
} 
Await.result(futureDiv, 1 second)
@ELMANU 
FUTURES: SAD PATH 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
val futureDiv: Future[Int] = Future { 1 / 0 } 
val futurePrint: Future[Unit] = futureDiv.map { div => 
println("The division result is " + div) 
}.recover { 
case a: java.lang.ArithmeticException => 
println("What on earth are you trying to do?") 
} 
Await.result(futurePrint, 1 second) Be mindful of failure
@ELMANU 
FUTURES: SAD PATH 
•Exceptions are propagated up the chain 
•Without recover there is no guarantee that 
failure will ever get noticed!
@ELMANU 
COMPOSING FUTURES 
val futureA: Future[Int] = Future { 1 + 1 } 
val futureB: Future[Int] = Future { 2 + 2 } 
val futureC: Future[Int] = for { 
a <- futureA 
b <- futureB 
} yield { 
a + b 
}
@ELMANU 
COMPOSING FUTURES 
val futureC: Future[Int] = for { 
a <- Future { 1 + 1 } 
b <- Future { 2 + 2 } 
} yield { 
a + b 
}
@ELMANU 
COMPOSING FUTURES 
val futureC: Future[Int] = for { 
a <- Future { 1 + 1 } 
b <- Future { 2 + 2 } 
} yield { 
a + b 
} 
This runs in sequence 
Don’t do this
@ELMANU 
FUTURES: CALLBACKS 
import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
val futureDiv: Future[Int] = Future { 1 / 0 } 
futureDiv.onSuccess { case result => 
println("Result: " + result) 
} 
futureDiv.onFailure { case t: Throwable => 
println("Oh no!") 
}
@ELMANU 
using FUTURES 
•a Future { … } block that doesn’t do any I/O 
is code smell 
•use them in combination with the “right” 
ExecutionContext set-up 
•when you have blocking operations, wrap 
them into a blocking block
@ELMANU 
using FUTURES 
import scala.concurrent.blocking 
Future { 
blocking { 
DB.withConnection { implicit connection => 
val query = SQL("select * from bar") 
query() 
} 
} 
}
@ELMANU 
naming FUTURES
@ELMANU 
naming FUTURES 
“Say 
eventuallyMaybe 
one more time!”
@ELMANU 
ACTORS
@ELMANU 
ACTORS 
•lightweight objects 
•send and receive messages (mailbox) 
•can have children (supervision)
@ELMANU 
ACTORS 
Mailbox Mailbox 
akka://application/user/georgePeppard akka://application/user/audreyHepburn 
Mailbox 
akka://application/user/audreyHepburn/cat
@ELMANU 
ACTORS 
Mailbox Mailbox 
Holly, I'm in love with you. 
akka://application/user/georgePeppard akka://application/user/audreyHepburn 
akka://application/user/audreyHepburn/cat
@ELMANU 
ACTORS 
Mailbox Mailbox 
Holly, I'm in love with you. 
So what? 
akka://application/user/georgePeppard akka://application/user/audreyHepburn 
akka://application/user/audreyHepburn/cat
@ELMANU 
GETTING AN ACTOR 
import akka.actor._ 
class AudreyHepburn extends Actor { 
def receive = { ... } 
} 
val system: ActorSystem = ActorSystem() 
val audrey: ActorRef = system.actorOf(Props[AudreyHepburn])
@ELMANU 
SENDING AND 
RECEIVING MESSAGES 
case class Script(text: String) 
class AudreyHepburn extends Actor { 
def receive = { 
case Script(text) => 
read(text) 
} 
}
@ELMANU 
SENDING AND 
RECEIVING MESSAGES 
case class Script(text: String) 
class AudreyHepburn extends Actor { 
def receive = { 
case Script(text) => 
read(text) 
} 
} 
audrey ! Script(breakfastAtTiffany)
@ELMANU 
SENDING AND 
RECEIVING MESSAGES 
case class Script(text: String) 
class AudreyHepburn extends Actor { 
def receive = { 
case Script(text) => 
read(text) 
} 
} 
audrey ! Script(breakfastAtTiffany) 
“tell” - fire-forget
@ELMANU 
ASK PATTERN 
import akka.pattern.ask 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
implicit val timeout = akka.util.Timeout(1 second) 
val maybeAnswer: Future[String] = 
audrey ? "Where should we have breakfast?"
@ELMANU 
ASK PATTERN 
import akka.pattern.ask 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
implicit val timeout = akka.util.Timeout(1 second) 
val maybeAnswer: Future[String] = 
audrey ? "Where should we have breakfast?" 
“ask”
@ELMANU 
SUPERVISION 
class UserMigrator extends Actor { 
lazy val workers: ActorRef = context 
.actorOf[UserMigrationWorker] 
.withRouter(RoundRobinRouter(nrOfInstances = 100)) 
}
@ELMANU 
SUPERVISION 
class UserMigrator extends Actor { 
actor context 
lazy val workers: ActorRef = context 
.actorOf[UserMigrationWorker] 
.withRouter(RoundRobinRouter(nrOfInstances = 100)) 
} 
router type many children
@ELMANU 
SUPERVISION
@ELMANU 
SUPERVISION 
class UserMigrator extends Actor { 
lazy val workers: ActorRef = context 
.actorOf[UserMigrationWorker] 
.withRouter(RoundRobinRouter(nrOfInstances = 100)) 
override def supervisorStrategy: SupervisorStrategy = 
OneForOneStrategy(maxNrOfRetries = 3) { 
case t: Throwable => 
log.error(“A child died!”, t) 
Restart 
} 
}
@ELMANU 
PIPES
@ELMANU 
CECI EST UNE PIPE 
•Akka pattern to combine Futures and Actors 
•Sends the result of a Future to an Actor 
•Be careful with error handling
@ELMANU 
CECI EST UNE PIPE 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender() 
val download: Future[DownloadedFile] = 
WS.url(url).get().map { response => 
DownloadedFile( 
url, 
response.ahcResponse.getResponseBodyAsBytes 
) 
} 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
}
@ELMANU 
CECI EST UNE PIPE 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender() 
val download: Future[DownloadedFile] = 
WS.url(url).get().map { response => 
DownloadedFile( 
url, 
response.ahcResponse.getResponseBodyAsBytes 
) 
} 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
} 
This is how you pipe
@ELMANU 
CECI EST UNE PIPE 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender() 
val download: Future[DownloadedFile] = 
WS.url(url).get().map { response => 
DownloadedFile( 
url, 
response.ahcResponse.getResponseBodyAsBytes 
) 
} 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
} 
Keep reference to original sender - what follows is a Future!
@ELMANU 
CECI EST UNE PIPE 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender() 
val download: Future[DownloadedFile] = 
WS.url(url).get().map { response => 
DownloadedFile( 
url, 
response.ahcResponse.getResponseBodyAsBytes 
) 
} 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
} 
Wrap your result into something you can easily match against
@ELMANU 
CECI EST UNE PIPE 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender 
val download: Future[Array[Byte]] = 
WS.url(url).get().map { response => 
DownloadedFile( 
url, 
response.ahcResponse.getResponseBodyAsBytes 
) 
} 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
} 
Will this work?
@ELMANU 
PIPES AND error 
handling 
class FileFetcher extends Actor { 
def receive = { 
case FetchFile(url) => 
val originalSender = sender() 
val download = 
WS.url(url).get().map { response => 
DownloadedFile(...) 
} recover { case t: Throwable => 
DownloadFileFailure(url, t) 
} 
Don’t forget to recover! 
import akka.pattern.pipe 
download pipeTo originalSender 
} 
}
@ELMANU 
SUMMARY 
•Futures: manipulate and combine 
asynchronous operation results 
•Actors: organise complex asynchronous flows, 
deal with failure via supervision 
•Pipes: deal with results of asynchronous 
computation inside of actors
@ELMANU 
[ | 
LESSONS LEARNED
@ELMANU 
design according to 
YOUR DATA 
User migrator 
Worker Worker Worker Worker Worker
@ELMANU 
design according to 
YOUR DATA 
Item migrator 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
design A
@ELMANU 
design according to 
YOUR DATA 
Item migrator 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
design A 
Not all users have the same amount of items
@ELMANU 
design according to 
YOUR DATA 
Item migrator 
Item 
migration 
worker 
User item 
migrator 
User item 
migrator 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
File 
fetcher 
File 
fetcher 
File 
uploader 
File 
uploader 
Soundcloud 
worker 
design B
@ELMANU 
design according to 
YOUR DATA 
Item 
migration 
worker 
User item 
migrator 
User item 
migrator 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
Item 
migration 
worker 
File 
fetcher 
File 
fetcher 
File 
uploader 
File 
uploader 
Soundcloud 
worker 
Pools of actors 
design B 
Item migrator 
User item 
migrator
@ELMANU 
KNOW THE limits OF 
THY SOURCE SYSTEM
@ELMANU 
KNOW THE limits OF 
THY SOURCE SYSTEM
@ELMANU 
DATA MIGRATION 
SHOULD not BE A RACE 
•Your goal is to get 
the data, not to be 
as fast as possible 
•Be gentle to the 
legacy system(s)
@ELMANU 
CLOUD API 
STANDARDS 
•ISO-28601 Data formats in REST APIs 
•ISO-28700 Response times and failure 
communication of REST APIs 
•ISO-28701 Rate limits in REST APIs and HTTP 
error codes
@ELMANU 
CLOUD API 
STANDARDS 
•ISO-28601 Data formats in REST APIs 
•ISO-28700 Response times and failure 
communication of REST APIs 
•ISO-28701 Rate limits in REST APIs and HTTP 
error codes DREAM ON
@ELMANU 
NO STANDARDS! 
•The cloud is heterogenous 
•Response times, rate limits, error codes all 
different 
•Don’t even try to treat all systems the same
@ELMANU 
RATE limits
@ELMANU 
RATE limits 
•Read the docs - most cloud API docs will 
warn you about them 
•Design your actor system so that you can 
queue if necessary 
•Keep track of migration status
@ELMANU 
RATE limits 
•Example: Soundcloud API 
•500 Internal Server Error after seemingly 
random amount of requests
@ELMANU 
RATE limits 
•Example: Soundcloud API 
•500 Internal Server Error after seemingly 
random amount of requests 
Magic User-Agent 
WS 
.url("http://api.soundcloud.com/resolve.json") 
.withHeaders("User-Agent" -> “FOOBAR”) // the magic ingredient that 
// opens the door to Soundcloud
@ELMANU 
BLOCKING
@ELMANU 
seriously, do not 
BLOCK 
•Seems innocent at first to block from time to 
time 
•OutOfMemory after 8 hours of migration run 
is not very funny 
•You will end up rewriting your whole code to 
be async anyway
@ELMANU 
MISC 
•Unstable primary IDs in source system 
•Build a lot of small tools, be pragmatic 
•sbt-tasks (http://yobriefca.se/sbt-tasks/)
@ELMANU 
THE END
@ELMANU 
THE END 
QUESTIONS?

Weitere ähnliche Inhalte

Was ist angesagt?

2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)Dominik Gruber
 
The dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupThe dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupkrivachy
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scalaStratio
 
Advanced akka features
Advanced akka featuresAdvanced akka features
Advanced akka featuresGrzegorz Duda
 
Introduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users GroupIntroduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users GroupRoy Russo
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayYardena Meymann
 
Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Johan Andrén
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Jiayun Zhou
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Clustermiciek
 
The internet of (lego) trains
The internet of (lego) trainsThe internet of (lego) trains
The internet of (lego) trainsGrzegorz Duda
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akkanartamonov
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesKonrad Malawski
 
Reactive streams processing using Akka Streams
Reactive streams processing using Akka StreamsReactive streams processing using Akka Streams
Reactive streams processing using Akka StreamsJohan Andrén
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentationGene Chang
 
Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akkaBardia Heydari
 
Scalamen and OT
Scalamen and OTScalamen and OT
Scalamen and OTgetch123
 
React Native One Day
React Native One DayReact Native One Day
React Native One DayTroy Miles
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 

Was ist angesagt? (20)

2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)2014-02-20 | Akka Concurrency (Vienna Scala User Group)
2014-02-20 | Akka Concurrency (Vienna Scala User Group)
 
The dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupThe dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetup
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scala
 
Advanced akka features
Advanced akka featuresAdvanced akka features
Advanced akka features
 
Actor Model Akka Framework
Actor Model Akka FrameworkActor Model Akka Framework
Actor Model Akka Framework
 
Introduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users GroupIntroduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users Group
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka way
 
Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Reactive stream processing using Akka streams
Reactive stream processing using Akka streams
 
Akka 2.0 Reloaded
Akka 2.0 ReloadedAkka 2.0 Reloaded
Akka 2.0 Reloaded
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
 
The internet of (lego) trains
The internet of (lego) trainsThe internet of (lego) trains
The internet of (lego) trains
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akka
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutes
 
Reactive streams processing using Akka Streams
Reactive streams processing using Akka StreamsReactive streams processing using Akka Streams
Reactive streams processing using Akka Streams
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
 
Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akka
 
Scalamen and OT
Scalamen and OTScalamen and OT
Scalamen and OT
 
React Native One Day
React Native One DayReact Native One Day
React Native One Day
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 

Ähnlich wie Back to the futures, actors and pipes: using Akka for large-scale data migration

Scala Future & Promises
Scala Future & PromisesScala Future & Promises
Scala Future & PromisesKnoldus Inc.
 
Anatomy of a Reactive Application
Anatomy of a Reactive ApplicationAnatomy of a Reactive Application
Anatomy of a Reactive ApplicationMark Wilson
 
Java concurrency model - The Future Task
Java concurrency model - The Future TaskJava concurrency model - The Future Task
Java concurrency model - The Future TaskSomenath Mukhopadhyay
 
Using Akka Futures
Using Akka FuturesUsing Akka Futures
Using Akka FuturesKnoldus Inc.
 
From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017Agustin Ramos
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & WebpackCodifly
 
cats.effect.IO - Scala Vienna Meetup February 2019
cats.effect.IO - Scala Vienna Meetup February 2019cats.effect.IO - Scala Vienna Meetup February 2019
cats.effect.IO - Scala Vienna Meetup February 2019Daniel Pfeiffer
 
Session 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdfSession 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdfEngmohammedAlzared
 
Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitVaclav Pech
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Queryitsarsalan
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Ahmed Moawad
 
The Atmosphere Framework
The Atmosphere FrameworkThe Atmosphere Framework
The Atmosphere Frameworkjfarcand
 
JavaScript Editions ES7, ES8 and ES9 vs V8
JavaScript Editions ES7, ES8 and ES9 vs V8JavaScript Editions ES7, ES8 and ES9 vs V8
JavaScript Editions ES7, ES8 and ES9 vs V8Rafael Casuso Romate
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesNaresha K
 

Ähnlich wie Back to the futures, actors and pipes: using Akka for large-scale data migration (20)

Scala Future & Promises
Scala Future & PromisesScala Future & Promises
Scala Future & Promises
 
Akka http 2
Akka http 2Akka http 2
Akka http 2
 
Anatomy of a Reactive Application
Anatomy of a Reactive ApplicationAnatomy of a Reactive Application
Anatomy of a Reactive Application
 
Java concurrency model - The Future Task
Java concurrency model - The Future TaskJava concurrency model - The Future Task
Java concurrency model - The Future Task
 
Using Akka Futures
Using Akka FuturesUsing Akka Futures
Using Akka Futures
 
From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017From Elixir to Akka (and back) - ElixirConf Mx 2017
From Elixir to Akka (and back) - ElixirConf Mx 2017
 
Akka knolx
Akka knolxAkka knolx
Akka knolx
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
 
cats.effect.IO - Scala Vienna Meetup February 2019
cats.effect.IO - Scala Vienna Meetup February 2019cats.effect.IO - Scala Vienna Meetup February 2019
cats.effect.IO - Scala Vienna Meetup February 2019
 
Session 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdfSession 9 Android Web Services - Part 2.pdf
Session 9 Android Web Services - Part 2.pdf
 
Pick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruitPick up the low-hanging concurrency fruit
Pick up the low-hanging concurrency fruit
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Query
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Basics of Akka
Basics of AkkaBasics of Akka
Basics of Akka
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2
 
The Atmosphere Framework
The Atmosphere FrameworkThe Atmosphere Framework
The Atmosphere Framework
 
JavaScript Editions ES7, ES8 and ES9 vs V8
JavaScript Editions ES7, ES8 and ES9 vs V8JavaScript Editions ES7, ES8 and ES9 vs V8
JavaScript Editions ES7, ES8 and ES9 vs V8
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good Practices
 

Mehr von Manuel Bernhardt

Is there anybody out there? Reactive Systems Hamburg
Is there anybody out there? Reactive Systems HamburgIs there anybody out there? Reactive Systems Hamburg
Is there anybody out there? Reactive Systems HamburgManuel Bernhardt
 
Is there anybody out there? Scala Days Berlin 2018
Is there anybody out there? Scala Days Berlin 2018Is there anybody out there? Scala Days Berlin 2018
Is there anybody out there? Scala Days Berlin 2018Manuel Bernhardt
 
Is there anybody out there?
Is there anybody out there?Is there anybody out there?
Is there anybody out there?Manuel Bernhardt
 
Is there anybody out there?
Is there anybody out there?Is there anybody out there?
Is there anybody out there?Manuel Bernhardt
 
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 20178 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017Manuel Bernhardt
 
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware of
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware ofScala Days Copenhagen - 8 Akka anti-patterns you'd better be aware of
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware ofManuel Bernhardt
 
8 Akka anti-patterns you'd better be aware of
8 Akka anti-patterns you'd better be aware of8 Akka anti-patterns you'd better be aware of
8 Akka anti-patterns you'd better be aware ofManuel Bernhardt
 
Beyond the buzzword: a reactive web-appliction in practice
Beyond the buzzword: a reactive web-appliction in practiceBeyond the buzzword: a reactive web-appliction in practice
Beyond the buzzword: a reactive web-appliction in practiceManuel Bernhardt
 
Beyond the Buzzword - a reactive application in practice
Beyond the Buzzword - a reactive application in practiceBeyond the Buzzword - a reactive application in practice
Beyond the Buzzword - a reactive application in practiceManuel Bernhardt
 
Six years of Scala and counting
Six years of Scala and countingSix years of Scala and counting
Six years of Scala and countingManuel Bernhardt
 
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVMVoxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVMManuel Bernhardt
 
Project Phoenix - From PHP to the Play Framework in 3 months
Project Phoenix - From PHP to the Play Framework in 3 monthsProject Phoenix - From PHP to the Play Framework in 3 months
Project Phoenix - From PHP to the Play Framework in 3 monthsManuel Bernhardt
 
Tips and tricks for setting up a Play 2 project
Tips and tricks for setting up a Play 2 projectTips and tricks for setting up a Play 2 project
Tips and tricks for setting up a Play 2 projectManuel Bernhardt
 

Mehr von Manuel Bernhardt (17)

Is there anybody out there? Reactive Systems Hamburg
Is there anybody out there? Reactive Systems HamburgIs there anybody out there? Reactive Systems Hamburg
Is there anybody out there? Reactive Systems Hamburg
 
Is there anybody out there? Scala Days Berlin 2018
Is there anybody out there? Scala Days Berlin 2018Is there anybody out there? Scala Days Berlin 2018
Is there anybody out there? Scala Days Berlin 2018
 
Is there anybody out there?
Is there anybody out there?Is there anybody out there?
Is there anybody out there?
 
Is there anybody out there?
Is there anybody out there?Is there anybody out there?
Is there anybody out there?
 
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 20178 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
 
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware of
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware ofScala Days Copenhagen - 8 Akka anti-patterns you'd better be aware of
Scala Days Copenhagen - 8 Akka anti-patterns you'd better be aware of
 
8 Akka anti-patterns you'd better be aware of
8 Akka anti-patterns you'd better be aware of8 Akka anti-patterns you'd better be aware of
8 Akka anti-patterns you'd better be aware of
 
Beyond the buzzword: a reactive web-appliction in practice
Beyond the buzzword: a reactive web-appliction in practiceBeyond the buzzword: a reactive web-appliction in practice
Beyond the buzzword: a reactive web-appliction in practice
 
Beyond the Buzzword - a reactive application in practice
Beyond the Buzzword - a reactive application in practiceBeyond the Buzzword - a reactive application in practice
Beyond the Buzzword - a reactive application in practice
 
Six years of Scala and counting
Six years of Scala and countingSix years of Scala and counting
Six years of Scala and counting
 
Writing a technical book
Writing a technical bookWriting a technical book
Writing a technical book
 
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVMVoxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
 
Project Phoenix - From PHP to the Play Framework in 3 months
Project Phoenix - From PHP to the Play Framework in 3 monthsProject Phoenix - From PHP to the Play Framework in 3 months
Project Phoenix - From PHP to the Play Framework in 3 months
 
Scala - Java2Days Sofia
Scala - Java2Days SofiaScala - Java2Days Sofia
Scala - Java2Days Sofia
 
Tips and tricks for setting up a Play 2 project
Tips and tricks for setting up a Play 2 projectTips and tricks for setting up a Play 2 project
Tips and tricks for setting up a Play 2 project
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Scala pitfalls
Scala pitfallsScala pitfalls
Scala pitfalls
 

Kürzlich hochgeladen

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...apidays
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 

Kürzlich hochgeladen (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

Back to the futures, actors and pipes: using Akka for large-scale data migration

  • 1. @ELMANU BACK < & future: ACTORS AND > PIPES < using akka for large-scale data migration manuel BERNHART
  • 2. @ELMANU AGENDA • { BACKGROUND STORY • } FUTURES > PIPES < ACTORS • | LESSONS LEARNED
  • 3. @ELMANU who is speaking? • freelance software consultant based in Vienna • Vienna Scala User Group • web, web, web • writing a book on reactive web-applications
  • 4. @ELMANU [ { BACKGROUND STORY
  • 5. @ELMANU talenthouse • www.talenthouse.com • based in Los Angeles • connecting brands and artists • 3+ million users
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. @ELMANU BACKGROUND STORY • old, slow (very slow) platform • re-implementation from scratch with Scala & Play • tight schedule, a lot of data to migrate
  • 12. @ELMANU SOURCE SYSTEM DISCLAIMER: What follows is not intended as a bashing of the source system, but as a necessary explanation of its complexity in relation to data migration.
  • 21. @ELMANU MIGRATION schedule •basically, one week-end •big-bang kind-of migration •if possible incremental migration beforehand
  • 22. @ELMANU [ } FUTURES > PIPES < ACTORS
  • 24. @ELMANU FUTURES •scala.concurrent.Future[T] •holds a value of type T •can either fail or succeed
  • 25. @ELMANU FUTURES: HAPPY PATH import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global val futureSum: Future[Int] = Future { 1 + 1 } futureSum.map { sum => println("The sum is " + sum) }
  • 26. @ELMANU FUTURES: SAD PATH import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ val futureDiv: Future[Int] = Future { 1 / 0 } val futurePrint: Future[Unit] = futureDiv.map { div => println("The division result is " + div) } Await.result(futurePrint, 1 second)
  • 27. @ELMANU FUTURES: SAD PATH import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ val futureDiv: Future[Int] = Future { 1 / 0 } val futurePrint: Future[Unit] = futureDiv.map { div => println("The division result is " + div) } Await.result(futurePrint, 1 second) Avoid blocking if possible
  • 28. @ELMANU FUTURES: SAD PATH import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ scala> Await.result(futureDiv, 1.second) java.lang.ArithmeticException: / by zero at $anonfun$1.apply$mcI$sp(<console>:11) at $anonfun$1.apply(<console>:11) at $anonfun$1.apply(<console>:11) at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) at scala.concurrent.impl.ExecutionContextImpl $AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) val futureDiv: Future[Int] = Future { 1 / 0 } futureDiv.map { div => println("The division result is " + div) } Await.result(futureDiv, 1 second)
  • 29. @ELMANU FUTURES: SAD PATH import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ val futureDiv: Future[Int] = Future { 1 / 0 } val futurePrint: Future[Unit] = futureDiv.map { div => println("The division result is " + div) }.recover { case a: java.lang.ArithmeticException => println("What on earth are you trying to do?") } Await.result(futurePrint, 1 second) Be mindful of failure
  • 30. @ELMANU FUTURES: SAD PATH •Exceptions are propagated up the chain •Without recover there is no guarantee that failure will ever get noticed!
  • 31. @ELMANU COMPOSING FUTURES val futureA: Future[Int] = Future { 1 + 1 } val futureB: Future[Int] = Future { 2 + 2 } val futureC: Future[Int] = for { a <- futureA b <- futureB } yield { a + b }
  • 32. @ELMANU COMPOSING FUTURES val futureC: Future[Int] = for { a <- Future { 1 + 1 } b <- Future { 2 + 2 } } yield { a + b }
  • 33. @ELMANU COMPOSING FUTURES val futureC: Future[Int] = for { a <- Future { 1 + 1 } b <- Future { 2 + 2 } } yield { a + b } This runs in sequence Don’t do this
  • 34. @ELMANU FUTURES: CALLBACKS import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global val futureDiv: Future[Int] = Future { 1 / 0 } futureDiv.onSuccess { case result => println("Result: " + result) } futureDiv.onFailure { case t: Throwable => println("Oh no!") }
  • 35. @ELMANU using FUTURES •a Future { … } block that doesn’t do any I/O is code smell •use them in combination with the “right” ExecutionContext set-up •when you have blocking operations, wrap them into a blocking block
  • 36. @ELMANU using FUTURES import scala.concurrent.blocking Future { blocking { DB.withConnection { implicit connection => val query = SQL("select * from bar") query() } } }
  • 38. @ELMANU naming FUTURES “Say eventuallyMaybe one more time!”
  • 40. @ELMANU ACTORS •lightweight objects •send and receive messages (mailbox) •can have children (supervision)
  • 41. @ELMANU ACTORS Mailbox Mailbox akka://application/user/georgePeppard akka://application/user/audreyHepburn Mailbox akka://application/user/audreyHepburn/cat
  • 42. @ELMANU ACTORS Mailbox Mailbox Holly, I'm in love with you. akka://application/user/georgePeppard akka://application/user/audreyHepburn akka://application/user/audreyHepburn/cat
  • 43. @ELMANU ACTORS Mailbox Mailbox Holly, I'm in love with you. So what? akka://application/user/georgePeppard akka://application/user/audreyHepburn akka://application/user/audreyHepburn/cat
  • 44. @ELMANU GETTING AN ACTOR import akka.actor._ class AudreyHepburn extends Actor { def receive = { ... } } val system: ActorSystem = ActorSystem() val audrey: ActorRef = system.actorOf(Props[AudreyHepburn])
  • 45. @ELMANU SENDING AND RECEIVING MESSAGES case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } }
  • 46. @ELMANU SENDING AND RECEIVING MESSAGES case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } } audrey ! Script(breakfastAtTiffany)
  • 47. @ELMANU SENDING AND RECEIVING MESSAGES case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } } audrey ! Script(breakfastAtTiffany) “tell” - fire-forget
  • 48. @ELMANU ASK PATTERN import akka.pattern.ask import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ implicit val timeout = akka.util.Timeout(1 second) val maybeAnswer: Future[String] = audrey ? "Where should we have breakfast?"
  • 49. @ELMANU ASK PATTERN import akka.pattern.ask import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ implicit val timeout = akka.util.Timeout(1 second) val maybeAnswer: Future[String] = audrey ? "Where should we have breakfast?" “ask”
  • 50. @ELMANU SUPERVISION class UserMigrator extends Actor { lazy val workers: ActorRef = context .actorOf[UserMigrationWorker] .withRouter(RoundRobinRouter(nrOfInstances = 100)) }
  • 51. @ELMANU SUPERVISION class UserMigrator extends Actor { actor context lazy val workers: ActorRef = context .actorOf[UserMigrationWorker] .withRouter(RoundRobinRouter(nrOfInstances = 100)) } router type many children
  • 53. @ELMANU SUPERVISION class UserMigrator extends Actor { lazy val workers: ActorRef = context .actorOf[UserMigrationWorker] .withRouter(RoundRobinRouter(nrOfInstances = 100)) override def supervisorStrategy: SupervisorStrategy = OneForOneStrategy(maxNrOfRetries = 3) { case t: Throwable => log.error(“A child died!”, t) Restart } }
  • 55. @ELMANU CECI EST UNE PIPE •Akka pattern to combine Futures and Actors •Sends the result of a Future to an Actor •Be careful with error handling
  • 56. @ELMANU CECI EST UNE PIPE class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender() val download: Future[DownloadedFile] = WS.url(url).get().map { response => DownloadedFile( url, response.ahcResponse.getResponseBodyAsBytes ) } import akka.pattern.pipe download pipeTo originalSender } }
  • 57. @ELMANU CECI EST UNE PIPE class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender() val download: Future[DownloadedFile] = WS.url(url).get().map { response => DownloadedFile( url, response.ahcResponse.getResponseBodyAsBytes ) } import akka.pattern.pipe download pipeTo originalSender } } This is how you pipe
  • 58. @ELMANU CECI EST UNE PIPE class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender() val download: Future[DownloadedFile] = WS.url(url).get().map { response => DownloadedFile( url, response.ahcResponse.getResponseBodyAsBytes ) } import akka.pattern.pipe download pipeTo originalSender } } Keep reference to original sender - what follows is a Future!
  • 59. @ELMANU CECI EST UNE PIPE class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender() val download: Future[DownloadedFile] = WS.url(url).get().map { response => DownloadedFile( url, response.ahcResponse.getResponseBodyAsBytes ) } import akka.pattern.pipe download pipeTo originalSender } } Wrap your result into something you can easily match against
  • 60. @ELMANU CECI EST UNE PIPE class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender val download: Future[Array[Byte]] = WS.url(url).get().map { response => DownloadedFile( url, response.ahcResponse.getResponseBodyAsBytes ) } import akka.pattern.pipe download pipeTo originalSender } } Will this work?
  • 61. @ELMANU PIPES AND error handling class FileFetcher extends Actor { def receive = { case FetchFile(url) => val originalSender = sender() val download = WS.url(url).get().map { response => DownloadedFile(...) } recover { case t: Throwable => DownloadFileFailure(url, t) } Don’t forget to recover! import akka.pattern.pipe download pipeTo originalSender } }
  • 62. @ELMANU SUMMARY •Futures: manipulate and combine asynchronous operation results •Actors: organise complex asynchronous flows, deal with failure via supervision •Pipes: deal with results of asynchronous computation inside of actors
  • 63. @ELMANU [ | LESSONS LEARNED
  • 64. @ELMANU design according to YOUR DATA User migrator Worker Worker Worker Worker Worker
  • 65. @ELMANU design according to YOUR DATA Item migrator User item migrator Item migration worker Item migration worker User item migrator Item migration worker Item migration worker User item migrator Item migration worker Item migration worker design A
  • 66. @ELMANU design according to YOUR DATA Item migrator User item migrator Item migration worker Item migration worker User item migrator Item migration worker Item migration worker User item migrator Item migration worker Item migration worker design A Not all users have the same amount of items
  • 67. @ELMANU design according to YOUR DATA Item migrator Item migration worker User item migrator User item migrator User item migrator Item migration worker Item migration worker Item migration worker Item migration worker Item migration worker File fetcher File fetcher File uploader File uploader Soundcloud worker design B
  • 68. @ELMANU design according to YOUR DATA Item migration worker User item migrator User item migrator Item migration worker Item migration worker Item migration worker Item migration worker Item migration worker File fetcher File fetcher File uploader File uploader Soundcloud worker Pools of actors design B Item migrator User item migrator
  • 69. @ELMANU KNOW THE limits OF THY SOURCE SYSTEM
  • 70. @ELMANU KNOW THE limits OF THY SOURCE SYSTEM
  • 71. @ELMANU DATA MIGRATION SHOULD not BE A RACE •Your goal is to get the data, not to be as fast as possible •Be gentle to the legacy system(s)
  • 72. @ELMANU CLOUD API STANDARDS •ISO-28601 Data formats in REST APIs •ISO-28700 Response times and failure communication of REST APIs •ISO-28701 Rate limits in REST APIs and HTTP error codes
  • 73. @ELMANU CLOUD API STANDARDS •ISO-28601 Data formats in REST APIs •ISO-28700 Response times and failure communication of REST APIs •ISO-28701 Rate limits in REST APIs and HTTP error codes DREAM ON
  • 74. @ELMANU NO STANDARDS! •The cloud is heterogenous •Response times, rate limits, error codes all different •Don’t even try to treat all systems the same
  • 76. @ELMANU RATE limits •Read the docs - most cloud API docs will warn you about them •Design your actor system so that you can queue if necessary •Keep track of migration status
  • 77. @ELMANU RATE limits •Example: Soundcloud API •500 Internal Server Error after seemingly random amount of requests
  • 78. @ELMANU RATE limits •Example: Soundcloud API •500 Internal Server Error after seemingly random amount of requests Magic User-Agent WS .url("http://api.soundcloud.com/resolve.json") .withHeaders("User-Agent" -> “FOOBAR”) // the magic ingredient that // opens the door to Soundcloud
  • 80. @ELMANU seriously, do not BLOCK •Seems innocent at first to block from time to time •OutOfMemory after 8 hours of migration run is not very funny •You will end up rewriting your whole code to be async anyway
  • 81. @ELMANU MISC •Unstable primary IDs in source system •Build a lot of small tools, be pragmatic •sbt-tasks (http://yobriefca.se/sbt-tasks/)
  • 83. @ELMANU THE END QUESTIONS?