Skip to content

Instantly share code, notes, and snippets.

@mpkocher
Created April 14, 2015 22:26
Show Gist options
  • Save mpkocher/9cc70e58e5defd69dc80 to your computer and use it in GitHub Desktop.
Save mpkocher/9cc70e58e5defd69dc80 to your computer and use it in GitHub Desktop.
Scala Futures Example
package com.github.mpkocher.futuresdemo
import com.typesafe.scalalogging.LazyLogging
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success}
object FutureDemoUtils extends LazyLogging {
def myFunc(name: String): Future[String] = Future {
Thread.sleep(1500)
"stuff"
}
def myAdderOne(n: Int): Future[Int] = Future {
Thread.sleep(1000)
n + 1
}
def myDoubler(n: Int): Future[Int] = Future {
Thread.sleep(1200)
n * 2
}
def myDemoFunc(n: Int): Future[Int] = {
myAdderOne(n).flatMap { x =>
myDoubler(x)
}
}
// This will get translated to flatMap calls
def myForFunc(n: Int): Future[Int] = for {
x <- myAdderOne(n)
y <- myDoubler(x)
} yield y
// It's important that these are defined here and
// Not within the for comprehension
val f = Future {
3
}
val g = Future {
5
}
def exampleStuff(n: Int): Future[Int] = for {
x: Int <- f
y: Int <- g
} yield x + y * n
def callServiceA(n: Int): Future[Int] =
for {
// This will run
x: Int <- Future {
2 * n
}
// Then this run
y: Int <- Future {
3 * n
}
} yield x + y
def callServiceB(n: Int): Future[Int] = {
for {
z: Int <- Future {
n * 4
}
} yield z
}
def composeServiceCalls(n: Int): Future[Int] = {
for {
a: Int <- callServiceA(n)
b: Int <- callServiceB(a)
} yield a + b
}
// de-sugared equivalent of the composeServiceCalls example above
def composeServiceFlatMap(n: Int): Future[Int] = {
callServiceA(n).flatMap { x =>
callServiceB(x).map {z =>
z
}
}
}
case class TestResult(name: String)
case class Person(name: String, age: Int)
// Transforming And composing
// Person -> Int -> Float -> Person -> String
def toP(n: Int): Person = Person("a name", n)
def composeToPerson(n: Int): Future[Person] = {
for {
a: Int <- callServiceA(n)
b: Int <- callServiceB(a)
//c: Person <- toP(b)
} yield toP(b)
}
def testA(n: Person): TestResult = {
TestResult("test_a")
}
def testB(n: Int): TestResult = {
TestResult("test_b")
}
def testP(p1: Person, p2: Person) = TestResult("test_compare people")
def runOrchestration01(n: Int): Future[(Person, Seq[TestResult])] = {
for {
// These all need to manipulate Futures
a: Int <- callServiceA(n)
b: Int <- callServiceB(a)
person: Person <- Future { toP(b) }
} yield (person, Seq(testB(a), testB(b), testA(person)))
}
def runOrchestion02(n: Int, person: Person): Future[(Person, Seq[TestResult])] = {
for {
x <- runOrchestration01(n)
y <- callServiceB(4)
} yield (person, Seq(testP(x._1, person), testB(y)))
}
def runner(n: Int): Boolean = {
val fx = runOrchestration01(n)
fx onComplete { x =>
logger.info(s"Results from orchestration $x")
}
logger.info("completed runner.")
true
}
}
object FutureMain extends App with LazyLogging {
val myNumber = 12
val result = FutureDemoUtils.runner(myNumber)
import FutureDemoUtils._
val name = "Steve"
myFunc(name) onComplete {
case Success(s: String) => println(s"Message $name successful future to $s"); s"Hello $s"
case Failure(ex) => "Failed to "
}
println("Starting Demo 2 (raw flatmap composition)")
val m = 7
val n = myDemoFunc(m) onComplete {
case Success(x: Int) => x
case Failure(ex) => println(s"Failed future ${ex.getMessage}"); -1
}
println(s"Started with $m -> $n")
println("Starting Demo3 (for comprehension composition)")
val x = 6
val z = myForFunc(6)
// This is a Promise
z onComplete {
case Success(u) => println(s"Futures resolved to $u"); u
case Failure(ex) => println(s"Failed ${ex.getMessage}"); -1
}
// Sequence of Future Examples
val names = Seq("Steve", "Ralph", "Bird", "Cat", "Dog", "Giraffe")
val futures = names.map(x => myFunc(x))
// Create a new future
//val rs = Future collect futures
//val rs = Future sequence futures
val f2 = composeServiceCalls(4)
f2 onComplete {
case Success(r2) => println(s"Calling services $r2")
case Failure(ex) => println(s"Future failed.")
}
// Block and wait till
Await.result(z, 10 seconds)
Await.result(f2, 1 seconds)
println(s"Started with $x -> $z")
println("Exiting main.")
logger.info("Exiting main.")
println("Exiting main.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment